[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