[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);
}
Re: RFC: Lightweight synchronization mechanism for gnumach, Richard Braun, 2016/02/28
Re: RFC: Lightweight synchronization mechanism for gnumach, Richard Braun, 2016/02/28