Improve ATOMIC_BARRIER documentation

This commit is contained in:
Petr Ledvina 2016-12-30 12:57:34 +01:00 committed by borisbstyle
parent 5b11326eb1
commit 2171d0115a
1 changed files with 10 additions and 10 deletions

View File

@ -69,25 +69,25 @@ static inline uint8_t __basepriSetRetVal(uint8_t prio)
#define ATOMIC_BLOCK(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestoreMem))) = __get_BASEPRI(), \ #define ATOMIC_BLOCK(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestoreMem))) = __get_BASEPRI(), \
__ToDo = __basepriSetMemRetVal(prio); __ToDo ; __ToDo = 0 ) __ToDo = __basepriSetMemRetVal(prio); __ToDo ; __ToDo = 0 )
// Run block with elevated BASEPRI (using BASEPRI_MAX), but do not create any (explicit) memory barrier. // Run block with elevated BASEPRI (using BASEPRI_MAX), but do not create memory barrier.
// Be carefull when using this, you must use some method to prevent optimizer form breaking things // Be careful when using this, you must use some method to prevent optimizer form breaking things
// - lto is used for baseflight compillation, so function call is not memory barrier // - lto is used for Cleanflight compilation, so function call is not memory barrier
// - use ATOMIC_BARRIER or propper volatile to protect used variables // - use ATOMIC_BARRIER or volatile to protect used variables
// - gcc 4.8.4 does write all values in registes to memory before 'asm volatile', so this optimization does not help much // - gcc 4.8.4 does write all values in registers to memory before 'asm volatile', so this optimization does not help much
// but that can change in future versions // - gcc 5 and later works as intended, generating quite optimal code
#define ATOMIC_BLOCK_NB(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestore))) = __get_BASEPRI(), \ #define ATOMIC_BLOCK_NB(prio) for ( uint8_t __basepri_save __attribute__((__cleanup__(__basepriRestore))) = __get_BASEPRI(), \
__ToDo = __basepriSetRetVal(prio); __ToDo ; __ToDo = 0 ) \ __ToDo = __basepriSetRetVal(prio); __ToDo ; __ToDo = 0 ) \
// ATOMIC_BARRIER // ATOMIC_BARRIER
// Create memory barrier // Create memory barrier
// - at the beginning (all data must be reread from memory) // - at the beginning of containing block (value of parameter must be reread from memory)
// - at exit of block (all exit paths) (all data must be written, but may be cached in register for subsequent use) // - at exit of block (all exit paths) (parameter value if written into memory, but may be cached in register for subsequent use)
// ideally this would only protect memory passed as parameter (any type should work), but gcc is curently creating almost full barrier // On gcc 5 and higher, this protects only memory passed as parameter (any type should work)
// this macro can be used only ONCE PER LINE, but multiple uses per block are fine // this macro can be used only ONCE PER LINE, but multiple uses per block are fine
#if (__GNUC__ > 6) #if (__GNUC__ > 6)
#warning "Please verify that ATOMIC_BARRIER works as intended" #warning "Please verify that ATOMIC_BARRIER works as intended"
// increment version number is BARRIER works // increment version number if BARRIER works
// TODO - use flag to disable ATOMIC_BARRIER and use full barrier instead // TODO - use flag to disable ATOMIC_BARRIER and use full barrier instead
// you should check that local variable scope with cleanup spans entire block // you should check that local variable scope with cleanup spans entire block
#endif #endif