diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-08-23 16:15:50 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-08-30 11:16:28 +0200 |
commit | bf30999cc697325eda3afd1833b78a7e64255fc4 (patch) | |
tree | bc365daf0a3c0e6fe7c72cfe33c7603f7da54351 /cpukit | |
parent | sapi: SMP support for chains (diff) | |
download | rtems-bf30999cc697325eda3afd1833b78a7e64255fc4.tar.bz2 |
smp: Add and use _Assert_Owner_of_giant()
Add and use _ISR_Disable_without_giant() and
_ISR_Enable_without_giant() if RTEMS_SMP is defined.
On single processor systems the ISR disable/enable was the big hammer
which ensured system-wide mutual exclusion. On SMP configurations this
no longer works since other processors do not care about disabled
interrupts on this processor and continue to execute freely.
On SMP in addition to ISR disable/enable an SMP lock must be used.
Currently we have only the Giant lock so we can check easily that ISR
disable/enable is used only in the right context.
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/rtems/src/taskmode.c | 4 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/assert.h | 9 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/isr.h | 4 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/isrlevel.h | 20 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 4 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threaddispatch.h | 4 | ||||
-rw-r--r-- | cpukit/score/src/smp.c | 2 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatch.c | 4 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatchdisablelevel.c | 34 |
9 files changed, 64 insertions, 21 deletions
diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c index 606366b25f..8650ccc250 100644 --- a/cpukit/rtems/src/taskmode.c +++ b/cpukit/rtems/src/taskmode.c @@ -39,7 +39,7 @@ static void _RTEMS_Tasks_Dispatch_if_necessary( #if defined( RTEMS_SMP ) ISR_Level level; - _ISR_Disable( level ); + _ISR_Disable_without_giant( level ); #endif if ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) { @@ -48,7 +48,7 @@ static void _RTEMS_Tasks_Dispatch_if_necessary( } #if defined( RTEMS_SMP ) - _ISR_Enable( level ); + _ISR_Enable_without_giant( level ); #endif if ( dispatch_necessary ) { diff --git a/cpukit/score/include/rtems/score/assert.h b/cpukit/score/include/rtems/score/assert.h index 174676e0e3..4856eae8b4 100644 --- a/cpukit/score/include/rtems/score/assert.h +++ b/cpukit/score/include/rtems/score/assert.h @@ -50,6 +50,15 @@ extern "C" { #define _Assert_Thread_dispatching_repressed() ( ( void ) 0 ) #endif +/** + * @brief Asserts that current thread of execution owns the giant lock. + */ +#if defined( RTEMS_DEBUG ) && defined( RTEMS_SMP ) + void _Assert_Owner_of_giant( void ); +#else + #define _Assert_Owner_of_giant() ( ( void ) 0 ) +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/cpukit/score/include/rtems/score/isr.h b/cpukit/score/include/rtems/score/isr.h index 4d4a5f3c49..fa0052fdcb 100644 --- a/cpukit/score/include/rtems/score/isr.h +++ b/cpukit/score/include/rtems/score/isr.h @@ -163,13 +163,13 @@ RTEMS_INLINE_ROUTINE uint32_t _ISR_Get_nest_level( void ) #if defined( RTEMS_SMP ) ISR_Level level; - _ISR_Disable( level ); + _ISR_Disable_without_giant( level ); #endif isr_nest_level = _ISR_Nest_level; #if defined( RTEMS_SMP ) - _ISR_Enable( level ); + _ISR_Enable_without_giant( level ); #endif return isr_nest_level; diff --git a/cpukit/score/include/rtems/score/isrlevel.h b/cpukit/score/include/rtems/score/isrlevel.h index 35d3d037cc..3da67fd189 100644 --- a/cpukit/score/include/rtems/score/isrlevel.h +++ b/cpukit/score/include/rtems/score/isrlevel.h @@ -20,6 +20,7 @@ #define _RTEMS_SCORE_ISR_LEVEL_h #include <rtems/score/cpu.h> +#include <rtems/score/assert.h> #ifdef __cplusplus extern "C" { @@ -57,6 +58,7 @@ typedef uint32_t ISR_Level; #define _ISR_Disable( _level ) \ do { \ _CPU_ISR_Disable( _level ); \ + _Assert_Owner_of_giant(); \ RTEMS_COMPILER_MEMORY_BARRIER(); \ } while (0) @@ -74,6 +76,7 @@ typedef uint32_t ISR_Level; #define _ISR_Enable( _level ) \ do { \ RTEMS_COMPILER_MEMORY_BARRIER(); \ + _Assert_Owner_of_giant(); \ _CPU_ISR_Enable( _level ); \ } while (0) @@ -99,6 +102,7 @@ typedef uint32_t ISR_Level; #define _ISR_Flash( _level ) \ do { \ RTEMS_COMPILER_MEMORY_BARRIER(); \ + _Assert_Owner_of_giant(); \ _CPU_ISR_Flash( _level ); \ RTEMS_COMPILER_MEMORY_BARRIER(); \ } while (0) @@ -132,6 +136,22 @@ typedef uint32_t ISR_Level; RTEMS_COMPILER_MEMORY_BARRIER(); \ } while (0) +#if defined( RTEMS_SMP ) + +#define _ISR_Disable_without_giant( _level ) \ + do { \ + _CPU_ISR_Disable( _level ); \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + } while (0) + +#define _ISR_Enable_without_giant( _level ) \ + do { \ + RTEMS_COMPILER_MEMORY_BARRIER(); \ + _CPU_ISR_Enable( _level ); \ + } while (0) + +#endif /* defined( RTEMS_SMP ) */ + /**@}*/ #ifdef __cplusplus diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 77f1d7a2d2..33b5244ac7 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -495,13 +495,13 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Get_executing( void ) #if defined( RTEMS_SMP ) ISR_Level level; - _ISR_Disable( level ); + _ISR_Disable_without_giant( level ); #endif executing = _Thread_Executing; #if defined( RTEMS_SMP ) - _ISR_Enable( level ); + _ISR_Enable_without_giant( level ); #endif return executing; diff --git a/cpukit/score/include/rtems/score/threaddispatch.h b/cpukit/score/include/rtems/score/threaddispatch.h index 9cd12873fb..2211662696 100644 --- a/cpukit/score/include/rtems/score/threaddispatch.h +++ b/cpukit/score/include/rtems/score/threaddispatch.h @@ -54,13 +54,13 @@ RTEMS_INLINE_ROUTINE bool _Thread_Dispatch_is_enabled(void) #if defined(RTEMS_SMP) ISR_Level level; - _ISR_Disable( level ); + _ISR_Disable_without_giant( level ); #endif enabled = _Thread_Dispatch_disable_level == 0; #if defined(RTEMS_SMP) - _ISR_Enable( level ); + _ISR_Enable_without_giant( level ); #endif return enabled; diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c index 6020b94c46..2f8a488474 100644 --- a/cpukit/score/src/smp.c +++ b/cpukit/score/src/smp.c @@ -75,7 +75,7 @@ void rtems_smp_process_interrupt( void ) #endif if ( ( message & RTEMS_BSP_SMP_SHUTDOWN ) != 0 ) { - _ISR_Disable( level ); + _ISR_Disable_without_giant( level ); _Thread_Dispatch_set_disable_level( 0 ); diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c index 3b5fb429cf..0c8298f15f 100644 --- a/cpukit/score/src/threaddispatch.c +++ b/cpukit/score/src/threaddispatch.c @@ -35,7 +35,7 @@ void _Thread_Dispatch( void ) ISR_Level level; #if defined( RTEMS_SMP ) - _ISR_Disable( level ); + _ISR_Disable_without_giant( level ); #endif per_cpu = _Per_CPU_Get(); @@ -43,7 +43,7 @@ void _Thread_Dispatch( void ) per_cpu->thread_dispatch_disable_level = 1; #if defined( RTEMS_SMP ) - _ISR_Enable( level ); + _ISR_Enable_without_giant( level ); #endif /* diff --git a/cpukit/score/src/threaddispatchdisablelevel.c b/cpukit/score/src/threaddispatchdisablelevel.c index 30755349b2..a3dec9998c 100644 --- a/cpukit/score/src/threaddispatchdisablelevel.c +++ b/cpukit/score/src/threaddispatchdisablelevel.c @@ -17,6 +17,7 @@ #include <rtems/score/threaddispatch.h> #include <rtems/score/assert.h> +#include <rtems/score/sysstate.h> #define NO_OWNER_CPU 0xffffffffU @@ -63,7 +64,7 @@ uint32_t _Thread_Dispatch_increment_disable_level( void ) uint32_t disable_level; Per_CPU_Control *self_cpu; - _ISR_Disable( isr_level ); + _ISR_Disable_without_giant( isr_level ); /* * We must obtain the processor ID after interrupts are disabled to prevent @@ -78,7 +79,7 @@ uint32_t _Thread_Dispatch_increment_disable_level( void ) ++disable_level; self_cpu->thread_dispatch_disable_level = disable_level; - _ISR_Enable( isr_level ); + _ISR_Enable_without_giant( isr_level ); return disable_level; } @@ -89,7 +90,7 @@ uint32_t _Thread_Dispatch_decrement_disable_level( void ) uint32_t disable_level; Per_CPU_Control *self_cpu; - _ISR_Disable( isr_level ); + _ISR_Disable_without_giant( isr_level ); self_cpu = _Per_CPU_Get(); disable_level = self_cpu->thread_dispatch_disable_level; @@ -97,8 +98,9 @@ uint32_t _Thread_Dispatch_decrement_disable_level( void ) self_cpu->thread_dispatch_disable_level = disable_level; _Giant_Do_release(); + _Assert( disable_level != 0 || _Giant.owner_cpu == NO_OWNER_CPU ); - _ISR_Enable( isr_level ); + _ISR_Enable_without_giant( isr_level ); return disable_level; } @@ -118,9 +120,9 @@ uint32_t _Thread_Dispatch_set_disable_level(uint32_t value) ISR_Level isr_level; uint32_t disable_level; - _ISR_Disable( isr_level ); + _ISR_Disable_without_giant( isr_level ); disable_level = _Thread_Dispatch_disable_level; - _ISR_Enable( isr_level ); + _ISR_Enable_without_giant( isr_level ); /* * If we need the dispatch level to go higher @@ -147,18 +149,30 @@ void _Giant_Acquire( void ) { ISR_Level isr_level; - _ISR_Disable( isr_level ); + _ISR_Disable_without_giant( isr_level ); _Assert( _Thread_Dispatch_disable_level != 0 ); _Giant_Do_acquire( _SMP_Get_current_processor() ); - _ISR_Enable( isr_level ); + _ISR_Enable_without_giant( isr_level ); } void _Giant_Release( void ) { ISR_Level isr_level; - _ISR_Disable( isr_level ); + _ISR_Disable_without_giant( isr_level ); _Assert( _Thread_Dispatch_disable_level != 0 ); _Giant_Do_release(); - _ISR_Enable( isr_level ); + _ISR_Enable_without_giant( isr_level ); } + +#if defined( RTEMS_DEBUG ) +void _Assert_Owner_of_giant( void ) +{ + Giant_Control *giant = &_Giant; + + _Assert( + giant->owner_cpu == _SMP_Get_current_processor() + || !_System_state_Is_up( _System_state_Get() ) + ); +} +#endif |