/* * Mutex Handler * * DESCRIPTION: * * This package is the implementation of the Mutex Handler. * This handler provides synchronization and mutual exclusion capabilities. * * COPYRIGHT (c) 1989-1999. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. * * $Id$ */ #include #include #include #include #include #include /* * _CORE_mutex_Surrender * * DESCRIPTION: * * This routine frees a unit to the mutex. If a task was blocked waiting for * a unit from this mutex, then that task will be readied and the unit * given to that task. Otherwise, the unit will be returned to the mutex. * * Input parameters: * the_mutex - the mutex to be flushed * id - id of parent mutex * api_mutex_mp_support - api dependent MP support actions * * Output parameters: * CORE_MUTEX_STATUS_SUCCESSFUL - if successful * core error code - if unsuccessful */ CORE_mutex_Status _CORE_mutex_Surrender( CORE_mutex_Control *the_mutex, Objects_Id id, CORE_mutex_API_mp_support_callout api_mutex_mp_support ) { Thread_Control *the_thread; Thread_Control *executing; executing = _Thread_Executing; /* * 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. */ 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; } } the_mutex->nest_count--; if ( the_mutex->nest_count != 0 ) return( CORE_MUTEX_STATUS_SUCCESSFUL ); _Thread_Executing->resource_count--; the_mutex->holder = NULL; the_mutex->holder_id = 0; /* * 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. */ 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: if ( executing->resource_count == 0 && executing->real_priority != executing->current_priority ) { _Thread_Change_priority( executing, executing->real_priority, TRUE ); } break; } if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) { #if defined(RTEMS_MULTIPROCESSING) if ( !_Objects_Is_local_id( the_thread->Object.id ) ) { the_mutex->holder = NULL; the_mutex->holder_id = the_thread->Object.id; the_mutex->nest_count = 1; ( *api_mutex_mp_support)( the_thread, id ); } else #endif { the_mutex->holder = the_thread; the_mutex->holder_id = the_thread->Object.id; the_thread->resource_count++; the_mutex->nest_count = 1; /* * No special action for priority inheritance or priority ceiling * because the_thread is guaranteed to be the highest priority * thread waiting for the mutex. */ } } else the_mutex->lock = CORE_MUTEX_UNLOCKED; return( CORE_MUTEX_STATUS_SUCCESSFUL ); }