Changeset f6372be9 in mainline for uspace/lib/c/generic/futex.c


Ignore:
Timestamp:
2018-06-26T17:34:23Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b59318e
Parents:
38e3427
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-25 20:50:53)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-06-26 17:34:23)
Message:

Improve the debugging options for futexes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/futex.c

    r38e3427 rf6372be9  
    3434
    3535#include <futex.h>
     36
     37#include <assert.h>
    3638#include <atomic.h>
     39#include <fibril.h>
     40#include <io/kio.h>
     41
     42#include "private/fibril.h"
     43
     44//#define DPRINTF(...) kio_printf(__VA_ARGS__)
     45#define DPRINTF(...) ((void)0)
    3746
    3847/** Initialize futex counter.
     
    4756}
    4857
     58#ifdef CONFIG_DEBUG_FUTEX
     59
     60void __futex_assert_is_locked(futex_t *futex, const char *name)
     61{
     62        void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     63        fibril_t *self = (fibril_t *) fibril_get_id();
     64        if (owner != self) {
     65                DPRINTF("Assertion failed: %s (%p) is not locked by fibril %p (instead locked by fibril %p).\n", name, futex, self, owner);
     66        }
     67        assert(owner == self);
     68}
     69
     70void __futex_assert_is_not_locked(futex_t *futex, const char *name)
     71{
     72        void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     73        fibril_t *self = (fibril_t *) fibril_get_id();
     74        if (owner == self) {
     75                DPRINTF("Assertion failed: %s (%p) is already locked by fibril %p.\n", name, futex, self);
     76        }
     77        assert(owner != self);
     78}
     79
     80void __futex_lock(futex_t *futex, const char *name)
     81{
     82        /* We use relaxed atomics to avoid violating C11 memory model.
     83         * They should compile to regular load/stores, but simple assignments
     84         * would be UB by definition.
     85         */
     86
     87        fibril_t *self = (fibril_t *) fibril_get_id();
     88        DPRINTF("Locking futex %s (%p) by fibril %p.\n", name, futex, self);
     89        __futex_assert_is_not_locked(futex, name);
     90        futex_down(futex);
     91
     92        void *prev_owner = __atomic_exchange_n(&futex->owner, self, __ATOMIC_RELAXED);
     93        assert(prev_owner == NULL);
     94
     95        atomic_inc(&self->futex_locks);
     96}
     97
     98void __futex_unlock(futex_t *futex, const char *name)
     99{
     100        fibril_t *self = (fibril_t *) fibril_get_id();
     101        DPRINTF("Unlocking futex %s (%p) by fibril %p.\n", name, futex, self);
     102        __futex_assert_is_locked(futex, name);
     103        __atomic_store_n(&futex->owner, NULL, __ATOMIC_RELAXED);
     104        atomic_dec(&self->futex_locks);
     105        futex_up(futex);
     106}
     107
     108bool __futex_trylock(futex_t *futex, const char *name)
     109{
     110        fibril_t *self = (fibril_t *) fibril_get_id();
     111        bool success = futex_trydown(futex);
     112        if (success) {
     113                void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     114                assert(owner == NULL);
     115
     116                __atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED);
     117
     118                atomic_inc(&self->futex_locks);
     119
     120                DPRINTF("Trylock on futex %s (%p) by fibril %p succeeded.\n", name, futex, self);
     121        } else {
     122                DPRINTF("Trylock on futex %s (%p) by fibril %p failed.\n", name, futex, self);
     123        }
     124
     125        return success;
     126}
     127
     128void __futex_give_to(futex_t *futex, void *new_owner, const char *name)
     129{
     130        fibril_t *self = fibril_self();
     131        fibril_t *no = new_owner;
     132        DPRINTF("Passing futex %s (%p) from fibril %p to fibril %p.\n", name, futex, self, no);
     133
     134        __futex_assert_is_locked(futex, name);
     135        atomic_dec(&self->futex_locks);
     136        atomic_inc(&no->futex_locks);
     137        __atomic_store_n(&futex->owner, new_owner, __ATOMIC_RELAXED);
     138}
     139
     140#endif
     141
    49142/** @}
    50143 */
Note: See TracChangeset for help on using the changeset viewer.