summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-03-27 13:38:04 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-03-31 08:29:43 +0200
commit346845730cb7cdd3f2a1e9231cced7cdfd046ce1 (patch)
tree3764fe70bfaea1d230d5052982b3bff6b1322e13
parentscore: Relax Giant lock usage for API mutexes (diff)
downloadrtems-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.h42
-rw-r--r--cpukit/score/src/apimutexlock.c14
-rw-r--r--cpukit/score/src/apimutexunlock.c26
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 );
+ }
}