[rtems commit] score: Rework CORE priority ceiling mutex

Sebastian Huber sebh at rtems.org
Mon May 30 14:17:59 UTC 2016


Module:    rtems
Branch:    master
Commit:    33e250c9fa370f620ddbc5850342d5a90b123524
Changeset: http://git.rtems.org/rtems/commit/?id=33e250c9fa370f620ddbc5850342d5a90b123524

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri May 27 15:41:41 2016 +0200

score: Rework CORE priority ceiling mutex

Rework seize and surrender methods to use CORE_ceiling_mutex_Control.
This eliminates CORE_mutex_Disciplines.

---

 cpukit/posix/src/mutexgetprioceiling.c           |   2 +-
 cpukit/posix/src/mutexinit.c                     |  16 +-
 cpukit/posix/src/mutexlocksupp.c                 |  11 +
 cpukit/posix/src/mutexsetprioceiling.c           |   5 +-
 cpukit/posix/src/mutexunlock.c                   |   8 +
 cpukit/rtems/include/rtems/rtems/semimpl.h       |   1 +
 cpukit/rtems/src/semcreate.c                     |  41 ++--
 cpukit/rtems/src/semdelete.c                     |   2 +
 cpukit/rtems/src/semflush.c                      |   1 +
 cpukit/rtems/src/semobtain.c                     |  10 +
 cpukit/rtems/src/semrelease.c                    |  12 +-
 cpukit/rtems/src/semsetpriority.c                |  84 ++++----
 cpukit/score/include/rtems/score/coremutex.h     |  24 ---
 cpukit/score/include/rtems/score/coremuteximpl.h | 250 ++++++++++++++++-------
 cpukit/score/src/apimutex.c                      |   4 +-
 cpukit/score/src/coremutex.c                     |  32 ---
 cpukit/score/src/coremutexseize.c                |  33 ++-
 cpukit/score/src/coremutexsurrender.c            |  16 +-
 18 files changed, 327 insertions(+), 225 deletions(-)

diff --git a/cpukit/posix/src/mutexgetprioceiling.c b/cpukit/posix/src/mutexgetprioceiling.c
index 06eaf30..2df4776 100644
--- a/cpukit/posix/src/mutexgetprioceiling.c
+++ b/cpukit/posix/src/mutexgetprioceiling.c
@@ -46,7 +46,7 @@ int pthread_mutex_getprioceiling(
   _POSIX_Mutex_Acquire_critical( the_mutex, &queue_context );
 
   *prioceiling = _POSIX_Priority_From_core(
-    the_mutex->Mutex.Recursive.Mutex.Attributes.priority_ceiling
+    the_mutex->Mutex.priority_ceiling
   );
 
   _POSIX_Mutex_Release( the_mutex, &queue_context );
diff --git a/cpukit/posix/src/mutexinit.c b/cpukit/posix/src/mutexinit.c
index f2912ea..6c5705b 100644
--- a/cpukit/posix/src/mutexinit.c
+++ b/cpukit/posix/src/mutexinit.c
@@ -119,7 +119,12 @@ int pthread_mutex_init(
   the_mutex->protocol = protocol;
   the_mutex->is_recursive = ( the_attr->type == PTHREAD_MUTEX_RECURSIVE );
 
-  if ( protocol == POSIX_MUTEX_NO_PROTOCOL ) {
+  if ( protocol == POSIX_MUTEX_PRIORITY_CEILING ) {
+    _CORE_ceiling_mutex_Initialize(
+      &the_mutex->Mutex,
+      _POSIX_Priority_To_core( the_attr->prio_ceiling )
+    );
+  } else if ( protocol == POSIX_MUTEX_NO_PROTOCOL ) {
     _CORE_recursive_mutex_Initialize(
       &the_mutex->Mutex.Recursive
     );
@@ -132,15 +137,6 @@ int pthread_mutex_init(
       the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
     }
 
-    the_mutex_attr.priority_ceiling =
-      _POSIX_Priority_To_core( the_attr->prio_ceiling );
-
-    if ( protocol == POSIX_MUTEX_PRIORITY_CEILING ) {
-      the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
-    } else {
-      the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
-    }
-
     /*
      *  Must be initialized to unlocked.
      */
diff --git a/cpukit/posix/src/mutexlocksupp.c b/cpukit/posix/src/mutexlocksupp.c
index 2499ae1..cccb2d3 100644
--- a/cpukit/posix/src/mutexlocksupp.c
+++ b/cpukit/posix/src/mutexlocksupp.c
@@ -65,6 +65,16 @@ int _POSIX_Mutex_Lock_support(
   executing = _Thread_Executing;
 
   switch ( the_mutex->protocol ) {
+    case POSIX_MUTEX_PRIORITY_CEILING:
+      status = _CORE_ceiling_mutex_Seize(
+        &the_mutex->Mutex,
+        executing,
+        wait,
+        timeout,
+        _POSIX_Mutex_Lock_nested,
+        &queue_context
+      );
+      break;
     case POSIX_MUTEX_NO_PROTOCOL:
       status = _CORE_recursive_mutex_Seize_no_protocol(
         &the_mutex->Mutex.Recursive,
@@ -77,6 +87,7 @@ int _POSIX_Mutex_Lock_support(
       );
       break;
     default:
+      _Assert( the_mutex->protocol == POSIX_MUTEX_PRIORITY_INHERIT );
       status = _CORE_mutex_Seize(
         &the_mutex->Mutex.Recursive.Mutex,
         executing,
diff --git a/cpukit/posix/src/mutexsetprioceiling.c b/cpukit/posix/src/mutexsetprioceiling.c
index 5d11edf..96e8dbf 100644
--- a/cpukit/posix/src/mutexsetprioceiling.c
+++ b/cpukit/posix/src/mutexsetprioceiling.c
@@ -57,10 +57,9 @@ int pthread_mutex_setprioceiling(
   _Assert( the_mutex != NULL );
 
   *old_ceiling = _POSIX_Priority_From_core(
-    the_mutex->Mutex.Recursive.Mutex.Attributes.priority_ceiling
+    the_mutex->Mutex.priority_ceiling
   );
-  the_mutex->Mutex.Recursive.Mutex.Attributes.priority_ceiling =
-    the_priority;
+  the_mutex->Mutex.priority_ceiling = the_priority;
 
   error = pthread_mutex_unlock( mutex );
   _Assert( error == 0 );
diff --git a/cpukit/posix/src/mutexunlock.c b/cpukit/posix/src/mutexunlock.c
index b0ca33d..5404cef 100644
--- a/cpukit/posix/src/mutexunlock.c
+++ b/cpukit/posix/src/mutexunlock.c
@@ -45,6 +45,13 @@ int pthread_mutex_unlock(
   executing = _Thread_Executing;
 
   switch ( the_mutex->protocol ) {
+    case POSIX_MUTEX_PRIORITY_CEILING:
+      status = _CORE_ceiling_mutex_Surrender(
+        &the_mutex->Mutex,
+        executing,
+        &queue_context
+      );
+      break;
     case POSIX_MUTEX_NO_PROTOCOL:
       status = _CORE_recursive_mutex_Surrender_no_protocol(
         &the_mutex->Mutex.Recursive,
@@ -54,6 +61,7 @@ int pthread_mutex_unlock(
       );
       break;
     default:
+      _Assert( the_mutex->protocol == POSIX_MUTEX_PRIORITY_INHERIT );
       status = _CORE_mutex_Surrender(
         &the_mutex->Mutex.Recursive.Mutex,
         &queue_context
diff --git a/cpukit/rtems/include/rtems/rtems/semimpl.h b/cpukit/rtems/include/rtems/rtems/semimpl.h
index 5b789d6..9d82a12 100644
--- a/cpukit/rtems/include/rtems/rtems/semimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/semimpl.h
@@ -33,6 +33,7 @@ extern "C" {
  */
 typedef enum {
   SEMAPHORE_VARIANT_MUTEX,
+  SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING,
   SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL,
   SEMAPHORE_VARIANT_SIMPLE_BINARY,
   SEMAPHORE_VARIANT_COUNTING
diff --git a/cpukit/rtems/src/semcreate.c b/cpukit/rtems/src/semcreate.c
index 91f693c..720fb63 100644
--- a/cpukit/rtems/src/semcreate.c
+++ b/cpukit/rtems/src/semcreate.c
@@ -136,6 +136,7 @@ rtems_status_code rtems_semaphore_create(
   }
 #endif
 
+  priority_ceiling = _RTEMS_tasks_Priority_to_Core( priority_ceiling );
   the_semaphore->attribute_set = attribute_set;
   executing = _Thread_Get_executing();
 
@@ -169,10 +170,32 @@ rtems_status_code rtems_semaphore_create(
       count != 1
     );
 #endif
-  } else if (
-    !_Attributes_Is_inherit_priority( attribute_set )
-      && !_Attributes_Is_priority_ceiling( attribute_set )
-  ) {
+  } else if ( _Attributes_Is_priority_ceiling( attribute_set ) ) {
+    _Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
+    the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
+    _CORE_ceiling_mutex_Initialize(
+      &the_semaphore->Core_control.Mutex,
+      priority_ceiling
+    );
+
+    if ( count == 0 ) {
+      Thread_queue_Context queue_context;
+
+      _Thread_queue_Context_initialize( &queue_context );
+      _ISR_lock_ISR_disable( &queue_context.Lock_context );
+      _CORE_mutex_Acquire_critical(
+        &the_semaphore->Core_control.Mutex.Recursive.Mutex,
+        &queue_context
+      );
+      status = _CORE_ceiling_mutex_Set_owner(
+        &the_semaphore->Core_control.Mutex,
+        executing,
+        &queue_context
+      );
+    } else {
+      status = STATUS_SUCCESSFUL;
+    }
+  } else if ( !_Attributes_Is_inherit_priority( attribute_set ) ) {
     _Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
     the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
     _CORE_recursive_mutex_Initialize(
@@ -189,19 +212,11 @@ rtems_status_code rtems_semaphore_create(
     status = STATUS_SUCCESSFUL;
   } else {
     _Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
+    _Assert( _Attributes_Is_inherit_priority( attribute_set ) );
     the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX;
 
-    the_mutex_attr.priority_ceiling =
-      _RTEMS_tasks_Priority_to_Core( priority_ceiling );
     the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
 
-    if ( _Attributes_Is_inherit_priority( attribute_set ) ) {
-      the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
-    } else {
-      _Assert( _Attributes_Is_priority_ceiling( attribute_set ) );
-      the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
-    }
-
     status = _CORE_mutex_Initialize(
       &the_semaphore->Core_control.Mutex.Recursive.Mutex,
       executing,
diff --git a/cpukit/rtems/src/semdelete.c b/cpukit/rtems/src/semdelete.c
index 365d895..a38d761 100644
--- a/cpukit/rtems/src/semdelete.c
+++ b/cpukit/rtems/src/semdelete.c
@@ -51,6 +51,7 @@ rtems_status_code rtems_semaphore_delete(
 
   switch ( the_semaphore->variant ) {
     case SEMAPHORE_VARIANT_MUTEX:
+    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
       if (
         _CORE_mutex_Is_locked(
@@ -97,6 +98,7 @@ rtems_status_code rtems_semaphore_delete(
     default:
       _Assert(
         the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX
+          || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING
           || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
           || the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
           || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
diff --git a/cpukit/rtems/src/semflush.c b/cpukit/rtems/src/semflush.c
index 6c1f4dd..17c589f 100644
--- a/cpukit/rtems/src/semflush.c
+++ b/cpukit/rtems/src/semflush.c
@@ -58,6 +58,7 @@ rtems_status_code rtems_semaphore_flush( rtems_id id )
     default:
       _Assert(
         the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX
+          || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING
           || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
           || the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
           || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c
index a7774d6..44507ab 100644
--- a/cpukit/rtems/src/semobtain.c
+++ b/cpukit/rtems/src/semobtain.c
@@ -90,6 +90,16 @@ rtems_status_code rtems_semaphore_obtain(
         &queue_context
       );
       break;
+    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
+      status = _CORE_ceiling_mutex_Seize(
+        &the_semaphore->Core_control.Mutex,
+        executing,
+        wait,
+        timeout,
+        _CORE_recursive_mutex_Seize_nested,
+        &queue_context
+      );
+      break;
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
       status = _CORE_recursive_mutex_Seize_no_protocol(
         &the_semaphore->Core_control.Mutex.Recursive,
diff --git a/cpukit/rtems/src/semrelease.c b/cpukit/rtems/src/semrelease.c
index 7cd92cf..d92197b 100644
--- a/cpukit/rtems/src/semrelease.c
+++ b/cpukit/rtems/src/semrelease.c
@@ -28,6 +28,7 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
 {
   Semaphore_Control    *the_semaphore;
   Thread_queue_Context  queue_context;
+  Thread_Control       *executing;
   Status_Control        status;
 
   the_semaphore = _Semaphore_Get( id, &queue_context );
@@ -40,6 +41,8 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
 #endif
   }
 
+  executing = _Thread_Executing;
+
   _Thread_queue_Context_set_MP_callout(
     &queue_context,
     _Semaphore_Core_mutex_mp_support
@@ -50,7 +53,7 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
     case SEMAPHORE_VARIANT_MRSP:
       status = _MRSP_Surrender(
         &the_semaphore->Core_control.mrsp,
-        _Thread_Executing,
+        executing,
         &queue_context
       );
       break;
@@ -61,6 +64,13 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
         &queue_context
       );
       break;
+    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
+      status = _CORE_ceiling_mutex_Surrender(
+        &the_semaphore->Core_control.Mutex,
+        executing,
+        &queue_context
+      );
+      break;
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
       _CORE_recursive_mutex_Surrender_no_protocol_classic(
         &the_semaphore->Core_control.Mutex.Recursive,
diff --git a/cpukit/rtems/src/semsetpriority.c b/cpukit/rtems/src/semsetpriority.c
index 0a8c58c..57a5368 100644
--- a/cpukit/rtems/src/semsetpriority.c
+++ b/cpukit/rtems/src/semsetpriority.c
@@ -17,7 +17,6 @@
 #endif
 
 #include <rtems/rtems/semimpl.h>
-#include <rtems/rtems/attrimpl.h>
 #include <rtems/rtems/tasksimpl.h>
 #include <rtems/score/schedulerimpl.h>
 
@@ -29,51 +28,62 @@ static rtems_status_code _Semaphore_Set_priority(
   Thread_queue_Context *queue_context
 )
 {
-  rtems_status_code   sc;
-  rtems_attribute     attribute_set = the_semaphore->attribute_set;
-  rtems_task_priority old_priority;
+  rtems_status_code    sc;
+  rtems_task_priority  old_priority;
+#if defined(RTEMS_SMP)
+  MRSP_Control        *mrsp;
+  uint32_t             scheduler_index;
+#endif
 
   new_priority = _RTEMS_tasks_Priority_to_Core( new_priority );
 
+  switch ( the_semaphore->variant ) {
+    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
+      _CORE_mutex_Acquire_critical(
+        &the_semaphore->Core_control.Mutex.Recursive.Mutex,
+        queue_context
+      );
+
+      old_priority = the_semaphore->Core_control.Mutex.priority_ceiling;
+
+      if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
+        the_semaphore->Core_control.Mutex.priority_ceiling = new_priority;
+      }
+
+      _CORE_mutex_Release(
+        &the_semaphore->Core_control.Mutex.Recursive.Mutex,
+        queue_context
+      );
+      sc = RTEMS_SUCCESSFUL;
+      break;
 #if defined(RTEMS_SMP)
-  if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
-    MRSP_Control *mrsp = &the_semaphore->Core_control.mrsp;
-    uint32_t scheduler_index = _Scheduler_Get_index_by_id( scheduler_id );
-
-    _MRSP_Acquire_critical( mrsp, queue_context );
+    case SEMAPHORE_VARIANT_MRSP:
+      mrsp = &the_semaphore->Core_control.mrsp;
+      scheduler_index = _Scheduler_Get_index_by_id( scheduler_id );
 
-    old_priority = _MRSP_Get_ceiling_priority( mrsp, scheduler_index );
+      _MRSP_Acquire_critical( mrsp, queue_context );
 
-    if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
-      _MRSP_Set_ceiling_priority( mrsp, scheduler_index, new_priority );
-    }
+      old_priority = _MRSP_Get_ceiling_priority( mrsp, scheduler_index );
 
-    _MRSP_Release( mrsp, queue_context );
+      if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
+        _MRSP_Set_ceiling_priority( mrsp, scheduler_index, new_priority );
+      }
 
-    sc = RTEMS_SUCCESSFUL;
-  } else
+      _MRSP_Release( mrsp, queue_context );
+      sc = RTEMS_SUCCESSFUL;
+      break;
 #endif
-  if ( _Attributes_Is_priority_ceiling( attribute_set ) ) {
-    CORE_mutex_Control *mutex;
-
-    mutex = &the_semaphore->Core_control.Mutex.Recursive.Mutex;
-    _CORE_mutex_Acquire_critical( mutex, queue_context );
-
-    old_priority = mutex->Attributes.priority_ceiling;
-
-    if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
-      mutex->Attributes.priority_ceiling = new_priority;
-    }
-
-    _CORE_mutex_Release( mutex, queue_context );
-
-    sc = RTEMS_SUCCESSFUL;
-  } else {
-    _ISR_lock_ISR_enable( &queue_context->Lock_context );
-
-    old_priority = 0;
-
-    sc = RTEMS_NOT_DEFINED;
+    default:
+      _Assert(
+        the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX
+          || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
+          || the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
+      );
+      _ISR_lock_ISR_enable( &queue_context->Lock_context );
+      old_priority = 0;
+      sc = RTEMS_NOT_DEFINED;
+      break;
   }
 
   *old_priority_p = _RTEMS_tasks_Priority_from_Core( old_priority );
diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h
index 173bb2e..704ea0d 100644
--- a/cpukit/score/include/rtems/score/coremutex.h
+++ b/cpukit/score/include/rtems/score/coremutex.h
@@ -42,22 +42,6 @@ extern "C" {
 /**@{*/
 
 /**
- *  @brief The blocking disciplines for a mutex.
- *
- *  This enumerated type defines the blocking disciplines for a mutex.
- */
-typedef enum {
-  /** This specifies that threads will wait for the mutex in priority order.
-   *  Additionally, the Priority Inheritance Protocol will be in effect.
-   */
-  CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
-  /** This specifies that threads will wait for the mutex in priority order.
-   *  Additionally, the Priority Ceiling Protocol will be in effect.
-   */
-  CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
-}   CORE_mutex_Disciplines;
-
-/**
  *  @brief The possible behaviors for lock nesting.
  *
  *  This enumerated type defines the possible behaviors for
@@ -96,14 +80,6 @@ typedef struct {
    *  be when attempting to acquire the mutex when it is already locked.
    */
   CORE_mutex_Nesting_behaviors lock_nesting_behavior;
-  /** This field indicates whether threads waiting on the mutex block in
-   *  FIFO or priority order.
-   */
-  CORE_mutex_Disciplines       discipline;
-  /** This field contains the ceiling priority to be used if that protocol
-   *  is selected.
-   */
-  Priority_Control             priority_ceiling;
 }   CORE_mutex_Attributes;
 
 /**
diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h
index fc2ffd9..f459743 100644
--- a/cpukit/score/include/rtems/score/coremuteximpl.h
+++ b/cpukit/score/include/rtems/score/coremuteximpl.h
@@ -128,42 +128,6 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_locked(
 }
 
 /**
- * @brief Does mutex use priority inheritance.
- *
- * This routine returns true if the mutex's wait discipline is
- * INHERIT_PRIORITY and false otherwise.
- *
- * @param[in] the_attribute is the attribute set of the mutex.
- *
- * @retval true The mutex is using priority inheritance.
- * @retval false The mutex is not using priority inheritance.
- */
-RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_inherit_priority(
-  const CORE_mutex_Attributes *the_attribute
-)
-{
-  return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
-}
-
-/**
- * @brief Does mutex use priority ceiling.
- *
- * This routine returns true if the mutex's wait discipline is
- * PRIORITY_CEILING and false otherwise.
- *
- * @param[in] the_attribute is the attribute set of the mutex.
- *
- * @retval true The mutex is using priority ceiling.
- * @retval false The mutex is not using priority ceiling.
- */
-RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_priority_ceiling(
-  const CORE_mutex_Attributes *the_attribute
-)
-{
-  return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
-}
-
-/**
  *  @brief Attempt to receive a unit from the_mutex.
  *
  *  This routine attempts to receive a unit from the_mutex.
@@ -191,40 +155,7 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_mutex_Seize_interrupt_trylock(
     the_mutex->nest_count = 1;
     ++executing->resource_count;
 
-    if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
-      _CORE_mutex_Release( the_mutex, queue_context );
-    } else {
-      /*
-       * must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
-       *
-       * we possibly bump the priority of the current holder -- which
-       * happens to be _Thread_Executing.
-       */
-      Priority_Control  ceiling;
-      Priority_Control  current;
-
-      ceiling = the_mutex->Attributes.priority_ceiling;
-      current = executing->current_priority;
-      if ( current == ceiling ) {
-        _CORE_mutex_Release( the_mutex, queue_context );
-      } else if ( current > ceiling ) {
-        Per_CPU_Control *cpu_self;
-
-        cpu_self = _Thread_Dispatch_disable_critical(
-          &queue_context->Lock_context
-        );
-        _CORE_mutex_Release( the_mutex, queue_context );
-        _Thread_Raise_priority( executing, ceiling );
-        _Thread_Dispatch_enable( cpu_self );
-      } else /* if ( current < ceiling ) */ {
-        the_mutex->holder = NULL;
-        the_mutex->nest_count = 0;     /* undo locking above */
-        executing->resource_count--;   /* undo locking above */
-        _CORE_mutex_Release( the_mutex, queue_context );
-        return STATUS_MUTEX_CEILING_VIOLATED;
-      }
-    }
-
+    _CORE_mutex_Release( the_mutex, queue_context );
     return STATUS_SUCCESSFUL;
   }
 
@@ -345,6 +276,32 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_owner(
   return _CORE_mutex_Get_owner( the_mutex ) == the_thread;
 }
 
+RTEMS_INLINE_ROUTINE void _CORE_mutex_Restore_priority(
+  Thread_Control *executing
+)
+{
+  /*
+   *  Whether or not someone is waiting for the mutex, an
+   *  inherited priority must be lowered if this is the last
+   *  mutex (i.e. resource) this task has.
+   */
+  if ( !_Thread_Owns_resources( executing ) ) {
+    /*
+     * Ensure that the executing resource count is visible to all other
+     * processors and that we read the latest priority restore hint.
+     */
+    _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+
+    if ( executing->priority_restore_hint ) {
+      Per_CPU_Control *cpu_self;
+
+      cpu_self = _Thread_Dispatch_disable();
+      _Thread_Restore_priority( executing );
+      _Thread_Dispatch_enable( cpu_self );
+    }
+  }
+}
+
 RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize(
   CORE_recursive_mutex_Control *the_mutex
 )
@@ -479,6 +436,159 @@ RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Surrender_no_protocol_classic(
   );
 }
 
+RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Initialize(
+  CORE_ceiling_mutex_Control *the_mutex,
+  Priority_Control            priority_ceiling
+)
+{
+  _CORE_recursive_mutex_Initialize( &the_mutex->Recursive );
+  the_mutex->priority_ceiling = priority_ceiling;
+}
+
+RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner(
+  CORE_ceiling_mutex_Control *the_mutex,
+  Thread_Control             *owner,
+  Thread_queue_Context       *queue_context
+)
+{
+  Priority_Control  priority_ceiling;
+  Priority_Control  current_priority;
+  Per_CPU_Control  *cpu_self;
+
+  priority_ceiling = the_mutex->priority_ceiling;
+  current_priority = owner->current_priority;
+
+  if ( current_priority < priority_ceiling ) {
+    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+    return STATUS_MUTEX_CEILING_VIOLATED;
+  }
+
+  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
+  ++owner->resource_count;
+
+  if ( current_priority == priority_ceiling ) {
+    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+    return STATUS_SUCCESSFUL;
+  }
+
+  cpu_self = _Thread_Dispatch_disable_critical( &queue_context->Lock_context );
+  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+  _Thread_Raise_priority( owner, priority_ceiling );
+  _Thread_Dispatch_enable( cpu_self );
+  return STATUS_SUCCESSFUL;
+}
+
+RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Seize(
+  CORE_ceiling_mutex_Control    *the_mutex,
+  Thread_Control                *executing,
+  bool                           wait,
+  Watchdog_Interval              timeout,
+  Status_Control              ( *nested )( CORE_recursive_mutex_Control * ),
+  Thread_queue_Context          *queue_context
+)
+{
+  Thread_Control *owner;
+
+  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
+
+  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
+
+  if ( owner == NULL ) {
+    return _CORE_ceiling_mutex_Set_owner(
+      the_mutex,
+      executing,
+      queue_context
+    );
+  }
+
+  if ( owner == executing ) {
+    Status_Control status;
+
+    status = ( *nested )( &the_mutex->Recursive );
+    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+    return status;
+  }
+
+  return _CORE_mutex_Seize_no_protocol_slow(
+    &the_mutex->Recursive.Mutex,
+    CORE_MUTEX_TQ_OPERATIONS,
+    executing,
+    wait,
+    timeout,
+    queue_context
+  );
+}
+
+RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender(
+  CORE_ceiling_mutex_Control *the_mutex,
+  Thread_Control             *executing,
+  Thread_queue_Context       *queue_context
+)
+{
+  unsigned int    nest_level;
+  Thread_Control *new_owner;
+
+  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
+
+  if ( !_CORE_mutex_Is_owner( &the_mutex->Recursive.Mutex, executing ) ) {
+    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+    return STATUS_NOT_OWNER;
+  }
+
+  nest_level = the_mutex->Recursive.nest_level;
+
+  if ( nest_level > 0 ) {
+    the_mutex->Recursive.nest_level = nest_level - 1;
+    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+    return STATUS_SUCCESSFUL;
+  }
+
+  --executing->resource_count;
+
+  new_owner = _Thread_queue_First_locked(
+    &the_mutex->Recursive.Mutex.Wait_queue,
+    CORE_MUTEX_TQ_OPERATIONS
+  );
+  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, new_owner );
+
+  if ( new_owner != NULL ) {
+    bool unblock;
+
+    /*
+     * We must extract the thread now since this will restore its default
+     * thread lock.  This is necessary to avoid a deadlock in the
+     * _Thread_Change_priority() below due to a recursive thread queue lock
+     * acquire.
+     */
+    unblock = _Thread_queue_Extract_locked(
+      &the_mutex->Recursive.Mutex.Wait_queue.Queue,
+      CORE_MUTEX_TQ_OPERATIONS,
+      new_owner,
+      queue_context
+    );
+
+#if defined(RTEMS_MULTIPROCESSING)
+    if ( _Objects_Is_local_id( new_owner->Object.id ) )
+#endif
+    {
+      ++new_owner->resource_count;
+      _Thread_Raise_priority( new_owner, the_mutex->priority_ceiling );
+    }
+
+    _Thread_queue_Unblock_critical(
+      unblock,
+      &the_mutex->Recursive.Mutex.Wait_queue.Queue,
+      new_owner,
+      &queue_context->Lock_context
+    );
+  } else {
+    _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
+  }
+
+  _CORE_mutex_Restore_priority( executing );
+  return STATUS_SUCCESSFUL;
+}
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpukit/score/src/apimutex.c b/cpukit/score/src/apimutex.c
index 8af374a..e3c6e5a 100644
--- a/cpukit/score/src/apimutex.c
+++ b/cpukit/score/src/apimutex.c
@@ -48,9 +48,7 @@ void _API_Mutex_Allocate(
   API_Mutex_Control *mutex;
 
   CORE_mutex_Attributes attr =  {
-    CORE_MUTEX_NESTING_ACQUIRES,
-    CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
-    0
+    CORE_MUTEX_NESTING_ACQUIRES
   };
 
   mutex = (API_Mutex_Control *)
diff --git a/cpukit/score/src/coremutex.c b/cpukit/score/src/coremutex.c
index 6f73c1b..9c6b7a8 100644
--- a/cpukit/score/src/coremutex.c
+++ b/cpukit/score/src/coremutex.c
@@ -39,41 +39,9 @@ Status_Control _CORE_mutex_Initialize(
   the_mutex->Attributes    = *the_mutex_attributes;
 
   if ( initially_locked ) {
-    bool              is_priority_ceiling;
-    Priority_Control  ceiling;
-    Per_CPU_Control  *cpu_self;
-
     the_mutex->nest_count = 1;
     the_mutex->holder     = executing;
-
-    /* The mutex initialization is only protected by the allocator lock */
-    cpu_self = _Thread_Dispatch_disable();
-
-    is_priority_ceiling =
-      _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes );
-    ceiling = the_mutex->Attributes.priority_ceiling;
-
-    /*
-     * The test to check for a ceiling violation is a bit arbitrary.  In case
-     * this thread is the owner of a priority inheritance mutex, then it may
-     * get a higher priority later or anytime on SMP configurations.
-     */
-    if ( is_priority_ceiling && executing->current_priority < ceiling ) {
-      /*
-       * There is no need to undo the previous work since this error aborts
-       * the object creation.
-       */
-      _Thread_Dispatch_enable( cpu_self );
-      return STATUS_MUTEX_CEILING_VIOLATED;
-    }
-
     executing->resource_count++;
-
-    if ( is_priority_ceiling ) {
-      _Thread_Raise_priority( executing, ceiling );
-    }
-
-    _Thread_Dispatch_enable( cpu_self );
   } else {
     the_mutex->nest_count = 0;
     the_mutex->holder     = NULL;
diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c
index 596378f..ed5eb0a 100644
--- a/cpukit/score/src/coremutexseize.c
+++ b/cpukit/score/src/coremutexseize.c
@@ -29,6 +29,8 @@ Status_Control _CORE_mutex_Seize_interrupt_blocking(
   Thread_queue_Context *queue_context
 )
 {
+  Thread_Control *holder;
+
 #if !defined(RTEMS_SMP)
   /*
    * We must disable thread dispatching here since we enable the interrupts for
@@ -37,32 +39,27 @@ Status_Control _CORE_mutex_Seize_interrupt_blocking(
   _Thread_Dispatch_disable();
 #endif
 
-  if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
-    Thread_Control *holder = the_mutex->holder;
+  holder = the_mutex->holder;
 
 #if !defined(RTEMS_SMP)
-    /*
-     * To enable interrupts here works only since exactly one executing thread
-     * exists and only threads are allowed to seize and surrender mutexes with
-     * the priority inheritance protocol.  On SMP configurations more than one
-     * executing thread may exist, so here we must not release the lock, since
-     * otherwise the current holder may be no longer the holder of the mutex
-     * once we released the lock.
-     */
-    _CORE_mutex_Release( the_mutex, queue_context );
+  /*
+   * To enable interrupts here works only since exactly one executing thread
+   * exists and only threads are allowed to seize and surrender mutexes with
+   * the priority inheritance protocol.  On SMP configurations more than one
+   * executing thread may exist, so here we must not release the lock, since
+   * otherwise the current holder may be no longer the holder of the mutex
+   * once we released the lock.
+   */
+  _CORE_mutex_Release( the_mutex, queue_context );
 #endif
 
-    _Thread_Inherit_priority( holder, executing );
-
-#if !defined(RTEMS_SMP)
-    _ISR_lock_ISR_disable( &queue_context->Lock_context );
-    _CORE_mutex_Acquire_critical( the_mutex, queue_context );
-#endif
-  }
+  _Thread_Inherit_priority( holder, executing );
 
 #if defined(RTEMS_SMP)
   _Thread_queue_Context_set_expected_level( queue_context, 1 );
 #else
+  _ISR_lock_ISR_disable( &queue_context->Lock_context );
+  _CORE_mutex_Acquire_critical( the_mutex, queue_context );
   _Thread_queue_Context_set_expected_level( queue_context, 2 );
 #endif
 
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c
index 2d976e0..5075e20 100644
--- a/cpukit/score/src/coremutexsurrender.c
+++ b/cpukit/score/src/coremutexsurrender.c
@@ -118,19 +118,8 @@ Status_Control _CORE_mutex_Surrender(
     if ( _Objects_Is_local_id( the_thread->Object.id ) )
 #endif
     {
-      switch ( the_mutex->Attributes.discipline ) {
-        case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
-          the_thread->resource_count++;
-          _Thread_queue_Boost_priority( &the_mutex->Wait_queue.Queue, the_thread );
-          break;
-        case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
-          the_thread->resource_count++;
-          _Thread_Raise_priority(
-            the_thread,
-            the_mutex->Attributes.priority_ceiling
-          );
-          break;
-      }
+      the_thread->resource_count++;
+      _Thread_queue_Boost_priority( &the_mutex->Wait_queue.Queue, the_thread );
     }
 
     _Thread_queue_Unblock_critical(
@@ -164,5 +153,6 @@ Status_Control _CORE_mutex_Surrender(
     }
   }
 
+  _CORE_mutex_Restore_priority( holder );
   return STATUS_SUCCESSFUL;
 }




More information about the vc mailing list