This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Race unlocking-locking mutex


On 9/14/13 6:31 PM, Ángel González wrote:
One option that comes to mind is adding a new element in the mutex --
a __prev_owner. On the unlock path set __prev_owner to thread id,
release lock, awaken a waiter. If it is an uncontended lock (no tasks
awakened or waiting), set __prev_owner to 0.

On the lock path check if __prev_owner is equal to thread id and if so
take the slow path into the kernel.

Any particular worrisome race conditions to be wary of?

David
Hmm, yes, it seems doable.
I think it could even be implemented without __prev_owner.

This may be such an implementation (to replace the nptl/lowlevellock.h
__generic_mutex_lock).

In my case I am not seeing this code path used. This is linux, x86_64 and from what I can see the code path is:
  pthread_mutex_lock == __pthread_mutex_lock()

In the latter you hit the 'simple:' goto path, and then LLL_MUTEX_LOCK which is a macro to lll_lock and that comes from nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h.

I can read asm well enough to get the gist of the code but I do not know asm near good enough to implement your suggestion below.

David


static inline void
__generic_mutex_lock (int *mutex)
{
   unsigned int v;

   /* Mutex available and no waiters, we got the mutex.  (this is the
fastpath).  */
   if (!atomic_compare_and_exchange_bool_acq(mutex, 1 << 31, 0))
     return;

   atomic_increment (mutex);

   while (1)
     {
       if (!atomic_compare_and_exchange_bool_acq(mutex, 1 << 31, 1))
     {
       return;
     }

       /* We have to wait now. First make sure the futex value we are
      monitoring is locked or with waiters. */
       v = *mutex;
       assert(v != 0);
       if (__builtin_expect(v == 0, 0))
     continue;

       lll_futex_wait (mutex, v,
               // XYZ check mutex flag
               LLL_SHARED);
     }

       while (1)
         {
           if (atomic_bit_test_set (mutex, 31) == 0)
         {
           atomic_decrement (mutex);
           return;
         }

           /* We have to wait now. First make sure the futex value we are
          monitoring is truly negative (i.e. locked). */
           v = *mutex;
           if (v >= 0)
         continue;

           lll_futex_wait (mutex, v,
                   // XYZ check mutex flag
                   LLL_SHARED);
         }

}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]