diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-27 08:02:03 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-30 16:16:23 +0200 |
commit | 5a598ac99b0de720a04afc5e2ac6764117589b90 (patch) | |
tree | 811d57df33c0f4fcc1cce61095cb5c0a33eadd7c /cpukit/posix | |
parent | posix: Delete POSIX_Mutex_Protocol::process_shared (diff) | |
download | rtems-5a598ac99b0de720a04afc5e2ac6764117589b90.tar.bz2 |
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.
Diffstat (limited to 'cpukit/posix')
-rw-r--r-- | cpukit/posix/include/rtems/posix/mutex.h | 33 | ||||
-rw-r--r-- | cpukit/posix/include/rtems/posix/muteximpl.h | 35 | ||||
-rw-r--r-- | cpukit/posix/src/mutexdestroy.c | 12 | ||||
-rw-r--r-- | cpukit/posix/src/mutexgetprioceiling.c | 6 | ||||
-rw-r--r-- | cpukit/posix/src/mutexinit.c | 63 | ||||
-rw-r--r-- | cpukit/posix/src/mutexlocksupp.c | 59 | ||||
-rw-r--r-- | cpukit/posix/src/mutexsetprioceiling.c | 5 | ||||
-rw-r--r-- | cpukit/posix/src/mutexunlock.c | 21 |
8 files changed, 186 insertions, 48 deletions
diff --git a/cpukit/posix/include/rtems/posix/mutex.h b/cpukit/posix/include/rtems/posix/mutex.h index e1dfa34e8c..97ab138652 100644 --- a/cpukit/posix/include/rtems/posix/mutex.h +++ b/cpukit/posix/include/rtems/posix/mutex.h @@ -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; /** @} */ diff --git a/cpukit/posix/include/rtems/posix/muteximpl.h b/cpukit/posix/include/rtems/posix/muteximpl.h index 30cc19da7e..4957e207fb 100644 --- a/cpukit/posix/include/rtems/posix/muteximpl.h +++ b/cpukit/posix/include/rtems/posix/muteximpl.h @@ -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 * diff --git a/cpukit/posix/src/mutexdestroy.c b/cpukit/posix/src/mutexdestroy.c index 7fda7d3ac9..57e63937a9 100644 --- a/cpukit/posix/src/mutexdestroy.c +++ b/cpukit/posix/src/mutexdestroy.c @@ -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 { diff --git a/cpukit/posix/src/mutexgetprioceiling.c b/cpukit/posix/src/mutexgetprioceiling.c index 268457a73e..06eaf30764 100644 --- a/cpukit/posix/src/mutexgetprioceiling.c +++ b/cpukit/posix/src/mutexgetprioceiling.c @@ -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; } diff --git a/cpukit/posix/src/mutexinit.c b/cpukit/posix/src/mutexinit.c index d90b391c9d..f2912ead18 100644 --- a/cpukit/posix/src/mutexinit.c +++ b/cpukit/posix/src/mutexinit.c @@ -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; - - 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; - - /* - * Must be initialized to unlocked. - */ - _CORE_mutex_Initialize( &the_mutex->Mutex, NULL, the_mutex_attr, false ); + the_mutex->protocol = protocol; + the_mutex->is_recursive = ( the_attr->type == PTHREAD_MUTEX_RECURSIVE ); + + if ( protocol == POSIX_MUTEX_NO_PROTOCOL ) { + _CORE_recursive_mutex_Initialize( + &the_mutex->Mutex.Recursive + ); + } else { + CORE_mutex_Attributes the_mutex_attr; + + 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 ); diff --git a/cpukit/posix/src/mutexlocksupp.c b/cpukit/posix/src/mutexlocksupp.c index 6ecf87cb46..2499ae1ace 100644 --- a/cpukit/posix/src/mutexlocksupp.c +++ b/cpukit/posix/src/mutexlocksupp.c @@ -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 ); } diff --git a/cpukit/posix/src/mutexsetprioceiling.c b/cpukit/posix/src/mutexsetprioceiling.c index 20f14dc1f6..5d11edf294 100644 --- a/cpukit/posix/src/mutexsetprioceiling.c +++ b/cpukit/posix/src/mutexsetprioceiling.c @@ -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 ); diff --git a/cpukit/posix/src/mutexunlock.c b/cpukit/posix/src/mutexunlock.c index 1c3f2d83f4..b0ca33d154 100644 --- a/cpukit/posix/src/mutexunlock.c +++ b/cpukit/posix/src/mutexunlock.c @@ -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 ); } |