Is there a data race problem while acquiring a mutex with priority inheritance protocol

Saurabh Gadia gadia at usc.edu
Fri Jul 24 01:47:02 UTC 2015


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20150723/66dc623f/attachment-0001.html>


More information about the devel mailing list