[comp.sys.ibm.pc] MSC 5.0 Local Stacks -- more obscure details

mac3n@babbage.acc.virginia.edu (Alex Colvin) (05/16/88)

In article <5356@cup.portal.com>, Devin_E_Ben-Hur@cup.portal.com writes:
> James H King posts some stack-swapping routines for MS-C:

>   The problem here is that there's no protection against interrupts
> comming in between the setting of SS and SP (ie. there's a new SS but
> the old SP, so the stack used by the interrupt will be bogus).

Note that iff you are executing this stuff out of an interrupt handler,
interrupts are disabled.  The safe thing to do is to swap stacks,
then enable interrupts, then serve the interrupt, then re-disable,
then swap stacks back, then return from the interrupt handler.

>   On some truely ancient 8088 chip masks, there was a bug which
> didn't lock interrupts after setting SS, so to be 100% safe one
> should surround the previous critical stack-switching instructions
> with CLI and STI to disable and enable interrupts:

Note above that this is not needed from the interrupt handler.

It's almost never right to issue a CLI or STI without reading the IFLAG first.
You generally want to read the IFLAG, do your CLI, do your critical code,
then RESTORE the IFLAG the way it was.

In the case of an interrupt handler, doing a CLI is a no-op. Doing the STI
can be disasterous if there are other critical resources.

I generally rely on the stat of the IFLAG (in my stack swap routine)
or use a routine.
It's written in TCC (not the interactive compiler!), but it's really in
assembler.  TCC just compiler the correct memory model for me.

------



/************************************************************************/
/*                      (c) Copyright 1986,1987,1988                    */
/*	by the Rector and Visitors of the University of Virginia	*/
/************************************************************************/

/*
 * read & set the interrupt enable flag
 * this should be used so that an inhibited region restores the state
 * the flag is represented by an integer, 0==disable 1 == enable
 */

#pragma inline

int
intrflag(int set)
  { asm pushf;                  /* get the flags register */
    asm pop AX;                 /* where we can see */
    asm cli;                    /* disable */
    if (set)
      asm sti;                  /* enable if set */
    return _AX&0x0200;          /* return old I flag */
    }