void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; Thread_queue_Context queue_context; ISR_Level level; Thread_Control *executing; Thread_Control *owner; mutex = _Mutex_recursive_Get( _mutex ); _Thread_queue_Context_initialize( &queue_context ); _Thread_queue_Context_ISR_disable( &queue_context, level ); executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context ); owner = mutex->Mutex.Queue.Queue.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.Queue.Queue.owner = executing; _Thread_Resource_count_increment( executing ); _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); } else if ( owner == executing ) { ++mutex->nest_level; _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); } else { _Thread_queue_Context_set_no_timeout( &queue_context ); _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context ); } }
void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; Thread_queue_Context queue_context; Thread_Control *executing; Thread_Control *owner; mutex = _Mutex_recursive_Get( _mutex ); _Thread_queue_Context_initialize( &queue_context ); executing = _Mutex_Queue_acquire( &mutex->Mutex, &queue_context ); owner = mutex->Mutex.Queue.Queue.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.Queue.Queue.owner = executing; ++executing->resource_count; _Mutex_Queue_release( &mutex->Mutex, &queue_context ); } else if ( owner == executing ) { ++mutex->nest_level; _Mutex_Queue_release( &mutex->Mutex, &queue_context ); } else { _Thread_queue_Context_set_no_timeout( &queue_context ); _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, &queue_context ); } }
int _Mutex_recursive_Acquire_timed( struct _Mutex_recursive_Control *_mutex, const struct timespec *abstime ) { Mutex_recursive_Control *mutex; ISR_lock_Context lock_context; Thread_Control *executing; Thread_Control *owner; mutex = _Mutex_recursive_Get( _mutex ); executing = _Mutex_Queue_acquire( &mutex->Mutex, &lock_context ); owner = mutex->Mutex.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.owner = executing; ++executing->resource_count; _Mutex_Queue_release( &mutex->Mutex, &lock_context ); return 0; } else if ( owner == executing ) { ++mutex->nest_level; _Mutex_Queue_release( &mutex->Mutex, &lock_context ); return 0; } else { Watchdog_Interval ticks; switch ( _TOD_Absolute_timeout_to_ticks( abstime, &ticks ) ) { case TOD_ABSOLUTE_TIMEOUT_INVALID: _Mutex_Queue_release( &mutex->Mutex, &lock_context ); return EINVAL; case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST: case TOD_ABSOLUTE_TIMEOUT_IS_NOW: _Mutex_Queue_release( &mutex->Mutex, &lock_context ); return ETIMEDOUT; default: break; } executing->Wait.return_code = 0; _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, ticks, &lock_context ); return (int) executing->Wait.return_code; } }
int _Mutex_recursive_Acquire_timed( struct _Mutex_recursive_Control *_mutex, const struct timespec *abstime ) { Mutex_recursive_Control *mutex; Thread_queue_Context queue_context; ISR_Level level; Thread_Control *executing; Thread_Control *owner; mutex = _Mutex_recursive_Get( _mutex ); _Thread_queue_Context_initialize( &queue_context ); _Thread_queue_Context_ISR_disable( &queue_context, level ); executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context ); owner = mutex->Mutex.Queue.Queue.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.Queue.Queue.owner = executing; _Thread_Resource_count_increment( executing ); _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); return 0; } else if ( owner == executing ) { ++mutex->nest_level; _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); return 0; } else { Watchdog_Interval ticks; switch ( _TOD_Absolute_timeout_to_ticks( abstime, CLOCK_REALTIME, &ticks ) ) { case TOD_ABSOLUTE_TIMEOUT_INVALID: _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); return EINVAL; case TOD_ABSOLUTE_TIMEOUT_IS_IN_PAST: case TOD_ABSOLUTE_TIMEOUT_IS_NOW: _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); return ETIMEDOUT; default: break; } _Thread_queue_Context_set_relative_timeout( &queue_context, ticks ); _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, level, &queue_context ); return STATUS_GET_POSIX( _Thread_Wait_get_status( executing ) ); } }
int _Mutex_recursive_Try_acquire( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; ISR_lock_Context lock_context; Thread_Control *executing; Thread_Control *owner; int success; mutex = _Mutex_recursive_Get( _mutex ); executing = _Mutex_Queue_acquire( &mutex->Mutex, &lock_context ); owner = mutex->Mutex.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.owner = executing; ++executing->resource_count; success = 1; } else if ( owner == executing ) { ++mutex->nest_level; success = 1; } else { success = 0; } _Mutex_Queue_release( &mutex->Mutex, &lock_context ); return success; }
static void _Mutex_Release_slow( Mutex_Control *mutex, Thread_Control *executing, Thread_queue_Heads *heads, bool keep_priority, ISR_lock_Context *lock_context ) { if (heads != NULL) { const Thread_queue_Operations *operations; Thread_Control *first; operations = MUTEX_TQ_OPERATIONS; first = ( *operations->first )( heads ); mutex->owner = first; _Thread_queue_Extract_critical( &mutex->Queue.Queue, operations, first, lock_context ); } else { _Mutex_Queue_release( mutex, lock_context); } if ( !keep_priority ) { Per_CPU_Control *cpu_self; cpu_self = _Thread_Dispatch_disable(); _Thread_Restore_priority( executing ); _Thread_Dispatch_enable( cpu_self ); } }
void _Mutex_recursive_Release( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; Thread_queue_Context queue_context; ISR_Level level; Thread_Control *executing; unsigned int nest_level; mutex = _Mutex_recursive_Get( _mutex ); _Thread_queue_Context_initialize( &queue_context ); _Thread_queue_Context_ISR_disable( &queue_context, level ); executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context ); _Assert( mutex->Mutex.Queue.Queue.owner == executing ); nest_level = mutex->nest_level; if ( __predict_true( nest_level == 0 ) ) { _Mutex_Release_critical( &mutex->Mutex, executing, level, &queue_context ); } else { mutex->nest_level = nest_level - 1; _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); } }
int _Mutex_recursive_Try_acquire( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; Thread_queue_Context queue_context; ISR_Level level; Thread_Control *executing; Thread_Control *owner; int eno; mutex = _Mutex_recursive_Get( _mutex ); _Thread_queue_Context_initialize( &queue_context ); _Thread_queue_Context_ISR_disable( &queue_context, level ); executing = _Mutex_Queue_acquire_critical( &mutex->Mutex, &queue_context ); owner = mutex->Mutex.Queue.Queue.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.Queue.Queue.owner = executing; _Thread_Resource_count_increment( executing ); eno = 0; } else if ( owner == executing ) { ++mutex->nest_level; eno = 0; } else { eno = EBUSY; } _Mutex_Queue_release( &mutex->Mutex, level, &queue_context ); return eno; }
static void _Mutex_Release_critical( Mutex_Control *mutex, Thread_Control *executing, ISR_Level level, Thread_queue_Context *queue_context ) { Thread_queue_Heads *heads; heads = mutex->Queue.Queue.heads; mutex->Queue.Queue.owner = NULL; _Thread_Resource_count_decrement( executing ); if ( __predict_true( heads == NULL ) ) { _Mutex_Queue_release( mutex, level, queue_context ); } else { _Thread_queue_Context_set_ISR_level( queue_context, level ); _Thread_queue_Surrender( &mutex->Queue.Queue, heads, executing, queue_context, MUTEX_TQ_OPERATIONS ); } }
int _Mutex_Try_acquire( struct _Mutex_Control *_mutex ) { Mutex_Control *mutex; Thread_queue_Context queue_context; Thread_Control *executing; Thread_Control *owner; int eno; mutex = _Mutex_Get( _mutex ); _Thread_queue_Context_initialize( &queue_context ); executing = _Mutex_Queue_acquire( mutex, &queue_context ); owner = mutex->Queue.Queue.owner; if ( __predict_true( owner == NULL ) ) { mutex->Queue.Queue.owner = executing; ++executing->resource_count; eno = 0; } else { eno = EBUSY; } _Mutex_Queue_release( mutex, &queue_context ); return eno; }
void _Mutex_recursive_Acquire( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; ISR_lock_Context lock_context; Thread_Control *executing; Thread_Control *owner; mutex = _Mutex_recursive_Get( _mutex ); executing = _Mutex_Queue_acquire( &mutex->Mutex, &lock_context ); owner = mutex->Mutex.owner; if ( __predict_true( owner == NULL ) ) { mutex->Mutex.owner = executing; ++executing->resource_count; _Mutex_Queue_release( &mutex->Mutex, &lock_context ); } else if ( owner == executing ) { ++mutex->nest_level; _Mutex_Queue_release( &mutex->Mutex, &lock_context ); } else { _Mutex_Acquire_slow( &mutex->Mutex, owner, executing, 0, &lock_context ); } }
void _Mutex_Acquire( struct _Mutex_Control *_mutex ) { Mutex_Control *mutex; ISR_lock_Context lock_context; Thread_Control *executing; Thread_Control *owner; mutex = _Mutex_Get( _mutex ); executing = _Mutex_Queue_acquire( mutex, &lock_context ); owner = mutex->owner; ++executing->resource_count; if ( __predict_true( owner == NULL ) ) { mutex->owner = executing; _Mutex_Queue_release( mutex, &lock_context ); } else { _Mutex_Acquire_slow( mutex, owner, executing, 0, &lock_context ); } }
void _Mutex_recursive_Release( struct _Mutex_recursive_Control *_mutex ) { Mutex_recursive_Control *mutex; ISR_lock_Context lock_context; Thread_Control *executing; unsigned int nest_level; mutex = _Mutex_recursive_Get( _mutex ); executing = _Mutex_Queue_acquire( &mutex->Mutex, &lock_context ); _Assert( mutex->Mutex.owner == executing ); nest_level = mutex->nest_level; if ( __predict_true( nest_level == 0 ) ) { _Mutex_Release_critical( &mutex->Mutex, executing, &lock_context ); } else { mutex->nest_level = nest_level - 1; _Mutex_Queue_release( &mutex->Mutex, &lock_context ); } }
static void _Mutex_Release_critical( Mutex_Control *mutex, Thread_Control *executing, Thread_queue_Context *queue_context ) { Thread_queue_Heads *heads; bool keep_priority; mutex->Queue.Queue.owner = NULL; --executing->resource_count; /* * Ensure that the owner resource count is visible to all other * processors and that we read the latest priority restore * hint. */ _Atomic_Fence( ATOMIC_ORDER_ACQ_REL ); heads = mutex->Queue.Queue.heads; keep_priority = _Thread_Owns_resources( executing ) || !executing->priority_restore_hint; if ( __predict_true( heads == NULL && keep_priority ) ) { _Mutex_Queue_release( mutex, queue_context ); } else { _Thread_queue_Surrender( &mutex->Queue.Queue, MUTEX_TQ_OPERATIONS, heads, executing, keep_priority, queue_context ); } }