Man Linux: Main Page and Category List

NAME

       <util/atomic.h> Atomically and Non-Atomically Executed Code Blocks -

   Defines
       #define ATOMIC_BLOCK(type)
       #define NONATOMIC_BLOCK(type)
       #define ATOMIC_RESTORESTATE
       #define ATOMIC_FORCEON
       #define NONATOMIC_RESTORESTATE
       #define NONATOMIC_FORCEOFF

Detailed Description

           #include <util/atomic.h>

       Note:
           The macros in this header file require the ISO/IEC 9899:1999 ('ISO
           C99') feature of for loop variables that are declared inside the
           for loop itself. For that reason, this header file can only be used
           if the standard level of the compiler (option --std=) is set to
           either c99 or gnu99.

       The macros in this header file deal with code blocks that are
       guaranteed to be excuted Atomically or Non-Atmomically. The term
       'Atomic' in this context refers to the unability of the respective code
       to be interrupted.

       These macros operate via automatic manipulation of the Global Interrupt
       Status (I) bit of the SREG register. Exit paths from both block types
       are all managed automatically without the need for special
       considerations, i. e. the interrupt status will be restored to the same
       value it has been when entering the respective block.

       A typical example that requires atomic access is a 16 (or more) bit
       variable that is shared between the main execution path and an ISR.
       While declaring such a variable as volatile ensures that the compiler
       will not optimize accesses to it away, it does not guarantee atomic
       access to it. Assuming the following example:

       #include <inttypes.h>
       #include <avr/interrupt.h>
       #include <avr/io.h>

       volatile uint16_t ctr;

       ISR(TIMER1_OVF_vect)
       {
         ctr--;
       }

       int
       main(void)
       {
          ...
          ctr = 0x200;
          start_timer();
          while (ctr != 0)
            // wait
              ;
          ...
       }

       There is a chance where the main context will exit its wait loop when
       the variable ctr just reached the value 0xFF. This happens because the
       compiler cannot natively access a 16-bit variable atomically in an
       8-bit CPU. So the variable is for example at 0x100, the compiler then
       tests the low byte for 0, which succeeds. It then proceeds to test the
       high byte, but that moment the ISR triggers, and the main context is
       interrupted. The ISR will decrement the variable from 0x100 to 0xFF,
       and the main context proceeds. It now tests the high byte of the
       variable which is (now) also 0, so it concludes the variable has
       reached 0, and terminates the loop.

       Using the macros from this header file, the above code can be rewritten
       like:

       #include <inttypes.h>
       #include <avr/interrupt.h>
       #include <avr/io.h>
       #include <util/atomic.h>

       volatile uint16_t ctr;

       ISR(TIMER1_OVF_vect)
       {
         ctr--;
       }

       int
       main(void)
       {
          ...
          ctr = 0x200;
          start_timer();
          sei();
          uint16_t ctr_copy;
          do
          {
            ATOMIC_BLOCK(ATOMIC_FORCEON)
            {
              ctr_copy = ctr;
            }
          }
          while (ctr_copy != 0);
          ...
       }

       This will install the appropriate interrupt protection before accessing
       variable ctr, so it is guaranteed to be consistently tested. If the
       global interrupt state were uncertain before entering the ATOMIC_BLOCK,
       it should be executed with the parameter ATOMIC_RESTORESTATE rather
       than ATOMIC_FORCEON.

Define Documentation

   #define ATOMIC_BLOCK(type) Creates a block of code that is guaranteed to be
       executed atomically. Upon entering the block the Global Interrupt
       Status flag in SREG is disabled, and re-enabled upon exiting the block
       from any exit path.
       Two possible macro parameters are permitted, ATOMIC_RESTORESTATE and
       ATOMIC_FORCEON.

   #define ATOMIC_FORCEON This is a possible parameter for ATOMIC_BLOCK. When
       used, it will cause the ATOMIC_BLOCK to force the state of the SREG
       register on exit, enabling the Global Interrupt Status flag bit. This
       saves on flash space as the previous value of the SREG register does
       not need to be saved at the start of the block.
       Care should be taken that ATOMIC_FORCEON is only used when it is known
       that interrupts are enabled before the block's execution or when the
       side effects of enabling global interrupts at the block's completion
       are known and understood.

   #define ATOMIC_RESTORESTATE This is a possible parameter for ATOMIC_BLOCK.
       When used, it will cause the ATOMIC_BLOCK to restore the previous state
       of the SREG register, saved before the Global Interrupt Status flag bit
       was disabled. The net effect of this is to make the ATOMIC_BLOCK's
       contents guaranteed atomic, without changing the state of the Global
       Interrupt Status flag when execution of the block completes.
   #define NONATOMIC_BLOCK(type) Creates a block of code that is executed non-
       atomically. Upon entering the block the Global Interrupt Status flag in
       SREG is enabled, and disabled upon exiting the block from any exit
       path. This is useful when nested inside ATOMIC_BLOCK sections, allowing
       for non-atomic execution of small blocks of code while maintaining the
       atomic access of the other sections of the parent ATOMIC_BLOCK.
       Two possible macro parameters are permitted, NONATOMIC_RESTORESTATE and
       NONATOMIC_FORCEOFF.

   #define NONATOMIC_FORCEOFF This is a possible parameter for
       NONATOMIC_BLOCK. When used, it will cause the NONATOMIC_BLOCK to force
       the state of the SREG register on exit, disabling the Global Interrupt
       Status flag bit. This saves on flash space as the previous value of the
       SREG register does not need to be saved at the start of the block.
       Care should be taken that NONATOMIC_FORCEOFF is only used when it is
       known that interrupts are disabled before the block's execution or when
       the side effects of disabling global interrupts at the block's
       completion are known and understood.

   #define NONATOMIC_RESTORESTATE This is a possible parameter for
       NONATOMIC_BLOCK. When used, it will cause the NONATOMIC_BLOCK to
       restore the previous state of the SREG register, saved before the
       Global Interrupt Status flag bit was enabled. The net effect of this is
       to make the NONATOMIC_BLOCK's contents guaranteed non-atomic, without
       changing the state of the Global Interrupt Status flag when execution
       of the block completes.

Author

       Generated automatically by Doxygen for avr-libc from the source code.

Version 1<util/atomic.h> Atomically and Non-Atomically Executed Code Blocks(3)