Atomic Operations (continuing on from Masking Interrupts?)

David Querbach
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

  - 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)

    // fiddle with i/o, and so forth


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.


David Querbach
Real-Time Systems Inc.

New CrossGCC FAQ:
To remove yourself from the crossgcc list, send
mail to with the
text 'unsubscribe' (without the quotes) in the
body of the message.

More information about the crossgcc mailing list