[PATCH 3/4] score: Use thread life protection for API mutexes

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Mar 27 13:20:23 UTC 2014


This prevents that asynchronous thread deletion can lead to an unusable
allocator or once mutex.
---
 cpukit/score/include/rtems/score/apimutex.h |   42 +++++++++++++--------------
 cpukit/score/src/apimutexlock.c             |   14 ++++++--
 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 380f054..5f02e0a 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 d943bdd..07e5159 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 43bdfe8..d0432a6 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 );
+  }
 }
-- 
1.7.7




More information about the devel mailing list