diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-05-02 14:27:24 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-05-19 12:00:47 +0200 |
commit | 4438ac2575fb9e0760bf53931a52d00dec4deb83 (patch) | |
tree | 1a81aa76215e781bdddd08a92f4be01454d330ae /cpukit/score/src/coremutexsurrender.c | |
parent | score: Inline _CORE_semaphore_Surrender() (diff) | |
download | rtems-4438ac2575fb9e0760bf53931a52d00dec4deb83.tar.bz2 |
score: Fine grained locking for mutexes
Update #2273.
Diffstat (limited to 'cpukit/score/src/coremutexsurrender.c')
-rw-r--r-- | cpukit/score/src/coremutexsurrender.c | 86 |
1 files changed, 62 insertions, 24 deletions
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c index 8fba301de9..3f0cd8619c 100644 --- a/cpukit/score/src/coremutexsurrender.c +++ b/cpukit/score/src/coremutexsurrender.c @@ -89,11 +89,12 @@ CORE_mutex_Status _CORE_mutex_Surrender( CORE_mutex_Control *the_mutex, #if defined(RTEMS_MULTIPROCESSING) Objects_Id id, - CORE_mutex_API_mp_support_callout api_mutex_mp_support + CORE_mutex_API_mp_support_callout api_mutex_mp_support, #else Objects_Id id __attribute__((unused)), - CORE_mutex_API_mp_support_callout api_mutex_mp_support __attribute__((unused)) + CORE_mutex_API_mp_support_callout api_mutex_mp_support __attribute__((unused)), #endif + ISR_lock_Context *lock_context ) { Thread_Control *the_thread; @@ -110,14 +111,20 @@ CORE_mutex_Status _CORE_mutex_Surrender( */ if ( the_mutex->Attributes.only_owner_release ) { - if ( !_Thread_Is_executing( holder ) ) + if ( !_Thread_Is_executing( holder ) ) { + _ISR_lock_ISR_enable( lock_context ); return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE; + } } + _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context ); + /* XXX already unlocked -- not right status */ - if ( !the_mutex->nest_count ) + if ( !the_mutex->nest_count ) { + _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); return CORE_MUTEX_STATUS_SUCCESSFUL; + } the_mutex->nest_count--; @@ -130,10 +137,12 @@ CORE_mutex_Status _CORE_mutex_Surrender( #if defined(RTEMS_DEBUG) switch ( the_mutex->Attributes.lock_nesting_behavior ) { case CORE_MUTEX_NESTING_ACQUIRES: + _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); return CORE_MUTEX_STATUS_SUCCESSFUL; #if defined(RTEMS_POSIX_API) case CORE_MUTEX_NESTING_IS_ERROR: /* should never occur */ + _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED; #endif case CORE_MUTEX_NESTING_BLOCKS: @@ -141,6 +150,7 @@ CORE_mutex_Status _CORE_mutex_Surrender( break; } #else + _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */ return CORE_MUTEX_STATUS_SUCCESSFUL; #endif @@ -155,20 +165,12 @@ CORE_mutex_Status _CORE_mutex_Surrender( CORE_mutex_Status pop_status = _CORE_mutex_Pop_priority( the_mutex, holder ); - if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL ) + if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL ) { + _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); return pop_status; + } holder->resource_count--; - - /* - * 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( holder ) && - holder->real_priority != holder->current_priority ) { - _Thread_Change_priority( holder, holder->real_priority, true ); - } } the_mutex->holder = NULL; @@ -176,20 +178,21 @@ CORE_mutex_Status _CORE_mutex_Surrender( * Now we check if another thread was waiting for this mutex. If so, * transfer the mutex to that thread. */ - if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) { + if ( ( the_thread = _Thread_queue_First_locked( &the_mutex->Wait_queue ) ) ) { + /* + * 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. + */ + _Thread_queue_Extract_locked( &the_mutex->Wait_queue, the_thread ); #if defined(RTEMS_MULTIPROCESSING) - if ( !_Objects_Is_local_id( the_thread->Object.id ) ) { - - the_mutex->holder = NULL; - the_mutex->nest_count = 1; + _Thread_Dispatch_disable(); - ( *api_mutex_mp_support)( the_thread, id ); - - } else + if ( _Objects_Is_local_id( the_thread->Object.id ) ) #endif { - the_mutex->holder = the_thread; the_mutex->nest_count = 1; @@ -215,6 +218,41 @@ CORE_mutex_Status _CORE_mutex_Surrender( break; } } + + _Thread_queue_Unblock_critical( + &the_mutex->Wait_queue, + the_thread, + lock_context + ); + +#if defined(RTEMS_MULTIPROCESSING) + if ( !_Objects_Is_local_id( the_thread->Object.id ) ) { + + the_mutex->holder = NULL; + the_mutex->nest_count = 1; + + ( *api_mutex_mp_support)( the_thread, id ); + + } + + _Thread_Dispatch_enable( _Per_CPU_Get() ); +#endif + } else { + _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); + } + + /* + * 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( holder ) && + holder->real_priority != holder->current_priority ) { + Per_CPU_Control *cpu_self; + + cpu_self = _Thread_Dispatch_disable(); + _Thread_Change_priority( holder, holder->real_priority, true ); + _Thread_Dispatch_enable( cpu_self ); } return CORE_MUTEX_STATUS_SUCCESSFUL; |