HelenOS sources
This source file includes following definitions.
- futex_initialize
- __futex_assert_is_locked
- __futex_assert_is_not_locked
- __futex_lock
- __futex_unlock
- __futex_trylock
- __futex_give_to
#include <assert.h>
#include <stdatomic.h>
#include <fibril.h>
#include <io/kio.h>
#include "../private/fibril.h"
#include "../private/futex.h"
#define DPRINTF(...) dummy_printf(__VA_ARGS__)
errno_t futex_initialize(futex_t *futex, int val)
{
        atomic_store_explicit(&futex->val, val, memory_order_relaxed);
        futex->whandle = CAP_NIL;
        return futex_allocate_waitq(futex);
}
#ifdef CONFIG_DEBUG_FUTEX
void __futex_assert_is_locked(futex_t *futex, const char *name)
{
        void *owner = atomic_load_explicit(&futex->owner, memory_order_relaxed);
        fibril_t *self = (fibril_t *) fibril_get_id();
        if (owner != self) {
                DPRINTF("Assertion failed: %s (%p) is not locked by fibril %p (instead locked by fibril %p).\n", name, futex, self, owner);
        }
        assert(owner == self);
}
void __futex_assert_is_not_locked(futex_t *futex, const char *name)
{
        void *owner = atomic_load_explicit(&futex->owner, memory_order_relaxed);
        fibril_t *self = (fibril_t *) fibril_get_id();
        if (owner == self) {
                DPRINTF("Assertion failed: %s (%p) is already locked by fibril %p.\n", name, futex, self);
        }
        assert(owner != self);
}
void __futex_lock(futex_t *futex, const char *name)
{
        
        fibril_t *self = (fibril_t *) fibril_get_id();
        DPRINTF("Locking futex %s (%p) by fibril %p.\n", name, futex, self);
        __futex_assert_is_not_locked(futex, name);
        futex_down(futex);
        void *prev_owner = atomic_load_explicit(&futex->owner,
            memory_order_relaxed);
        assert(prev_owner == NULL);
        atomic_store_explicit(&futex->owner, self, memory_order_relaxed);
}
void __futex_unlock(futex_t *futex, const char *name)
{
        fibril_t *self = (fibril_t *) fibril_get_id();
        DPRINTF("Unlocking futex %s (%p) by fibril %p.\n", name, futex, self);
        __futex_assert_is_locked(futex, name);
        atomic_store_explicit(&futex->owner, NULL, memory_order_relaxed);
        futex_up(futex);
}
bool __futex_trylock(futex_t *futex, const char *name)
{
        fibril_t *self = (fibril_t *) fibril_get_id();
        bool success = futex_trydown(futex);
        if (success) {
                void *owner = atomic_load_explicit(&futex->owner,
                    memory_order_relaxed);
                assert(owner == NULL);
                atomic_store_explicit(&futex->owner, self, memory_order_relaxed);
                DPRINTF("Trylock on futex %s (%p) by fibril %p succeeded.\n", name, futex, self);
        } else {
                DPRINTF("Trylock on futex %s (%p) by fibril %p failed.\n", name, futex, self);
        }
        return success;
}
void __futex_give_to(futex_t *futex, void *new_owner, const char *name)
{
        fibril_t *self = fibril_self();
        fibril_t *no = new_owner;
        DPRINTF("Passing futex %s (%p) from fibril %p to fibril %p.\n", name, futex, self, no);
        __futex_assert_is_locked(futex, name);
        atomic_store_explicit(&futex->owner, new_owner, memory_order_relaxed);
}
#endif
HelenOS homepage, sources at GitHub