hi,
Scenario: thread t1: current_priority = 5, mutex acquired = m1, m2 thread t2: current_priority = 3, mutex_acquired = None flow: thread t1 tries to acquire mutex m3 and thread t2 tries to acquire mutex m1 which is already acquired by thread t1 simultaneously on SMP. Action: thred t1 finds that m3 ->holder==NULL, so following code snippet of coremuteximpl.h executes on one processor: ///// RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock_body( CORE_mutex_Control *the_mutex, Thread_Control *executing, ISR_lock_Context *lock_context ) { /* disabled when you get here */ executing->Wait.return_code = CORE_MUTEX_STATUS_SUCCESSFUL; if ( !_CORE_mutex_Is_locked( the_mutex ) ) { the_mutex->holder = executing; the_mutex->nest_count = 1; if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) || _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ){ #ifdef __RTEMS_STRICT_ORDER_MUTEX__ /* Doesn't this lead to data race. If the executing thread is holder os some other mutex and its priority is promoted by other thread */ _Chain_Prepend_unprotected( &executing->lock_mutex, &the_mutex->queue.lock_queue ); *the_mutex->queue.priority_before = executing->current_priority;* #endif executing->resource_count++; } if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) { _Thread_queue_Release( &the_mutex->Wait_queue, lock_context ); return 0; } ////// And thread t2 tries to acquire m1 and following snippet of threadchangepriority.c executes: /////// (the_thread is holder for mutex m1 and new_priority == priority of thread t2 ==3) lock = _Thread_Lock_acquire( the_thread, &lock_context ); /* * For simplicity set the priority restore hint unconditionally since this is * an average case optimization. Otherwise complicated atomic operations * would be necessary. Synchronize with a potential read of the resource * count in the filter function. See also _CORE_mutex_Surrender(), * _Thread_Set_priority_filter() and _Thread_Restore_priority_filter(). */ the_thread->priority_restore_hint = true; _Atomic_Fence( ATOMIC_ORDER_ACQ_REL ); /* * Do not bother recomputing all the priority related information if * we are not REALLY changing priority. */ if ( ( *filter )( the_thread, &new_priority, arg ) ) { uint32_t my_generation; my_generation = the_thread->priority_generation + 1; * the_thread->current_priority = new_priority;* the_thread->priority_generation = my_generation; ( *the_thread->Wait.operations->priority_change )( the_thread, new_priority, the_thread->Wait.queue ); //// So can interleaving of highlighted code result in data race? From my perspective and from JPF model experience this is a data race and we need to have locking on executing thread and holder thread if it exists for mutex while acquiring any mutex. So for 2nd case when there is already holder we do acquire holder lock by calling *lock = _Thread_Lock_acquire( the_thread, &lock_context ); *in 2nd snippet but we should do the same on executing thread when holder==NULL in 1st code snippet. Am I right? or is there something I am missing? Thanks, Saurabh Gadia
_______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel