This is the mail archive of the crossgcc@cygnus.com mailing list for the crossgcc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Atomic Operations (continuing on from Masking Interrupts?)


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]