summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-27 15:41:41 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-30 16:16:23 +0200
commit33e250c9fa370f620ddbc5850342d5a90b123524 (patch)
treea2f4082a58231054f084e9a77aa0af4e3111662d
parent5a598ac99b0de720a04afc5e2ac6764117589b90 (diff)
score: Rework CORE priority ceiling mutex
Rework seize and surrender methods to use CORE_ceiling_mutex_Control. This eliminates CORE_mutex_Disciplines.
-rw-r--r--cpukit/posix/src/mutexgetprioceiling.c2
-rw-r--r--cpukit/posix/src/mutexinit.c16
-rw-r--r--cpukit/posix/src/mutexlocksupp.c11
-rw-r--r--cpukit/posix/src/mutexsetprioceiling.c5
-rw-r--r--cpukit/posix/src/mutexunlock.c8
-rw-r--r--cpukit/rtems/include/rtems/rtems/semimpl.h1
-rw-r--r--cpukit/rtems/src/semcreate.c41
-rw-r--r--cpukit/rtems/src/semdelete.c2
-rw-r--r--cpukit/rtems/src/semflush.c1
-rw-r--r--cpukit/rtems/src/semobtain.c10
-rw-r--r--cpukit/rtems/src/semrelease.c12
-rw-r--r--cpukit/rtems/src/semsetpriority.c84
-rw-r--r--cpukit/score/include/rtems/score/coremutex.h24
-rw-r--r--cpukit/score/include/rtems/score/coremuteximpl.h250
-rw-r--r--cpukit/score/src/apimutex.c4
-rw-r--r--cpukit/score/src/coremutex.c32
-rw-r--r--cpukit/score/src/coremutexseize.c33
-rw-r--r--cpukit/score/src/coremutexsurrender.c16
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 <rtems/rtems/semimpl.h>
-#include <rtems/rtems/attrimpl.h>
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/schedulerimpl.h>
@@ -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
@@ -42,22 +42,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.
*
* This enumerated type defines the possible behaviors for
@@ -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
@@ -128,42 +128,6 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_locked(
}
/**
- * @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.
*
* This routine attempts 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;
}