score: Add CORE mutex variants

Add CORE_recursive_mutex_Control and CORE_ceiling_mutex_Control to avoid
the run-time evaluation of attributes to figure out how a particular
mutex methods should behave.  Start with the no protocol variants.  This
eliminates the CORE_MUTEX_DISCIPLINES_FIFO and
CORE_MUTEX_DISCIPLINES_PRIORITY disciplines.
This commit is contained in:
Sebastian Huber
2016-05-30 16:16:23 +02:00
parent bbb3c5f331
commit 5a598ac99b
24 changed files with 508 additions and 170 deletions
+3 -2
View File
@@ -22,7 +22,7 @@ rtems_monitor_sema_canonical(
canonical_sema->attribute = rtems_sema->attribute_set;
canonical_sema->priority_ceiling =
rtems_sema->Core_control.mutex.Attributes.priority_ceiling;
rtems_sema->Core_control.Mutex.priority_ceiling;
canonical_sema->holder_id = 0;
@@ -33,8 +33,9 @@ rtems_monitor_sema_canonical(
}
else {
/* we have a binary semaphore (mutex) */
Thread_Control *holder = rtems_sema->Core_control.mutex.holder;
Thread_Control *holder;
holder = rtems_sema->Core_control.Mutex.Recursive.Mutex.holder;
if (holder != NULL) {
canonical_sema->holder_id = holder->Object.id;
canonical_sema->cur_count = 0;
+3 -3
View File
@@ -118,7 +118,7 @@ rtems_bsdnet_semaphore_release_recursive(void)
nest_count =
the_networkSemaphore ?
the_networkSemaphore->Core_control.mutex.nest_count : 0;
the_networkSemaphore->Core_control.Mutex.Recursive.Mutex.nest_count : 0;
for (i = 0; i < nest_count; ++i) {
rtems_bsdnet_semaphore_release();
}
@@ -378,7 +378,7 @@ rtems_bsdnet_semaphore_obtain (void)
_Thread_queue_Context_initialize(&queue_context);
_ISR_lock_ISR_disable(&queue_context.Lock_context);
status = _CORE_mutex_Seize (
&the_networkSemaphore->Core_control.mutex,
&the_networkSemaphore->Core_control.Mutex.Recursive.Mutex,
_Thread_Executing,
1, /* wait */
0, /* forever */
@@ -411,7 +411,7 @@ rtems_bsdnet_semaphore_release (void)
_Thread_queue_Context_initialize(&queue_context);
_ISR_lock_ISR_disable(&queue_context.Lock_context);
status = _CORE_mutex_Surrender (
&the_networkSemaphore->Core_control.mutex,
&the_networkSemaphore->Core_control.Mutex.Recursive.Mutex,
&queue_context
);
if (status != STATUS_SUCCESSFUL)
+27 -6
View File
@@ -35,14 +35,35 @@ extern "C" {
*/
/**@{**/
/*
* Data Structure used to manage a POSIX mutex
/**
* @brief The POSIX mutex control.
*/
typedef struct {
Objects_Control Object;
CORE_mutex_Control Mutex;
} POSIX_Mutex_Control;
/**
* @brief The object control.
*/
Objects_Control Object;
/**
* The most general mutex variant supported by a POSIX mutex.
*
* The priority inheritance or no protocol variants will use only parts of
* this structure.
*/
CORE_ceiling_mutex_Control Mutex;
/**
* @brief The protocol variant.
*
* @see POSIX_Mutex_Protocol.
*/
unsigned int protocol : 2;
/**
* @brief Indicates if this is a non-recursive or recursive mutex.
*/
unsigned int is_recursive : 1;
} POSIX_Mutex_Control;
/** @} */
@@ -28,6 +28,19 @@
extern "C" {
#endif
#define POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS &_Thread_queue_Operations_FIFO
/**
* @brief Supported POSIX mutex protocols.
*
* Must be in synchronization with POSIX_Mutex_Control::protocol.
*/
typedef enum {
POSIX_MUTEX_NO_PROTOCOL,
POSIX_MUTEX_PRIORITY_INHERIT,
POSIX_MUTEX_PRIORITY_CEILING
} POSIX_Mutex_Protocol;
/**
* The following defines the information control block used to manage
* this class of objects.
@@ -39,6 +52,28 @@ extern Objects_Information _POSIX_Mutex_Information;
*/
extern pthread_mutexattr_t _POSIX_Mutex_Default_attributes;
RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Acquire_critical(
POSIX_Mutex_Control *the_mutex,
Thread_queue_Context *queue_context
)
{
_CORE_mutex_Acquire_critical(
&the_mutex->Mutex.Recursive.Mutex,
queue_context
);
}
RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Release(
POSIX_Mutex_Control *the_mutex,
Thread_queue_Context *queue_context
)
{
_CORE_mutex_Release(
&the_mutex->Mutex.Recursive.Mutex,
queue_context
);
}
/**
* @brief POSIX Mutex Allocate
*
+7 -5
View File
@@ -37,21 +37,23 @@ int pthread_mutex_destroy(
the_mutex = _POSIX_Mutex_Get( mutex, &queue_context );
if ( the_mutex != NULL ) {
_CORE_mutex_Acquire_critical( &the_mutex->Mutex, &queue_context );
_POSIX_Mutex_Acquire_critical( the_mutex, &queue_context );
/*
* XXX: There is an error for the mutex being locked
* or being in use by a condition variable.
*/
if ( !_CORE_mutex_Is_locked( &the_mutex->Mutex ) ) {
if (
!_CORE_mutex_Is_locked( &the_mutex->Mutex.Recursive.Mutex )
) {
_Objects_Close( &_POSIX_Mutex_Information, &the_mutex->Object );
_CORE_mutex_Release( &the_mutex->Mutex, &queue_context );
_CORE_mutex_Destroy( &the_mutex->Mutex );
_POSIX_Mutex_Release( the_mutex, &queue_context );
_CORE_mutex_Destroy( &the_mutex->Mutex.Recursive.Mutex );
_POSIX_Mutex_Free( the_mutex );
eno = 0;
} else {
_CORE_mutex_Release( &the_mutex->Mutex, &queue_context );
_POSIX_Mutex_Release( the_mutex, &queue_context );
eno = EBUSY;
}
} else {
+3 -3
View File
@@ -43,13 +43,13 @@ int pthread_mutex_getprioceiling(
return EINVAL;
}
_CORE_mutex_Acquire_critical( &the_mutex->Mutex, &queue_context );
_POSIX_Mutex_Acquire_critical( the_mutex, &queue_context );
*prioceiling = _POSIX_Priority_From_core(
the_mutex->Mutex.Attributes.priority_ceiling
the_mutex->Mutex.Recursive.Mutex.Attributes.priority_ceiling
);
_CORE_mutex_Release( &the_mutex->Mutex, &queue_context );
_POSIX_Mutex_Release( the_mutex, &queue_context );
return 0;
}
+39 -20
View File
@@ -33,10 +33,9 @@ int pthread_mutex_init(
const pthread_mutexattr_t *attr
)
{
POSIX_Mutex_Control *the_mutex;
CORE_mutex_Attributes *the_mutex_attr;
const pthread_mutexattr_t *the_attr;
CORE_mutex_Disciplines the_discipline;
POSIX_Mutex_Control *the_mutex;
const pthread_mutexattr_t *the_attr;
POSIX_Mutex_Protocol protocol;
if ( attr ) the_attr = attr;
else the_attr = &_POSIX_Mutex_Default_attributes;
@@ -75,13 +74,13 @@ int pthread_mutex_init(
*/
switch ( the_attr->protocol ) {
case PTHREAD_PRIO_NONE:
the_discipline = CORE_MUTEX_DISCIPLINES_FIFO;
protocol = POSIX_MUTEX_NO_PROTOCOL;
break;
case PTHREAD_PRIO_INHERIT:
the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
protocol = POSIX_MUTEX_PRIORITY_INHERIT;
break;
case PTHREAD_PRIO_PROTECT:
the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
protocol = POSIX_MUTEX_PRIORITY_CEILING;
break;
default:
return EINVAL;
@@ -117,21 +116,41 @@ int pthread_mutex_init(
return EAGAIN;
}
the_mutex_attr = &the_mutex->Mutex.Attributes;
the_mutex->protocol = protocol;
the_mutex->is_recursive = ( the_attr->type == PTHREAD_MUTEX_RECURSIVE );
if ( the_attr->type == PTHREAD_MUTEX_RECURSIVE )
the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
else
the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
the_mutex_attr->only_owner_release = true;
the_mutex_attr->priority_ceiling =
_POSIX_Priority_To_core( the_attr->prio_ceiling );
the_mutex_attr->discipline = the_discipline;
if ( protocol == POSIX_MUTEX_NO_PROTOCOL ) {
_CORE_recursive_mutex_Initialize(
&the_mutex->Mutex.Recursive
);
} else {
CORE_mutex_Attributes the_mutex_attr;
/*
* Must be initialized to unlocked.
*/
_CORE_mutex_Initialize( &the_mutex->Mutex, NULL, the_mutex_attr, false );
if ( the_attr->type == PTHREAD_MUTEX_RECURSIVE ) {
the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
} else {
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.
*/
_CORE_mutex_Initialize(
&the_mutex->Mutex.Recursive.Mutex,
NULL,
&the_mutex_attr,
false
);
}
_Objects_Open_u32( &_POSIX_Mutex_Information, &the_mutex->Object, 0 );
+50 -9
View File
@@ -21,16 +21,39 @@
#include <rtems/posix/muteximpl.h>
#include <rtems/posix/posixapi.h>
THREAD_QUEUE_OBJECT_ASSERT( POSIX_Mutex_Control, Mutex.Wait_queue );
THREAD_QUEUE_OBJECT_ASSERT(
POSIX_Mutex_Control,
Mutex.Recursive.Mutex.Wait_queue
);
static Status_Control _POSIX_Mutex_Lock_nested(
CORE_recursive_mutex_Control *the_recursive_mutex
)
{
POSIX_Mutex_Control *the_mutex;
the_mutex = RTEMS_CONTAINER_OF(
the_recursive_mutex,
POSIX_Mutex_Control,
Mutex.Recursive
);
if ( the_mutex->is_recursive ) {
return _CORE_recursive_mutex_Seize_nested( the_recursive_mutex );
} else {
return STATUS_NESTING_NOT_ALLOWED;
}
}
int _POSIX_Mutex_Lock_support(
pthread_mutex_t *mutex,
bool blocking,
bool wait,
Watchdog_Interval timeout
)
{
POSIX_Mutex_Control *the_mutex;
Thread_queue_Context queue_context;
Thread_Control *executing;
Status_Control status;
the_mutex = _POSIX_Mutex_Get( mutex, &queue_context );
@@ -39,12 +62,30 @@ int _POSIX_Mutex_Lock_support(
return EINVAL;
}
status = _CORE_mutex_Seize(
&the_mutex->Mutex,
_Thread_Executing,
blocking,
timeout,
&queue_context
);
executing = _Thread_Executing;
switch ( the_mutex->protocol ) {
case POSIX_MUTEX_NO_PROTOCOL:
status = _CORE_recursive_mutex_Seize_no_protocol(
&the_mutex->Mutex.Recursive,
POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS,
executing,
wait,
timeout,
_POSIX_Mutex_Lock_nested,
&queue_context
);
break;
default:
status = _CORE_mutex_Seize(
&the_mutex->Mutex.Recursive.Mutex,
executing,
wait,
timeout,
&queue_context
);
break;
}
return _POSIX_Get_error( status );
}
+3 -2
View File
@@ -57,9 +57,10 @@ int pthread_mutex_setprioceiling(
_Assert( the_mutex != NULL );
*old_ceiling = _POSIX_Priority_From_core(
the_mutex->Mutex.Attributes.priority_ceiling
the_mutex->Mutex.Recursive.Mutex.Attributes.priority_ceiling
);
the_mutex->Mutex.Attributes.priority_ceiling = the_priority;
the_mutex->Mutex.Recursive.Mutex.Attributes.priority_ceiling =
the_priority;
error = pthread_mutex_unlock( mutex );
_Assert( error == 0 );
+20 -1
View File
@@ -33,6 +33,7 @@ int pthread_mutex_unlock(
{
POSIX_Mutex_Control *the_mutex;
Thread_queue_Context queue_context;
Thread_Control *executing;
Status_Control status;
the_mutex = _POSIX_Mutex_Get( mutex, &queue_context );
@@ -41,6 +42,24 @@ int pthread_mutex_unlock(
return EINVAL;
}
status = _CORE_mutex_Surrender( &the_mutex->Mutex, &queue_context );
executing = _Thread_Executing;
switch ( the_mutex->protocol ) {
case POSIX_MUTEX_NO_PROTOCOL:
status = _CORE_recursive_mutex_Surrender_no_protocol(
&the_mutex->Mutex.Recursive,
POSIX_MUTEX_NO_PROTOCOL_TQ_OPERATIONS,
executing,
&queue_context
);
break;
default:
status = _CORE_mutex_Surrender(
&the_mutex->Mutex.Recursive.Mutex,
&queue_context
);
break;
}
return _POSIX_Get_error( status );
}
+1 -1
View File
@@ -83,7 +83,7 @@ typedef struct {
* This is the SuperCore Mutex instance associated with this Classic
* API Semaphore instance.
*/
CORE_mutex_Control mutex;
CORE_ceiling_mutex_Control Mutex;
/**
* This is the SuperCore Semaphore instance associated with this Classic
@@ -26,8 +26,14 @@
extern "C" {
#endif
/**
* @brief Classic semaphore variants.
*
* Must be in synchronization with Semaphore_Control::variant.
*/
typedef enum {
SEMAPHORE_VARIANT_MUTEX,
SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL,
SEMAPHORE_VARIANT_SIMPLE_BINARY,
SEMAPHORE_VARIANT_COUNTING
#if defined(RTEMS_SMP)
+31 -26
View File
@@ -63,6 +63,7 @@ rtems_status_code rtems_semaphore_create(
{
Semaphore_Control *the_semaphore;
CORE_mutex_Attributes the_mutex_attr;
Thread_Control *executing;
Status_Control status;
if ( !rtems_is_name_valid( name ) )
@@ -136,6 +137,7 @@ rtems_status_code rtems_semaphore_create(
#endif
the_semaphore->attribute_set = attribute_set;
executing = _Thread_Get_executing();
if ( _Attributes_Is_priority( attribute_set ) ) {
the_semaphore->discipline = SEMAPHORE_DISCIPLINE_PRIORITY;
@@ -163,43 +165,46 @@ rtems_status_code rtems_semaphore_create(
status = _MRSP_Initialize(
&the_semaphore->Core_control.mrsp,
priority_ceiling,
_Thread_Get_executing(),
executing,
count != 1
);
#endif
} else if (
!_Attributes_Is_inherit_priority( attribute_set )
&& !_Attributes_Is_priority_ceiling( attribute_set )
) {
_Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
_CORE_recursive_mutex_Initialize(
&the_semaphore->Core_control.Mutex.Recursive
);
if ( count == 0 ) {
_CORE_mutex_Set_owner(
&the_semaphore->Core_control.Mutex.Recursive.Mutex,
executing
);
}
status = STATUS_SUCCESSFUL;
} else {
_Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
the_semaphore->variant = SEMAPHORE_VARIANT_MUTEX;
_Assert( _Attributes_Is_binary_semaphore( attribute_set ) );
/*
* It is either simple binary semaphore or a more powerful mutex
* style binary semaphore. This is the mutex style.
*/
if ( _Attributes_Is_priority( attribute_set ) )
the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY;
else
the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
the_mutex_attr.priority_ceiling = _RTEMS_tasks_Priority_to_Core(
priority_ceiling
);
the_mutex_attr.priority_ceiling =
_RTEMS_tasks_Priority_to_Core( priority_ceiling );
the_mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
the_mutex_attr.only_owner_release = false;
if ( the_mutex_attr.discipline == CORE_MUTEX_DISCIPLINES_PRIORITY ) {
if ( _Attributes_Is_inherit_priority( attribute_set ) ) {
the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
the_mutex_attr.only_owner_release = true;
} else if ( _Attributes_Is_priority_ceiling( attribute_set ) ) {
the_mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
the_mutex_attr.only_owner_release = true;
}
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,
_Thread_Get_executing(),
&the_semaphore->Core_control.Mutex.Recursive.Mutex,
executing,
&the_mutex_attr,
count != 1
);
+7 -1
View File
@@ -51,7 +51,12 @@ rtems_status_code rtems_semaphore_delete(
switch ( the_semaphore->variant ) {
case SEMAPHORE_VARIANT_MUTEX:
if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) ) {
case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
if (
_CORE_mutex_Is_locked(
&the_semaphore->Core_control.Mutex.Recursive.Mutex
)
) {
status = STATUS_RESOURCE_IN_USE;
} else {
status = STATUS_SUCCESSFUL;
@@ -92,6 +97,7 @@ rtems_status_code rtems_semaphore_delete(
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
);
+1
View File
@@ -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_NO_PROTOCOL
|| the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
|| the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
);
+13 -2
View File
@@ -29,7 +29,7 @@ THREAD_QUEUE_OBJECT_ASSERT(
THREAD_QUEUE_OBJECT_ASSERT(
Semaphore_Control,
Core_control.mutex.Wait_queue
Core_control.Mutex.Recursive.Mutex.Wait_queue
);
THREAD_QUEUE_OBJECT_ASSERT(
@@ -83,13 +83,24 @@ rtems_status_code rtems_semaphore_obtain(
#endif
case SEMAPHORE_VARIANT_MUTEX:
status = _CORE_mutex_Seize(
&the_semaphore->Core_control.mutex,
&the_semaphore->Core_control.Mutex.Recursive.Mutex,
executing,
wait,
timeout,
&queue_context
);
break;
case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
status = _CORE_recursive_mutex_Seize_no_protocol(
&the_semaphore->Core_control.Mutex.Recursive,
_Semaphore_Get_operations( the_semaphore ),
executing,
wait,
timeout,
_CORE_recursive_mutex_Seize_nested,
&queue_context
);
break;
default:
_Assert(
the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
+9 -1
View File
@@ -57,10 +57,18 @@ rtems_status_code rtems_semaphore_release( rtems_id id )
#endif
case SEMAPHORE_VARIANT_MUTEX:
status = _CORE_mutex_Surrender(
&the_semaphore->Core_control.mutex,
&the_semaphore->Core_control.Mutex.Recursive.Mutex,
&queue_context
);
break;
case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
_CORE_recursive_mutex_Surrender_no_protocol_classic(
&the_semaphore->Core_control.Mutex.Recursive,
_Semaphore_Get_operations( the_semaphore ),
&queue_context
);
status = STATUS_SUCCESSFUL;
break;
case SEMAPHORE_VARIANT_SIMPLE_BINARY:
status = _CORE_semaphore_Surrender(
&the_semaphore->Core_control.semaphore,
+2 -1
View File
@@ -54,8 +54,9 @@ static rtems_status_code _Semaphore_Set_priority(
} else
#endif
if ( _Attributes_Is_priority_ceiling( attribute_set ) ) {
CORE_mutex_Control *mutex = &the_semaphore->Core_control.mutex;
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;
+30 -13
View File
@@ -47,10 +47,6 @@ extern "C" {
* This enumerated type defines the blocking disciplines for a mutex.
*/
typedef enum {
/** This specifies that threads will wait for the mutex in FIFO order. */
CORE_MUTEX_DISCIPLINES_FIFO,
/** This specifies that threads will wait for the mutex in priority order. */
CORE_MUTEX_DISCIPLINES_PRIORITY,
/** This specifies that threads will wait for the mutex in priority order.
* Additionally, the Priority Inheritance Protocol will be in effect.
*/
@@ -100,10 +96,6 @@ typedef struct {
* be when attempting to acquire the mutex when it is already locked.
*/
CORE_mutex_Nesting_behaviors lock_nesting_behavior;
/** When this field is true, then only the thread that locked the mutex
* is allowed to unlock it.
*/
bool only_owner_release;
/** This field indicates whether threads waiting on the mutex block in
* FIFO or priority order.
*/
@@ -125,11 +117,6 @@ typedef struct {
*/
Thread_queue_Control Wait_queue;
/**
* @brief The thread queue operations according to the blocking discipline.
*/
const Thread_queue_Operations *operations;
/** This element is the set of attributes which define this instance's
* behavior.
*/
@@ -145,6 +132,36 @@ typedef struct {
Thread_Control *holder;
} CORE_mutex_Control;
/**
* @brief The recursive mutex control.
*/
typedef struct {
/**
* @brief The plain non-recursive mutex.
*/
CORE_mutex_Control Mutex;
/**
* @brief The nest level in case of a recursive seize.
*/
unsigned int nest_level;
} CORE_recursive_mutex_Control;
/**
* @brief The recursive mutex control with priority ceiling protocol support.
*/
typedef struct {
/**
* @brief The plain recursive mutex.
*/
CORE_recursive_mutex_Control Recursive;
/**
* @brief The priority ceiling value for the mutex owner.
*/
Priority_Control priority_ceiling;
} CORE_ceiling_mutex_Control;
/**@}*/
#ifdef __cplusplus
+159 -20
View File
@@ -33,6 +33,8 @@ extern "C" {
*/
/**@{**/
#define CORE_MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
/**
* @brief Initializes the mutex based on the parameters passed.
*
@@ -100,6 +102,13 @@ Status_Control _CORE_mutex_Seize_interrupt_blocking(
Thread_queue_Context *queue_context
);
RTEMS_INLINE_ROUTINE Thread_Control *_CORE_mutex_Get_owner(
const CORE_mutex_Control *the_mutex
)
{
return the_mutex->holder;
}
/**
* @brief Is mutex locked.
*
@@ -115,7 +124,7 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_locked(
const CORE_mutex_Control *the_mutex
)
{
return the_mutex->holder != NULL;
return _CORE_mutex_Get_owner( the_mutex ) != NULL;
}
/**
@@ -180,10 +189,7 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_mutex_Seize_interrupt_trylock(
if ( !_CORE_mutex_Is_locked( the_mutex ) ) {
the_mutex->holder = executing;
the_mutex->nest_count = 1;
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ){
executing->resource_count++;
}
++executing->resource_count;
if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
_CORE_mutex_Release( the_mutex, queue_context );
@@ -309,35 +315,168 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_mutex_Seize(
);
}
Status_Control _CORE_mutex_Seize_no_protocol_slow(
CORE_mutex_Control *the_mutex,
const Thread_queue_Operations *operations,
Thread_Control *executing,
bool wait,
Watchdog_Interval timeout,
Thread_queue_Context *queue_context
);
Status_Control _CORE_mutex_Surrender(
CORE_mutex_Control *the_mutex,
Thread_queue_Context *queue_context
);
RTEMS_INLINE_ROUTINE void _CORE_mutex_Set_owner(
CORE_mutex_Control *the_mutex,
Thread_Control *owner
)
{
the_mutex->holder = owner;
}
RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_owner(
const CORE_mutex_Control *the_mutex,
const Thread_Control *the_thread
)
{
return the_mutex->holder == the_thread;
return _CORE_mutex_Get_owner( the_mutex ) == the_thread;
}
/**
* @brief Does core mutex use FIFO blocking.
*
* This routine returns true if the mutex's wait discipline is FIFO and false
* otherwise.
*
* @param[in] the_attribute is the attribute set of the mutex.
*
* @retval true The mutex is using FIFO blocking order.
* @retval false The mutex is not using FIFO blocking order.
*/
RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_fifo(
const CORE_mutex_Attributes *the_attribute
RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize(
CORE_recursive_mutex_Control *the_mutex
)
{
return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_FIFO;
_Thread_queue_Initialize( &the_mutex->Mutex.Wait_queue );
the_mutex->Mutex.holder = NULL;
the_mutex->nest_level = 0;
}
RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Seize_nested(
CORE_recursive_mutex_Control *the_mutex
)
{
++the_mutex->nest_level;
return STATUS_SUCCESSFUL;
}
RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Seize_no_protocol(
CORE_recursive_mutex_Control *the_mutex,
const Thread_queue_Operations *operations,
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->Mutex, queue_context );
owner = _CORE_mutex_Get_owner( &the_mutex->Mutex );
if ( owner == NULL ) {
_CORE_mutex_Set_owner( &the_mutex->Mutex, executing );
_CORE_mutex_Release( &the_mutex->Mutex, queue_context );
return STATUS_SUCCESSFUL;
}
if ( owner == executing ) {
Status_Control status;
status = ( *nested )( the_mutex );
_CORE_mutex_Release( &the_mutex->Mutex, queue_context );
return status;
}
return _CORE_mutex_Seize_no_protocol_slow(
&the_mutex->Mutex,
operations,
executing,
wait,
timeout,
queue_context
);
}
RTEMS_INLINE_ROUTINE void
_CORE_recursive_mutex_Surrender_no_protocol_finalize(
CORE_recursive_mutex_Control *the_mutex,
const Thread_queue_Operations *operations,
Thread_queue_Context *queue_context
)
{
unsigned int nest_level;
Thread_Control *new_owner;
nest_level = the_mutex->nest_level;
if ( nest_level > 0 ) {
the_mutex->nest_level = nest_level - 1;
_CORE_mutex_Release( &the_mutex->Mutex, queue_context );
return;
}
new_owner = _Thread_queue_First_locked(
&the_mutex->Mutex.Wait_queue,
operations
);
_CORE_mutex_Set_owner( &the_mutex->Mutex, new_owner );
if ( new_owner == NULL ) {
_CORE_mutex_Release( &the_mutex->Mutex, queue_context );
return;
}
_Thread_queue_Extract_critical(
&the_mutex->Mutex.Wait_queue.Queue,
operations,
new_owner,
queue_context
);
}
RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender_no_protocol(
CORE_recursive_mutex_Control *the_mutex,
const Thread_queue_Operations *operations,
Thread_Control *executing,
Thread_queue_Context *queue_context
)
{
_CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
if ( !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing ) ) {
_CORE_mutex_Release( &the_mutex->Mutex, queue_context );
return STATUS_NOT_OWNER;
}
_CORE_recursive_mutex_Surrender_no_protocol_finalize(
the_mutex,
operations,
queue_context
);
return STATUS_SUCCESSFUL;
}
/*
* The Classic no protocol recursive mutex has the nice property that everyone
* can release it.
*/
RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Surrender_no_protocol_classic(
CORE_recursive_mutex_Control *the_mutex,
const Thread_queue_Operations *operations,
Thread_queue_Context *queue_context
)
{
_CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
_CORE_recursive_mutex_Surrender_no_protocol_finalize(
the_mutex,
operations,
queue_context
);
}
/** @} */
-1
View File
@@ -49,7 +49,6 @@ void _API_Mutex_Allocate(
CORE_mutex_Attributes attr = {
CORE_MUTEX_NESTING_ACQUIRES,
true,
CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
0
};
+25 -32
View File
@@ -39,42 +39,41 @@ Status_Control _CORE_mutex_Initialize(
the_mutex->Attributes = *the_mutex_attributes;
if ( initially_locked ) {
bool is_priority_ceiling =
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes );
bool is_priority_ceiling;
Priority_Control ceiling;
Per_CPU_Control *cpu_self;
the_mutex->nest_count = 1;
the_mutex->holder = executing;
if ( is_priority_ceiling ||
_CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
Priority_Control ceiling = the_mutex->Attributes.priority_ceiling;
Per_CPU_Control *cpu_self;
/* The mutex initialization is only protected by the allocator lock */
cpu_self = _Thread_Dispatch_disable();
/* 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 ) {
/*
* 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.
* There is no need to undo the previous work since this error aborts
* the object creation.
*/
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 );
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;
@@ -82,11 +81,5 @@ Status_Control _CORE_mutex_Initialize(
_Thread_queue_Initialize( &the_mutex->Wait_queue );
if ( _CORE_mutex_Is_fifo( the_mutex_attributes ) ) {
the_mutex->operations = &_Thread_queue_Operations_FIFO;
} else {
the_mutex->operations = &_Thread_queue_Operations_priority;
}
return STATUS_SUCCESSFUL;
}
+26 -1
View File
@@ -68,7 +68,7 @@ Status_Control _CORE_mutex_Seize_interrupt_blocking(
_Thread_queue_Enqueue_critical(
&the_mutex->Wait_queue.Queue,
the_mutex->operations,
CORE_MUTEX_TQ_OPERATIONS,
executing,
STATES_WAITING_FOR_MUTEX,
timeout,
@@ -82,3 +82,28 @@ Status_Control _CORE_mutex_Seize_interrupt_blocking(
return _Thread_Wait_get_status( executing );
}
Status_Control _CORE_mutex_Seize_no_protocol_slow(
CORE_mutex_Control *the_mutex,
const Thread_queue_Operations *operations,
Thread_Control *executing,
bool wait,
Watchdog_Interval timeout,
Thread_queue_Context *queue_context
)
{
if ( wait ) {
_Thread_queue_Context_set_expected_level( queue_context, 1 );
_Thread_queue_Enqueue_critical(
&the_mutex->Wait_queue.Queue,
operations,
executing,
STATES_WAITING_FOR_MUTEX,
timeout,
queue_context
);
return _Thread_Wait_get_status( executing );
} else {
_CORE_mutex_Release( the_mutex, queue_context );
return STATUS_UNAVAILABLE;
}
}
+8 -20
View File
@@ -34,18 +34,12 @@ Status_Control _CORE_mutex_Surrender(
holder = the_mutex->holder;
/*
* The following code allows a thread (or ISR) other than the thread
* which acquired the mutex to release that mutex. This is only
* allowed when the mutex in quetion is FIFO or simple Priority
* discipline. But Priority Ceiling or Priority Inheritance mutexes
* must be released by the thread which acquired them.
* Priority Ceiling or Priority Inheritance mutexes must be released by the
* thread which acquired them.
*/
if ( the_mutex->Attributes.only_owner_release ) {
if ( !_Thread_Is_executing( holder ) ) {
_ISR_lock_ISR_enable( &queue_context->Lock_context );
return STATUS_NOT_OWNER;
}
if ( !_Thread_Is_executing( holder ) ) {
_ISR_lock_ISR_enable( &queue_context->Lock_context );
return STATUS_NOT_OWNER;
}
_CORE_mutex_Acquire_critical( the_mutex, queue_context );
@@ -88,10 +82,7 @@ Status_Control _CORE_mutex_Surrender(
* Formally release the mutex before possibly transferring it to a
* blocked thread.
*/
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
holder->resource_count--;
}
holder->resource_count--;
the_mutex->holder = NULL;
/*
@@ -101,7 +92,7 @@ Status_Control _CORE_mutex_Surrender(
if (
( the_thread = _Thread_queue_First_locked(
&the_mutex->Wait_queue,
the_mutex->operations
CORE_MUTEX_TQ_OPERATIONS
)
)
) {
@@ -118,7 +109,7 @@ Status_Control _CORE_mutex_Surrender(
*/
unblock = _Thread_queue_Extract_locked(
&the_mutex->Wait_queue.Queue,
the_mutex->operations,
CORE_MUTEX_TQ_OPERATIONS,
the_thread,
queue_context
);
@@ -128,9 +119,6 @@ Status_Control _CORE_mutex_Surrender(
#endif
{
switch ( the_mutex->Attributes.discipline ) {
case CORE_MUTEX_DISCIPLINES_FIFO:
case CORE_MUTEX_DISCIPLINES_PRIORITY:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
the_thread->resource_count++;
_Thread_queue_Boost_priority( &the_mutex->Wait_queue.Queue, the_thread );