diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-03-27 13:38:04 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-03-31 08:29:43 +0200 |
commit | 346845730cb7cdd3f2a1e9231cced7cdfd046ce1 (patch) | |
tree | 3764fe70bfaea1d230d5052982b3bff6b1322e13 | |
parent | score: Relax Giant lock usage for API mutexes (diff) | |
download | rtems-346845730cb7cdd3f2a1e9231cced7cdfd046ce1.tar.bz2 |
score: Use thread life protection for API mutexes
This prevents that asynchronous thread deletion can lead to an unusable
allocator or once mutex.
-rw-r--r-- | cpukit/score/include/rtems/score/apimutex.h | 42 | ||||
-rw-r--r-- | cpukit/score/src/apimutexlock.c | 14 | ||||
-rw-r--r-- | cpukit/score/src/apimutexunlock.c | 26 |
3 files changed, 46 insertions, 36 deletions
diff --git a/cpukit/score/include/rtems/score/apimutex.h b/cpukit/score/include/rtems/score/apimutex.h index 380f054181..5f02e0a1cf 100644 --- a/cpukit/score/include/rtems/score/apimutex.h +++ b/cpukit/score/include/rtems/score/apimutex.h @@ -47,6 +47,12 @@ typedef struct { * Contains the SuperCore mutex information. */ CORE_mutex_Control Mutex; + + /** + * @brief The thread life protection state before the outer-most mutex + * obtain. + */ + bool previous_thread_life_protection; } API_Mutex_Control; /** @@ -66,18 +72,16 @@ void _API_Mutex_Initialization( uint32_t maximum_mutexes ); void _API_Mutex_Allocate( API_Mutex_Control **mutex ); /** - * @brief Acquires the specified API mutex. + * @brief Acquires the specified API mutex. + * + * @param[in] mutex The API mutex. */ -void _API_Mutex_Lock( - API_Mutex_Control *mutex - ); +void _API_Mutex_Lock( API_Mutex_Control *mutex ); /** - * @brief Releases the specified API mutex. + * @brief Releases the specified API mutex. * - * Releases the specified @a mutex. - * - * @param[in] mutex is the mutex to be removed. + * @param[in] mutex The API mutex. */ void _API_Mutex_Unlock( API_Mutex_Control *mutex ); @@ -104,21 +108,15 @@ void _API_Mutex_Unlock( API_Mutex_Control *mutex ); */ SCORE_EXTERN API_Mutex_Control *_RTEMS_Allocator_Mutex; -/** - * @brief Macro to ease locking the allocator mutex. - * - * This macro makes it explicit that one is locking the allocator mutex. - */ -#define _RTEMS_Lock_allocator() \ - _API_Mutex_Lock( _RTEMS_Allocator_Mutex ) +static inline void _RTEMS_Lock_allocator( void ) +{ + _API_Mutex_Lock( _RTEMS_Allocator_Mutex ); +} -/** - * @brief Macro to ease unlocking the allocator mutex. - * - * This macro makes it explicit that one is unlocking the allocator mutex. - */ -#define _RTEMS_Unlock_allocator() \ - _API_Mutex_Unlock( _RTEMS_Allocator_Mutex ) +static inline void _RTEMS_Unlock_allocator( void ) +{ + _API_Mutex_Unlock( _RTEMS_Allocator_Mutex ); +} SCORE_EXTERN API_Mutex_Control *_Once_Mutex; diff --git a/cpukit/score/src/apimutexlock.c b/cpukit/score/src/apimutexlock.c index d943bddf5d..07e5159987 100644 --- a/cpukit/score/src/apimutexlock.c +++ b/cpukit/score/src/apimutexlock.c @@ -19,16 +19,17 @@ #include "config.h" #endif -#include <rtems/system.h> #include <rtems/score/apimutex.h> #include <rtems/score/coremuteximpl.h> +#include <rtems/score/threadimpl.h> -void _API_Mutex_Lock( - API_Mutex_Control *the_mutex -) +void _API_Mutex_Lock( API_Mutex_Control *the_mutex ) { + bool previous_thread_life_protection; ISR_Level level; + previous_thread_life_protection = _Thread_Set_life_protection( true ); + #if defined(RTEMS_SMP) _Thread_Disable_dispatch(); #endif @@ -44,6 +45,11 @@ void _API_Mutex_Lock( level ); + if ( the_mutex->Mutex.nest_count == 1 ) { + the_mutex->previous_thread_life_protection = + previous_thread_life_protection; + } + #if defined(RTEMS_SMP) _Thread_Enable_dispatch(); #endif diff --git a/cpukit/score/src/apimutexunlock.c b/cpukit/score/src/apimutexunlock.c index 43bdfe8bbe..d0432a6f4a 100644 --- a/cpukit/score/src/apimutexunlock.c +++ b/cpukit/score/src/apimutexunlock.c @@ -19,19 +19,25 @@ #include "config.h" #endif -#include <rtems/system.h> #include <rtems/score/apimutex.h> #include <rtems/score/coremuteximpl.h> -void _API_Mutex_Unlock( - API_Mutex_Control *the_mutex -) +void _API_Mutex_Unlock( API_Mutex_Control *the_mutex ) { - _Thread_Disable_dispatch(); - _CORE_mutex_Surrender( - &the_mutex->Mutex, - the_mutex->Object.id, - NULL - ); + bool previous_thread_life_protection; + bool restore_thread_life_protection; + + _Thread_Disable_dispatch(); + + previous_thread_life_protection = + the_mutex->previous_thread_life_protection; + restore_thread_life_protection = the_mutex->Mutex.nest_count == 1; + + _CORE_mutex_Surrender( &the_mutex->Mutex, the_mutex->Object.id, NULL ); + _Thread_Enable_dispatch(); + + if ( restore_thread_life_protection ) { + _Thread_Set_life_protection( previous_thread_life_protection ); + } } |