[comp.sys.sequent] writing context-switching code for a Sequent Symmetry under DYNIX

svp@csgrad.cs.vt.edu (Joel Patterson) (12/20/90)

I am trying to write context-switching code for a Symmetry under DYNIX.  
I need to have a frame pointer register for use with the stack (similar
to the frame pointer register in a 68000).  I think I should be able to
use the BP register, but I am not sure.  Can anyone help me on this?  The
Symmetry uses an 80386.

Thanks,
	Joel



--

Joel Patterson   	                          UUCP: svp@csgrad.UUCP
804-421-9398					  INET: svp@csgrad.cs.vt.edu

rbj@uunet.UU.NET (Root Boy Jim) (12/20/90)

In article <776@creatures.cs.vt.edu> svp@csgrad.cs.vt.edu (Joel Patterson) writes:
? I am trying to write context-switching code for a Symmetry under DYNIX.  
? I need to have a frame pointer register for use with the stack (similar
? to the frame pointer register in a 68000).  I think I should be able to
? use the BP register, but I am not sure.  Can anyone help me on this?  The
? Symmetry uses an 80386.

? Joel Patterson   	                          UUCP: svp@csgrad.UUCP
? 804-421-9398					  INET: svp@csgrad.cs.vt.edu

That's what Sequent does. I think that's the most common choice. 
A cc -S command will tell you all you need to know.
-- 

	Root Boy Jim Cottrell <rbj@uunet.uu.net>
	Close the gap of the dark year in between

bakken@cs.arizona.edu (Dave Bakken) (12/22/90)

In article <776@creatures.cs.vt.edu> svp@csgrad.cs.vt.edu (Joel Patterson) writes:
>I am trying to write context-switching code for a Symmetry under DYNIX.  
>I need to have a frame pointer register for use with the stack (similar
>to the frame pointer register in a 68000).  I think I should be able to
>use the BP register, but I am not sure.  Can anyone help me on this?  The
>Symmetry uses an 80386.
>
>Thanks,
>	Joel

I don't rightly remember what the scoop is on that.  But I had to write
a context switching package for the '386 for our Sequent to port
our distributed programming language, Synchronizing Resources (SR),
to it.  I remember that the Sequent docs were pretty skimpy on the
calling convention details that I needed, so I used my friend "cc -S"
a lot.

But following are the '386-specific routines that I came up with.  They
have been tested with real users for almost a year, so they are stable.
The top of the ``stack area'' is used for a register save area, and then
the stack grows from the bottom of the stack area.  A magic cookie is
put on the stack  and it servers as a sanity check we call often (if
the cookie isn't there you've used too much stack and overwritten it.
This is not guaranteed to work always but often does and is cheap.).
To use the below functions, you call sr_build_context(code_ptr, stack, ...)
and then sr_chg_context(stack).  Note that sr_chg_context is called
voluntarily by the generated code (the SR compiler spits out C...)
so it only saves registers that are assumed to survive across
function calls.  Thus, it would probably be inappropriate for an 
interrupt/signal-driven context switch.

Enjoy,

Dave Bakken
bakken@cs.arizona.edu

P.S. SR is available via anonymous ftp from cs.arizona.edu for free
and via tar tape for a modest charge.  Send me email if you'd like
more information about it (it runs on Suns, VAXen, Encore, and a bunch
others besides Sequent).
======== snip ========== snip, snip =========== snippety-snip ======
/*  i386.s - intel 80386 context switching code for Sequent Symmetry
 *
 *  (This should work also for other Intel 80386 machines if they use the same
 *   calling sequences and register conventions.)
 *
 *  A context array is laid out like this:
 *
 *	saved registers (%ebp, %ebx, %esi, %edi)
 *  	magic word for checking integrity
 *	unused stack space
 *	saved %esp			<--- saved ebp points here
 *	saved pc (return address)
 *	error routine addr (if code returns, which is an error, it will go here)
 *	arguments from sr_build_context call
 *
 *  Registers %ebp, %ebx, %esi, and %edi are saved at the base of the array.
 *  %eax, %ecx, and %edx aren't saved because C doesn't expect them to survive
 *  over function calls.  %esp is saved on the stack at subroutine entry.
 */

#define MAGIC 79797979 		/* any unlikely long integer */
#define RSIZE 16		/* size of register save area */



	.data
	.align 2

dummy_stack: 			/* fake initial context */
	.long	0  		/* 00 offset - %ebp */
	.long	0  		/* 04 offset - %ebx */
	.long	0  		/* 08 offset - %esi*/
	.long 	0  		/* 12 offset - %edi */
	.long	MAGIC   	/* 16 offset - magic word for sanity check */

curr_stack:			/* saves addr of current context (stack) */
	.long	dummy_stack

	.text
	.align 2



/*  sr_build_context(code,buf,bufsize,a1,a2,a3,a4) -- create a new context.
 *
 *  code	 entry point of the code to be executed in the context
 *  buf		 buffer for holding the context array
 *  bufsize	 size of the buffer
 *  a1 - a4	 four int-sized arguments to be passed to the code
 */

	.globl	_sr_build_context

_sr_build_context:
	pushl	%ebp 		/* save caller's frame pointer */
	movl	%esp,%ebp	/* save caller's stack pointer */

	movl	12(%ebp), %eax	/* %eax = pointer to context array */
	movl	%eax, %esp
	addl	16(%ebp), %esp	/* point stack to end of context array */

	pushl	32(%ebp)	/* push arg4 */
	pushl	28(%ebp)	/* push arg3 */
	pushl	24(%ebp)	/* push arg2 */
	pushl	20(%ebp)	/* push arg1 */
	pushl	$under		/* push error addr in case context returns */
	pushl	8(%ebp)		/* push address for startind execution */
	pushl	$0		/* push dummy frame pointer */

	movl	%esp, (%eax)	/* set initial frame pointer*/
	movl	$MAGIC, RSIZE(%eax)  /* store magic word for integrity check */

	leave			/* restore stack and frame pointers */
	ret			/* return */



/*  sr_chg_context(newstack) -- switch context to the specified stack  */

	.globl	_sr_chg_context
_sr_chg_context:
	pushl	%ebp		/* save old frame pointer */
	movl	%esp,%ebp	/* save old stack pointer in frame pointer */

	movl	curr_stack,%eax	/* load address of current context stack */
	movl	%ebp,  0(%eax)	/* save registers in user context block */
	movl	%ebx,  4(%eax)
	movl	%esi,  8(%eax)
	movl	%edi, 12(%eax)

	addl	$RSIZE,%eax
	cmpl	%eax,%esp	/* check that stack isn't overflowing */
	jle	over
	cmpl	$MAGIC,(%eax)	/* catch earlier overflow (maybe) */
	jne	over

	movl	8(%ebp), %eax	/* load address of new context */
	cmpl	$MAGIC, RSIZE(%eax)	/* make sure new stack looks okay */
	jne	bad

	movl	%eax, curr_stack /* save address of new context */
	movl	 0(%eax), %ebp	/* load registers for new context */
	movl	 4(%eax), %ebx
	movl	 8(%eax), %esi
	movl	12(%eax), %edi

	leave			/* restore %esp and %ebp */
	ret			/* return into new context */



/*  sr_check_stk() -- check that the stack is not overflowing  */

	.globl	_sr_check_stk
_sr_check_stk:
	movl	curr_stack, %eax
	addl	$RSIZE, %eax
	cmpl	%eax, %esp
	jle	over
	ret



/*  stack problem handlers  (these calls do not return)  */

over:	call	_sr_stk_overflow
under:	call	_sr_stk_underflow
bad:	call	_sr_stk_corrupted
======== snip ========== snip, snip =========== snippety-snip ======
--
Dave Bakken, bakken@cs.arizona.edu, uunet!arizona!bakken, +1 602 621 4976

``I am Iraq, I am an island.  
  And Iraq feels no pain.  And an island never cries.''  Paul Simon (sort of)