summaryrefslogtreecommitdiffstats
path: root/cpukit/posix
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-27 08:02:03 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-30 16:16:23 +0200
commit5a598ac99b0de720a04afc5e2ac6764117589b90 (patch)
tree811d57df33c0f4fcc1cce61095cb5c0a33eadd7c /cpukit/posix
parentposix: Delete POSIX_Mutex_Protocol::process_shared (diff)
downloadrtems-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.h33
-rw-r--r--cpukit/posix/include/rtems/posix/muteximpl.h35
-rw-r--r--cpukit/posix/src/mutexdestroy.c12
-rw-r--r--cpukit/posix/src/mutexgetprioceiling.c6
-rw-r--r--cpukit/posix/src/mutexinit.c63
-rw-r--r--cpukit/posix/src/mutexlocksupp.c59
-rw-r--r--cpukit/posix/src/mutexsetprioceiling.c5
-rw-r--r--cpukit/posix/src/mutexunlock.c21
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 );
}