From 33e250c9fa370f620ddbc5850342d5a90b123524 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 27 May 2016 15:41:41 +0200 Subject: 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 06eaf30764..2df4776048 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 f2912ead18..6c5705b20b 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 2499ae1ace..cccb2d31b3 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 5d11edf294..96e8dbfeba 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 b0ca33d154..5404cef187 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 5b789d627d..9d82a12b3c 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 91f693c6c0..720fb63a0d 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 365d895362..a38d761320 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 6c1f4ddf2c..17c589f588 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 a7774d6f91..44507abefb 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 7cd92cfe0d..d92197b8f4 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 0a8c58cde2..57a5368353 100644 --- a/cpukit/rtems/src/semsetpriority.c +++ b/cpukit/rtems/src/semsetpriority.c @@ -17,7 +17,6 @@ #endif #include -#include #include #include @@ -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 173bb2efa6..704ea0da24 100644 --- a/cpukit/score/include/rtems/score/coremutex.h +++ b/cpukit/score/include/rtems/score/coremutex.h @@ -41,22 +41,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. * @@ -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 fc2ffd9020..f459743346 100644 --- a/cpukit/score/include/rtems/score/coremuteximpl.h +++ b/cpukit/score/include/rtems/score/coremuteximpl.h @@ -127,42 +127,6 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_locked( return _CORE_mutex_Get_owner( the_mutex ) != NULL; } -/** - * @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. * @@ -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 8af374aaef..e3c6e5a705 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 6f73c1bd16..9c6b7a8b93 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 596378fda6..ed5eb0aeec 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 2d976e0c22..5075e204c9 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; } -- cgit v1.2.3