galew_a@peyote.cactus.org (Andy Galewsky) (12/07/90)
We are trying to get Isis to run on a 386 sysv machine. Everything compiles cleanly but We can't seem to get the task switching to work. Has anybody out there gotten Isis to work on a 386 and would they be able to help us??? Thanks-in-advance --------------------------------------- Andy Galewsky Clinical Resource Systems, Inc. US Mail: 1111 West 6th St., Suite C230 Austin, TX 78703 Email: {...}cs.utexas.edu!peyote!sneffels!andy Phone: (512) 478-1792 Fax: (512) 478-4644
ken@gvax.cs.cornell.edu (Ken Birman) (12/08/90)
In article <3844@peyote.cactus.org> galew_a@peyote.cactus.org (Andy Galewsky) writes: >We are trying to get Isis to run on a 386 sysv machine. Everything >compiles cleanly but We can't seem to get the task switching to >work.... If you have gotten this far, it should be pretty easy. I assume you are following the document "v21.ports" and have only been working on clib and that you are trying to run testtasks.c, a stand-alone test program. I also assume you have NOT defined THREADS and that you have defined JB_SP (or this is defined in <jmpbuf.h>) and that isis_setjmp just calls _setjmp and that isis_longjmp calls _longjmp. This program forks off a series of tasks that each print a message and then block. The sequence is: 1) initial task calls swtch, which saves the state 2) swtch allocates new task region and stack 3) swtch computes a new stack pointer 4) a] swtch calls isis_setjmp to note the current context b] changes the stack pointer to the new one c] calls isis_longjmp to re-load everything causing the new stack to be loaded but the other registers to stay the same d] calls "invoke" 5) invoke calls the routine, which prints a message like "*** Task 0 " followed by a bunch of register values. (try program on a SUN; output on 386 should be the same) 6) routine decides to block, calls swtch 7) swtch saves state of caller 8) swtch does a longjmp into destination context Notes: isis_longjmp and invoke() are assumed never to return. Debugging: You need to deal with this in stages. [1] create of new stack -> first message by new task [2] switching from live task to live task [3] register corruption issues For [1], typical bugs are: a) Didn't use a meaningful value for JB_SP, hence didn't set the stack pointer to anything sensible. b) Didn't start by learning how a stack is supposed to look on the 386 hence didn't realize that the stack pointer needs special alignment or that some other frame register must also be changed or that a "hole" must be present under the stack pointer for the active register window, etc. (These are all features of some machine or other, but no machine necessarily has any or all of these). c) _longjmp didn't want to do the jump and returned an error code, which ISIS didn't check for and hence didn't detect. To catch 1.a or 1.b, you would have to consult your 386 manual or at least look at C compiler output (cc -S for some program with a procedure with some arguments, stare at output until it makes sense). To catch 1.c, try #define isis_longjmp(x) if(_longjmp(x)) panic("_longjmp returned!") ... if you get the panic, _longjmp is causing problems. In this case, you have no choice but to modify _longjmp to eliminate the error check that causes it to return. The situation here is that ISIS is jumping from stack to stack, not "up" the system stack. An overly cautious longjmp might be noticing this and returning an error code rather than jumping. ISIS likes the type of longjmp that just closes its eyes and jumps. To correct this problem, get assembler source for _longjmp (and perhaps _setjmp), i.e. using dbx or adb to show instructions. Remove any error checks and call the result isis_longjmp; put code in cl_setjmp.s, try again. For [2] you will mostly be concerned with case 1.c and can catch it the same way. However, if you get JB_SP wrong or neglect to set up some other critical register, you may also these problems during the first switch The third case is rare and occurs only if _setjmp/_longjmp don't save all the registers. For example, if you use GCC (which uses registers heavily) combined with a C library for some other version of CC that doesn't use certain registers, ever, you could see output from testtasks in which certain registers are visibly not being saved and restored. You need to recode _setjmp/_longjmp in such cases to save all registers, but this is very rare lately (was more common right after GCC was introduced). Hope this helps! Ken