rtems: Optimize semaphore control block

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

Update #3833.
This commit is contained in:
Sebastian Huber
2019-12-07 11:48:36 +01:00
parent cc466a53a1
commit 01f8c12ee5
9 changed files with 164 additions and 77 deletions

View File

@@ -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;
/**

View File

@@ -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;
}

View File

@@ -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 ),

View File

@@ -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;
}
#if defined(RTEMS_MULTIPROCESSING)
the_semaphore->is_global = _Attributes_Is_global( attribute_set );
flags = _Semaphore_Set_variant( 0, variant );
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;
#if defined(RTEMS_MULTIPROCESSING)
if ( _Attributes_Is_global( attribute_set ) ) {
bool ok;
ok = _Objects_MP_Allocate_and_open(
&_Semaphore_Information,
name,
the_semaphore->Object.id,
false
);
if ( !ok ) {
_Semaphore_Free( the_semaphore );
_Objects_Allocator_unlock();
return RTEMS_TOO_MANY;
}
flags = _Semaphore_Make_global( flags );
}
#endif
executing = _Thread_Get_executing();
the_semaphore->variant = variant;
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,

View File

@@ -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 );

View File

@@ -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
);

View File

@@ -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

View File

@@ -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
);

View File

@@ -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;