From 01f8c12ee57230fca1581e1b5be91f3decba0488 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sat, 7 Dec 2019 11:48:36 +0100 Subject: rtems: Optimize semaphore control block 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 | 26 ++++++++------ 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, 163 insertions(+), 76 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..44fec02b81 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 ); @@ -114,7 +118,7 @@ rtems_status_code rtems_semaphore_delete( } #if defined(RTEMS_MULTIPROCESSING) - if ( the_semaphore->is_global ) { + if ( _Semaphore_Is_global( flags ) ) { _Objects_MP_Close( &_Semaphore_Information, id ); 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; -- cgit v1.2.3