ken@gvax.cs.cornell.edu (Ken Birman) (03/13/90)
If you use ISISV1.3.1 on a Sparcstation you may have been tempted to disable SUNLWP by my recent mail pointing out that the ISIS native tasks are much faster and give smaller object codes. We just identified a bug in this situation, however, and you should patch clib/cl_setjmp.s and protos/pr_setjmp.s if you want to run ISIS this way. V2.0 fixes this bug, so you can also wait for the next release. The following is the corrected code; it is shorted and "correct". ENTRY(isis_setjmp) t ST_FLUSH_WINDOWS ! (won't be needed here in V2.0) st %o7, [%o0 + PCVAL] ! return pc st %sp, [%o0 + SPVAL] ! save caller's sp retl clr %o0 ! return zero ENTRY(isis_longjmp) t ST_FLUSH_WINDOWS ! flush all reg windows to the stack. sub %sp, WINDOWSIZE, %sp ! establish new save area (paranoid) ld [%o0 + SPVAL], %fp ! build new stack frame ld [%o0 + PCVAL], %o7 ! get new return pc retl restore %o1, 0, %o0 ! return (val) The logic is as follows: setjmp merely records the caller's frame; this will be used to force a register restore when doing a long-jump. It also notes the return address to jump to. No need to do anything else. Returns 0 in this case. The T_FLUSH_WINDOWS is actually not needed in most calls to setjmp; the only time we really need to do this in a call to setjmp is immediately prior to loading the new stack pointer value in cl_task.c or pr_task.c. Since many calls to swtch() switch tasks without creating a new one, in V2.0 we have eliminated the extra (costly!) trap in setjmp and move it to the asm sequence in pr_task.c. You can do this too if you like. Put a line asm("t 0x3"); right before the asm("sethi _stackp,%o0"); asm("ld [%o0+_stackp],%sp") sequence. 0x3 is the code for T_FLUSH_WINDOWS. Longjmp is the tricky case. First, it flushes the callers registers to the stack. Then, it makes room for a frame that can be used if the kernel fields an interrupt just after we load the destination framepointer but before the restore is executed that forces the underflow trap and loads in the destination registers. With this new frame in place, we can safely muck with the %i registers (in particular, loading the new %fp value, which will become the new %sp value after the restore) and the return address we want (%o7 gets this). We do a retl-restore sequence even though there was no prior save because we have artificially constructed a frame as if save had been used at the entry. Thanks to Steve Kleiman at SUN for helping us understand how to do this correctly.