bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: Lightweight synchronization mechanism for gnumach


From: Agustina Arzille
Subject: Re: RFC: Lightweight synchronization mechanism for gnumach
Date: Sun, 28 Feb 2016 13:23:18 -0300

As a followup, here's how one would use gsync to implement something akin to
Linux futexes.

===============================

#include <mach/gnumach.h>
#include <mach.h>

/* This bit signals that the lock is being held. The rest of
 * the word tells us how many waiters there are. */
#define BIT31   (1U << 31)

#define atomic_cas_bool(Ptr, Exp, Nval)   \
  ({   \
     typeof (Exp) __e = (Exp);   \
     __atomic_compare_exchange_n ((Ptr), &__e, (Nval), 1,   \
       __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);   \
  })

#define atomic_add(Ptr, Val)   \
  __atomic_fetch_add ((Ptr), (Val), __ATOMIC_ACQ_REL)

/* Lock the futex PTR. FLAGS may be zero in case we're dealing
 * with a task-local lock, or GSYNC_SHARED for a task-shared one. */
static void
futex_lock (unsigned int *ptr, int flags)
{
  unsigned int val = *ptr;
  if (!(val & BIT31) && atomic_cas_bool (ptr, val, val | BIT31))
    return;

  atomic_add (ptr, 1);
  while (1)
    {
      val = *ptr;
      if (!(val & BIT31) && atomic_cas_bool (ptr, val, (val - 1) | BIT31))
        break;

      gsync_wait (mach_task_self (), (vm_offset_t)ptr, val, 0, 0, flags);
    }
}

/* Unlock the futex PTR. See above for a description on what FLAGS does. */
static void
futex_unlock (unsigned int *ptr, int flags)
{
  unsigned int val = atomic_add (ptr, BIT31);
  if (val != BIT31)
    gsync_wait (mach_task_self (), (vm_offset_t)ptr, 0, flags);
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]