Atomic Operations (continuing on from Masking Interrupts?)
David Querbach
querbach@realtime.bc.ca
Tue Jul 6 13:36:00 GMT 1999
> The fix for this problem is to have a counter that increments on
> disable, and decrements on enable. The enable routine will only
> actually enable interrupts if the value of the counter is zero. We
> must make sure that the increment and decrement operations are also
> atomic; therefore, we must actually disable interrupts before the
> counter is incremented in assembler_routine_to_disable_interrupts(),
> and decrement before we disable interrupts in
> assembler_routine_to_enable_interrupts() (we realize, of course, that
> it is an error to call assembler_routine_to_enable_interrupts() when
> interrupts are not disabled!), and only actually enable interrupts in
> assembler_routine_to_enable_interrupts() is the counter goes to zero.
> The counter must be global in C, but should probably be class static
> in C++.
In our system, we have a target-dependent header file that defines four
macros:
- enableInts() unconditionally enables interrupts
- disableInts() unconditionally disables interrupts
- inhibitInts() saves the CPU's interrupt mask bit in an auto variable,
then invokes disableInts()
- restoreInts() sets the CPU's interrupt mask bit from the auto variable
written by inhibitInts().
For example, with the Hitachi Super-H processor, we use
#define enableInts() asm("stc sr,r3; and %0,r3; ldc r3,sr" : : "r" (__int_enable_mask__) : "r3" );
#define disableInts() asm("stc sr,r3; and %0,r3; or %1,r3; ldc r3,sr" : : "r" (0xFFFFFF0F), "r" (__int_disable_mask__) : "r3" );
#define inhibitInts() long sr; asm("stc sr,r3; mov.l r3,%0" : "=m" (sr) : : "r3"); disableInts();
#define restoreInts() asm("mov.l %0,r3; ldc r3,sr" : : "m" (sr) : "r3");
A typical entry point into an i/o driver then becomes:
scibuf::put(char c)
{
inhibitInts();
// fiddle with i/o, and so forth
restoreInts();
}
This method isn't perfect, but it does allow inhibiting interrupts deep in a
library without interfering with the application's interrupt enable/disable
status. Also, since we have such a file for each processor, interrupt mask
handling becomes portable.
Regards,
David Querbach
Real-Time Systems Inc.
_______________________________________________
New CrossGCC FAQ: http://www.objsw.com/CrossGCC
_______________________________________________
To remove yourself from the crossgcc list, send
mail to crossgcc-request@cygnus.com with the
text 'unsubscribe' (without the quotes) in the
body of the message.
More information about the crossgcc
mailing list