From 5870ac55678115857215a4199f519263599ee341 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 5 Jan 2000 22:19:21 +0000 Subject: Added support for simple binary semaphores in addition to the high power binary/mutex style semaphores already supported by RTEMS. This was done at the request of Eric Norum in support of his effort to port EPICS to RTEMS. This change consisted of changing the nesting_allowed boolean into a lock_nesting_behavior enumerated value as well as allowing the core mutex object to optionally support ensuring that the holder of a binary semaphore released it. Finally, a more subtle enhancement was to allow the non-holder to release a priority inheritance/ceiling mutex and still allow the holding task to return to its original priority. --- cpukit/score/include/rtems/score/coremutex.h | 36 ++++++++++++++++++++++--- cpukit/score/include/rtems/score/interr.h | 3 ++- cpukit/score/inline/rtems/score/coremutex.inl | 18 ------------- cpukit/score/macros/rtems/score/coremutex.inl | 9 ------- cpukit/score/src/coremutex.c | 13 ++++++++- cpukit/score/src/coremutexseize.c | 22 ++++++++------- cpukit/score/src/coremutexsurrender.c | 39 ++++++++++++--------------- 7 files changed, 77 insertions(+), 63 deletions(-) (limited to 'cpukit/score') diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h index 73f92c76e0..32e4f40b5e 100644 --- a/cpukit/score/include/rtems/score/coremutex.h +++ b/cpukit/score/include/rtems/score/coremutex.h @@ -62,6 +62,35 @@ typedef enum { CORE_MUTEX_STATUS_CEILING_VIOLATED } CORE_mutex_Status; +/* + * Mutex lock nesting behavior + * + * CORE_MUTEX_NESTING_ACQUIRES: + * This sequence has no blocking or errors: + * lock(m) + * lock(m) + * unlock(m) + * unlock(m) + * + * CORE_MUTEX_NESTING_IS_ERROR + * This sequence returns an error at the indicated point: + * lock(m) + * lock(m) - already locked error + * unlock(m) + * + * CORE_MUTEX_NESTING_BLOCKS + * This sequence performs as indicated: + * lock(m) + * lock(m) - deadlocks or timeouts + * unlock(m) - releases + */ + +typedef enum { + CORE_MUTEX_NESTING_ACQUIRES, + CORE_MUTEX_NESTING_IS_ERROR, + CORE_MUTEX_NESTING_BLOCKS +} CORE_mutex_Nesting_behaviors; + /* * Locked and unlocked values */ @@ -75,9 +104,10 @@ typedef enum { */ typedef struct { - boolean allow_nesting; - CORE_mutex_Disciplines discipline; - Priority_Control priority_ceiling; + CORE_mutex_Nesting_behaviors lock_nesting_behavior; + boolean only_owner_release; + CORE_mutex_Disciplines discipline; + Priority_Control priority_ceiling; } CORE_mutex_Attributes; /* diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h index b2e92906fe..293957ec2b 100644 --- a/cpukit/score/include/rtems/score/interr.h +++ b/cpukit/score/include/rtems/score/interr.h @@ -53,7 +53,8 @@ typedef enum { INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS, INTERNAL_ERROR_OUT_OF_PROXIES, INTERNAL_ERROR_INVALID_GLOBAL_ID, - INTERNAL_ERROR_BAD_STACK_HOOK + INTERNAL_ERROR_BAD_STACK_HOOK, + INTERNAL_ERROR_BAD_ATTRIBUTES } Internal_errors_Core_list; /* diff --git a/cpukit/score/inline/rtems/score/coremutex.inl b/cpukit/score/inline/rtems/score/coremutex.inl index b0289c3f9c..8ce3a9b214 100644 --- a/cpukit/score/inline/rtems/score/coremutex.inl +++ b/cpukit/score/inline/rtems/score/coremutex.inl @@ -101,23 +101,5 @@ RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority_ceiling( return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING; } -/*PAGE - * - * _CORE_mutex_Is_nesting_allowed - * - * DESCRIPTION: - * - * This routine returns TRUE if the mutex allows a task to obtain a - * semaphore more than once and nest. - */ - -RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_nesting_allowed( - CORE_mutex_Attributes *the_attribute -) -{ - return the_attribute->allow_nesting == TRUE; - -} - #endif /* end of include file */ diff --git a/cpukit/score/macros/rtems/score/coremutex.inl b/cpukit/score/macros/rtems/score/coremutex.inl index 88bc514d3d..be6f483dae 100644 --- a/cpukit/score/macros/rtems/score/coremutex.inl +++ b/cpukit/score/macros/rtems/score/coremutex.inl @@ -63,14 +63,5 @@ #define _CORE_mutex_Is_priority_ceiling( _the_attribute )\ ( (_the_attribute)->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING ) -/*PAGE - * - * _CORE_mutex_Is_nesting_allowed - * - */ - -#define _CORE_mutex_Is_nesting_allowed( _the_attribute ) \ - ( (_the_attribute)->allow_nesting == TRUE ) - #endif /* end of include file */ diff --git a/cpukit/score/src/coremutex.c b/cpukit/score/src/coremutex.c index 2f5b4a6675..a5842efb91 100644 --- a/cpukit/score/src/coremutex.c +++ b/cpukit/score/src/coremutex.c @@ -55,7 +55,18 @@ void _CORE_mutex_Initialize( */ the_mutex->Attributes = *the_mutex_attributes; - the_mutex->lock = initial_lock; + the_mutex->lock = initial_lock; + +#if 0 + if ( !the_mutex_attributes->only_owner_release && + the_mutex_attributes->nesting_allowed ) { + _Internal_error_Occurred( + INTERNAL_ERROR_CORE, + TRUE, + INTERNAL_ERROR_BAD_ATTRIBUTES + ); + } +#endif if ( initial_lock == CORE_MUTEX_LOCKED ) { the_mutex->nest_count = 1; diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c index c2a70da762..db576c6ef1 100644 --- a/cpukit/score/src/coremutexseize.c +++ b/cpukit/score/src/coremutexseize.c @@ -94,15 +94,19 @@ void _CORE_mutex_Seize( return; } - if ( _Objects_Are_ids_equal( - _Thread_Executing->Object.id, the_mutex->holder_id ) ) { - if ( _CORE_mutex_Is_nesting_allowed( &the_mutex->Attributes ) ) - the_mutex->nest_count++; - else - executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED; - - _ISR_Enable( level ); - return; + if ( _Thread_Is_executing( the_mutex->holder ) ) { + switch ( the_mutex->Attributes.lock_nesting_behavior ) { + case CORE_MUTEX_NESTING_ACQUIRES: + the_mutex->nest_count++; + _ISR_Enable( level ); + return; + case CORE_MUTEX_NESTING_IS_ERROR: + executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED; + _ISR_Enable( level ); + return; + case CORE_MUTEX_NESTING_BLOCKS: + break; + } } if ( !wait ) { diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c index 447a5421e8..d64badae1f 100644 --- a/cpukit/score/src/coremutexsurrender.c +++ b/cpukit/score/src/coremutexsurrender.c @@ -49,9 +49,9 @@ CORE_mutex_Status _CORE_mutex_Surrender( ) { Thread_Control *the_thread; - Thread_Control *executing; + Thread_Control *holder; - executing = _Thread_Executing; + holder = the_mutex->holder; /* * The following code allows a thread (or ISR) other than the thread @@ -61,20 +61,9 @@ CORE_mutex_Status _CORE_mutex_Surrender( * must be released by the thread which acquired them. */ - if ( the_mutex->Attributes.allow_nesting ) { - if ( !_Objects_Are_ids_equal( - _Thread_Executing->Object.id, the_mutex->holder_id ) ) { - - switch ( the_mutex->Attributes.discipline ) { - case CORE_MUTEX_DISCIPLINES_FIFO: - case CORE_MUTEX_DISCIPLINES_PRIORITY: - break; - case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING: - case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT: - return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE ); - break; - } - } + if ( the_mutex->Attributes.only_owner_release ) { + if ( !_Thread_Is_executing( holder ) ) + return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE ); } /* XXX already unlocked -- not right status */ @@ -85,9 +74,15 @@ CORE_mutex_Status _CORE_mutex_Surrender( the_mutex->nest_count--; if ( the_mutex->nest_count != 0 ) { - if ( the_mutex->Attributes.allow_nesting ) - return( CORE_MUTEX_STATUS_SUCCESSFUL ); - return( CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED ); + switch ( the_mutex->Attributes.lock_nesting_behavior ) { + case CORE_MUTEX_NESTING_ACQUIRES: + return CORE_MUTEX_STATUS_SUCCESSFUL; + case CORE_MUTEX_NESTING_IS_ERROR: + /* should never occur */ + return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED; + case CORE_MUTEX_NESTING_BLOCKS: + break; + } } _Thread_Executing->resource_count--; @@ -106,9 +101,9 @@ CORE_mutex_Status _CORE_mutex_Surrender( break; case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING: case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT: - if ( executing->resource_count == 0 && - executing->real_priority != executing->current_priority ) { - _Thread_Change_priority( executing, executing->real_priority, TRUE ); + if ( holder->resource_count == 0 && + holder->real_priority != holder->current_priority ) { + _Thread_Change_priority( holder, holder->real_priority, TRUE ); } break; } -- cgit v1.2.3