[comp.sys.isis] Isis on the 386

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