[PATCH 1/2] rtems: Optimize semaphore control block

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Dec 9 09:11:01 UTC 2019


Move variant, discipline, and global information to flags stored in a
node pointer of active semaphores.

Update #3833.
---
 cpukit/include/rtems/rtems/semdata.h | 28 +++++----------
 cpukit/include/rtems/rtems/semimpl.h | 69 ++++++++++++++++++++++++++++++++++--
 cpukit/libmisc/monitor/mon-sema.c    | 14 +++++---
 cpukit/rtems/src/semcreate.c         | 43 +++++++++++++---------
 cpukit/rtems/src/semdelete.c         | 24 +++++++------
 cpukit/rtems/src/semflush.c          | 18 ++++++----
 cpukit/rtems/src/semobtain.c         | 15 +++++---
 cpukit/rtems/src/semrelease.c        | 14 +++++---
 cpukit/rtems/src/semsetpriority.c    | 12 ++++---
 9 files changed, 162 insertions(+), 75 deletions(-)

diff --git a/cpukit/include/rtems/rtems/semdata.h b/cpukit/include/rtems/rtems/semdata.h
index d2275e5dfe..f5a8afcc87 100644
--- a/cpukit/include/rtems/rtems/semdata.h
+++ b/cpukit/include/rtems/rtems/semdata.h
@@ -38,7 +38,15 @@ extern "C" {
  *  The following defines the control block used to manage each semaphore.
  */
 typedef struct {
-  /** This field is the object management portion of a Semaphore instance. */
+  /**
+   * @brief The object management portion of a semaphore instance.
+   *
+   * A pointer of the node of active semaphores contains the semaphore flags,
+   * see _Semaphore_Get_flags().  The rational for this optimization is a
+   * reduction of the semaphore control size in general and the ability to
+   * allow a configuration dependent size of the semaphore control block, e.g.
+   * for the MrsP semaphores.
+   */
   Objects_Control          Object;
 
   /**
@@ -72,24 +80,6 @@ typedef struct {
     MRSP_Control MRSP;
 #endif
   } Core_control;
-
-  /**
-   * @brief The semaphore variant.
-   *
-   * @see Semaphore_Variant.
-   */
-  unsigned int variant : 3;
-
-  /**
-   * @brief The semaphore thread queue discipline.
-   *
-   * @see Semaphore_Discipline.
-   */
-  unsigned int discipline : 1;
-
-#if defined(RTEMS_MULTIPROCESSING)
-  unsigned int is_global : 1;
-#endif
 }   Semaphore_Control;
 
 /**
diff --git a/cpukit/include/rtems/rtems/semimpl.h b/cpukit/include/rtems/rtems/semimpl.h
index dd6a8b4e48..0cb78e35d4 100644
--- a/cpukit/include/rtems/rtems/semimpl.h
+++ b/cpukit/include/rtems/rtems/semimpl.h
@@ -56,15 +56,78 @@ typedef enum {
   SEMAPHORE_DISCIPLINE_FIFO
 } Semaphore_Discipline;
 
-RTEMS_INLINE_ROUTINE const Thread_queue_Operations *_Semaphore_Get_operations(
+RTEMS_INLINE_ROUTINE uintptr_t _Semaphore_Get_flags(
   const Semaphore_Control *the_semaphore
 )
 {
-  if ( the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY ) {
+  _Assert( _Chain_Is_node_off_chain( &the_semaphore->Object.Node ) );
+  return (uintptr_t) the_semaphore->Object.Node.previous;
+}
+
+RTEMS_INLINE_ROUTINE void _Semaphore_Set_flags(
+  Semaphore_Control *the_semaphore,
+  uintptr_t          flags
+)
+{
+  _Assert( _Chain_Is_node_off_chain( &the_semaphore->Object.Node ) );
+  the_semaphore->Object.Node.previous = (Chain_Node *) flags;
+}
+
+RTEMS_INLINE_ROUTINE Semaphore_Variant _Semaphore_Get_variant(
+  uintptr_t flags
+)
+{
+  return (Semaphore_Discipline) ( flags & 0x7 );
+}
+
+RTEMS_INLINE_ROUTINE uintptr_t _Semaphore_Set_variant(
+  uintptr_t         flags,
+  Semaphore_Variant variant
+)
+{
+  return flags | variant;
+}
+
+RTEMS_INLINE_ROUTINE Semaphore_Discipline _Semaphore_Get_discipline(
+  uintptr_t flags
+)
+{
+  return (Semaphore_Discipline) ( ( flags >> 3 ) & 0x1 );
+}
+
+RTEMS_INLINE_ROUTINE uintptr_t _Semaphore_Set_discipline(
+  uintptr_t            flags,
+  Semaphore_Discipline discipline
+)
+{
+  return flags | ( discipline << 3 );
+}
+
+#if defined(RTEMS_MULTIPROCESSING)
+RTEMS_INLINE_ROUTINE bool _Semaphore_Is_global(
+  uintptr_t flags
+)
+{
+  return ( flags & 0x10 ) != 0;
+}
+
+RTEMS_INLINE_ROUTINE uintptr_t _Semaphore_Make_global( uintptr_t flags )
+{
+  return flags | 0x10;
+}
+#endif
+
+RTEMS_INLINE_ROUTINE const Thread_queue_Operations *_Semaphore_Get_operations(
+  uintptr_t flags
+)
+{
+  if (
+    _Semaphore_Get_variant( flags ) == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
+  ) {
     return &_Thread_queue_Operations_priority_inherit;
   }
 
-  if ( the_semaphore->discipline == SEMAPHORE_DISCIPLINE_PRIORITY ) {
+  if ( _Semaphore_Get_discipline( flags ) == SEMAPHORE_DISCIPLINE_PRIORITY ) {
     return &_Thread_queue_Operations_priority;
   }
 
diff --git a/cpukit/libmisc/monitor/mon-sema.c b/cpukit/libmisc/monitor/mon-sema.c
index 87e784ea74..fabc3c952b 100644
--- a/cpukit/libmisc/monitor/mon-sema.c
+++ b/cpukit/libmisc/monitor/mon-sema.c
@@ -18,7 +18,8 @@ rtems_monitor_sema_canonical(
     const void            *sema_void
 )
 {
-    const Semaphore_Control *rtems_sema = (const Semaphore_Control *) sema_void;
+    const Semaphore_Control *rtems_sema;
+    uintptr_t flags;
     Thread_Control *owner;
 
     canonical_sema->attribute = 0;
@@ -27,17 +28,20 @@ rtems_monitor_sema_canonical(
     canonical_sema->cur_count = 0;
     canonical_sema->holder_id = 0;
 
+    rtems_sema = (const Semaphore_Control *) sema_void;
+    flags = _Semaphore_Get_flags( rtems_sema );
+
 #if defined(RTEMS_MULTIPROCESSING)
-    if (rtems_sema->is_global) {
+    if ( _Semaphore_Is_global( flags ) ) {
       canonical_sema->attribute |= RTEMS_GLOBAL;
     }
 #endif
 
-    if (rtems_sema->discipline == SEMAPHORE_DISCIPLINE_PRIORITY) {
+    if ( _Semaphore_Get_discipline( flags ) == SEMAPHORE_DISCIPLINE_PRIORITY ) {
       canonical_sema->attribute |= RTEMS_PRIORITY;
     }
 
-    switch ( rtems_sema->variant ) {
+    switch ( _Semaphore_Get_variant( flags ) ) {
       case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
         canonical_sema->attribute |= RTEMS_BINARY_SEMAPHORE
           | RTEMS_INHERIT_PRIORITY;
@@ -63,7 +67,7 @@ rtems_monitor_sema_canonical(
         break;
     }
 
-    switch ( rtems_sema->variant ) {
+    switch ( _Semaphore_Get_variant( flags ) ) {
       case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
         canonical_sema->priority_ceiling = _Scheduler_Unmap_priority(
           _CORE_ceiling_mutex_Get_scheduler( &rtems_sema->Core_control.Mutex ),
diff --git a/cpukit/rtems/src/semcreate.c b/cpukit/rtems/src/semcreate.c
index dc4e02cd97..81a968107f 100644
--- a/cpukit/rtems/src/semcreate.c
+++ b/cpukit/rtems/src/semcreate.c
@@ -47,6 +47,7 @@ rtems_status_code rtems_semaphore_create(
   const Scheduler_Control *scheduler;
   bool                     valid;
   Priority_Control         priority;
+  uintptr_t                flags;
 
   if ( !rtems_is_name_valid( name ) )
     return RTEMS_INVALID_NAME;
@@ -116,29 +117,39 @@ rtems_status_code rtems_semaphore_create(
     return RTEMS_TOO_MANY;
   }
 
+  flags = _Semaphore_Set_variant( 0, variant );
+
 #if defined(RTEMS_MULTIPROCESSING)
-  the_semaphore->is_global = _Attributes_Is_global( attribute_set );
+  if ( _Attributes_Is_global( attribute_set ) ) {
+    bool ok;
 
-  if ( _Attributes_Is_global( attribute_set ) &&
-       ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
-                            the_semaphore->Object.id, false ) ) ) {
-    _Semaphore_Free( the_semaphore );
-    _Objects_Allocator_unlock();
-    return RTEMS_TOO_MANY;
-  }
-#endif
+    ok = _Objects_MP_Allocate_and_open(
+      &_Semaphore_Information,
+      name,
+      the_semaphore->Object.id,
+      false
+    );
 
-  executing = _Thread_Get_executing();
+    if ( !ok ) {
+      _Semaphore_Free( the_semaphore );
+      _Objects_Allocator_unlock();
+      return RTEMS_TOO_MANY;
+    }
 
-  the_semaphore->variant = variant;
+    flags = _Semaphore_Make_global( flags );
+  }
+#endif
 
   if ( _Attributes_Is_priority( attribute_set ) ) {
-    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_PRIORITY;
+    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_PRIORITY );
   } else {
-    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_FIFO;
+    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_FIFO );
   }
 
-  switch ( the_semaphore->variant ) {
+  _Semaphore_Set_flags( the_semaphore, flags );
+  executing = _Thread_Get_executing();
+
+  switch ( variant ) {
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
     case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
       _CORE_recursive_mutex_Initialize(
@@ -214,8 +225,8 @@ rtems_status_code rtems_semaphore_create(
 #endif
     default:
       _Assert(
-        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
-          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
+        variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || variant == SEMAPHORE_VARIANT_COUNTING
       );
       _CORE_semaphore_Initialize(
         &the_semaphore->Core_control.Semaphore,
diff --git a/cpukit/rtems/src/semdelete.c b/cpukit/rtems/src/semdelete.c
index a9fb863814..3586b78434 100644
--- a/cpukit/rtems/src/semdelete.c
+++ b/cpukit/rtems/src/semdelete.c
@@ -27,6 +27,8 @@ rtems_status_code rtems_semaphore_delete(
 {
   Semaphore_Control    *the_semaphore;
   Thread_queue_Context  queue_context;
+  uintptr_t             flags;
+  Semaphore_Variant     variant;
   Status_Control        status;
 
   _Objects_Allocator_lock();
@@ -48,8 +50,10 @@ rtems_status_code rtems_semaphore_delete(
     &the_semaphore->Core_control.Wait_queue,
     &queue_context
   );
+  flags = _Semaphore_Get_flags( the_semaphore );
+  variant = _Semaphore_Get_variant( flags );
 
-  switch ( the_semaphore->variant ) {
+  switch ( variant ) {
     case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
     case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
@@ -71,8 +75,8 @@ rtems_status_code rtems_semaphore_delete(
 #endif
     default:
       _Assert(
-        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
-          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
+        variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || variant == SEMAPHORE_VARIANT_COUNTING
       );
       status = STATUS_SUCCESSFUL;
       break;
@@ -89,7 +93,7 @@ rtems_status_code rtems_semaphore_delete(
 
   _Objects_Close( &_Semaphore_Information, &the_semaphore->Object );
 
-  switch ( the_semaphore->variant ) {
+  switch ( variant ) {
 #if defined(RTEMS_SMP)
     case SEMAPHORE_VARIANT_MRSP:
       _MRSP_Destroy( &the_semaphore->Core_control.MRSP, &queue_context );
@@ -97,15 +101,15 @@ rtems_status_code rtems_semaphore_delete(
 #endif
     default:
       _Assert(
-        the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
-          || 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
+        variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
+          || variant == SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING
+          || variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
+          || variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || variant == SEMAPHORE_VARIANT_COUNTING
       );
       _Thread_queue_Flush_critical(
         &the_semaphore->Core_control.Wait_queue.Queue,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         _Thread_queue_Flush_status_object_was_deleted,
         &queue_context
       );
diff --git a/cpukit/rtems/src/semflush.c b/cpukit/rtems/src/semflush.c
index b7e8786f76..13c0e8d387 100644
--- a/cpukit/rtems/src/semflush.c
+++ b/cpukit/rtems/src/semflush.c
@@ -24,6 +24,8 @@ rtems_status_code rtems_semaphore_flush( rtems_id id )
 {
   Semaphore_Control    *the_semaphore;
   Thread_queue_Context  queue_context;
+  uintptr_t             flags;
+  Semaphore_Variant     variant;
 
   the_semaphore = _Semaphore_Get( id, &queue_context );
 
@@ -45,8 +47,10 @@ rtems_status_code rtems_semaphore_flush( rtems_id id )
     &queue_context,
     _Semaphore_MP_Send_object_was_deleted
   );
+  flags = _Semaphore_Get_flags( the_semaphore );
+  variant = _Semaphore_Get_variant( flags );
 
-  switch ( the_semaphore->variant ) {
+  switch ( variant ) {
 #if defined(RTEMS_SMP)
     case SEMAPHORE_VARIANT_MRSP:
       _Thread_queue_Release(
@@ -57,15 +61,15 @@ rtems_status_code rtems_semaphore_flush( rtems_id id )
 #endif
     default:
       _Assert(
-        the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
-          || 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
+        variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
+          || variant == SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING
+          || variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
+          || variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || variant == SEMAPHORE_VARIANT_COUNTING
       );
       _Thread_queue_Flush_critical(
         &the_semaphore->Core_control.Wait_queue.Queue,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         _Thread_queue_Flush_status_unavailable,
         &queue_context
       );
diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c
index 2f73166df0..5916cf5e69 100644
--- a/cpukit/rtems/src/semobtain.c
+++ b/cpukit/rtems/src/semobtain.c
@@ -58,6 +58,8 @@ rtems_status_code rtems_semaphore_obtain(
   Thread_queue_Context  queue_context;
   Thread_Control       *executing;
   bool                  wait;
+  uintptr_t             flags;
+  Semaphore_Variant     variant;
   Status_Control        status;
 
   the_semaphore = _Semaphore_Get( id, &queue_context );
@@ -79,7 +81,10 @@ rtems_status_code rtems_semaphore_obtain(
     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
   }
 
-  switch ( the_semaphore->variant ) {
+  flags = _Semaphore_Get_flags( the_semaphore );
+  variant = _Semaphore_Get_variant( flags );
+
+  switch ( variant ) {
     case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
       status = _CORE_recursive_mutex_Seize(
         &the_semaphore->Core_control.Mutex.Recursive,
@@ -102,7 +107,7 @@ rtems_status_code rtems_semaphore_obtain(
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
       status = _CORE_recursive_mutex_Seize(
         &the_semaphore->Core_control.Mutex.Recursive,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         executing,
         wait,
         _CORE_recursive_mutex_Seize_nested,
@@ -121,12 +126,12 @@ rtems_status_code rtems_semaphore_obtain(
 #endif
     default:
       _Assert(
-        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
-          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
+        variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || variant == SEMAPHORE_VARIANT_COUNTING
       );
       status = _CORE_semaphore_Seize(
         &the_semaphore->Core_control.Semaphore,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         executing,
         wait,
         &queue_context
diff --git a/cpukit/rtems/src/semrelease.c b/cpukit/rtems/src/semrelease.c
index 40860a1ea9..33767f9eb3 100644
--- a/cpukit/rtems/src/semrelease.c
+++ b/cpukit/rtems/src/semrelease.c
@@ -29,6 +29,8 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
   Semaphore_Control    *the_semaphore;
   Thread_queue_Context  queue_context;
   Thread_Control       *executing;
+  uintptr_t             flags;
+  Semaphore_Variant     variant;
   Status_Control        status;
 
   the_semaphore = _Semaphore_Get( id, &queue_context );
@@ -47,8 +49,10 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
     &queue_context,
     _Semaphore_Core_mutex_mp_support
   );
+  flags = _Semaphore_Get_flags( the_semaphore );
+  variant = _Semaphore_Get_variant( flags );
 
-  switch ( the_semaphore->variant ) {
+  switch ( variant ) {
     case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
       status = _CORE_recursive_mutex_Surrender(
         &the_semaphore->Core_control.Mutex.Recursive,
@@ -67,7 +71,7 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
     case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
       status = _CORE_recursive_mutex_Surrender(
         &the_semaphore->Core_control.Mutex.Recursive,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         executing,
         &queue_context
       );
@@ -75,7 +79,7 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
     case SEMAPHORE_VARIANT_SIMPLE_BINARY:
       status = _CORE_semaphore_Surrender(
         &the_semaphore->Core_control.Semaphore,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         1,
         &queue_context
       );
@@ -95,10 +99,10 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
       break;
 #endif
     default:
-      _Assert( the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING );
+      _Assert( variant == SEMAPHORE_VARIANT_COUNTING );
       status = _CORE_semaphore_Surrender(
         &the_semaphore->Core_control.Semaphore,
-        _Semaphore_Get_operations( the_semaphore ),
+        _Semaphore_Get_operations( flags ),
         UINT32_MAX,
         &queue_context
       );
diff --git a/cpukit/rtems/src/semsetpriority.c b/cpukit/rtems/src/semsetpriority.c
index 508dca5a12..772f30c0c9 100644
--- a/cpukit/rtems/src/semsetpriority.c
+++ b/cpukit/rtems/src/semsetpriority.c
@@ -47,6 +47,7 @@ static rtems_status_code _Semaphore_Set_priority(
   Priority_Control   core_priority;
   Priority_Control   old_priority;
   Per_CPU_Control   *cpu_self;
+  Semaphore_Variant  variant;
 
   core_priority = _RTEMS_Priority_To_core( scheduler, new_priority, &valid );
   if ( new_priority != RTEMS_CURRENT_PRIORITY && !valid ) {
@@ -59,8 +60,9 @@ static rtems_status_code _Semaphore_Set_priority(
     &the_semaphore->Core_control.Wait_queue,
     queue_context
   );
+  variant = _Semaphore_Get_variant( _Semaphore_Get_flags( the_semaphore ) );
 
-  switch ( the_semaphore->variant ) {
+  switch ( variant ) {
     case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
       sc = _Semaphore_Is_scheduler_valid(
         &the_semaphore->Core_control.Mutex,
@@ -100,10 +102,10 @@ static rtems_status_code _Semaphore_Set_priority(
 #endif
     default:
       _Assert(
-        the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
-          || the_semaphore->variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
-          || the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
-          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
+        variant == SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY
+          || variant == SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL
+          || variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+          || variant == SEMAPHORE_VARIANT_COUNTING
       );
       old_priority = 0;
       sc = RTEMS_NOT_DEFINED;
-- 
2.16.4



More information about the devel mailing list