Ignore:
File:
1 edited

Legend:

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

    rf6372be9 ra35b458  
    3434
    3535#include <futex.h>
    36 
    37 #include <assert.h>
    3836#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)
    4637
    4738/** Initialize futex counter.
     
    5647}
    5748
    58 #ifdef CONFIG_DEBUG_FUTEX
    5949
    60 void __futex_assert_is_locked(futex_t *futex, const char *name)
     50#ifdef FUTEX_UPGRADABLE
     51
     52int _upgrade_futexes = 0;
     53static futex_t upg_and_wait_futex = FUTEX_INITIALIZER;
     54
     55void futex_upgrade_all_and_wait(void)
    6156{
    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 }
     57        futex_down(&upg_and_wait_futex);
    6958
    70 void __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 
    80 void __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 
    98 void __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 
    108 bool __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);
     59        if (!_upgrade_futexes) {
     60                rcu_assign(_upgrade_futexes, 1);
     61                _rcu_synchronize(BM_BLOCK_THREAD);
    12362        }
    12463
    125         return success;
    126 }
    127 
    128 void __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);
     64        futex_up(&upg_and_wait_futex);
    13865}
    13966
Note: See TracChangeset for help on using the changeset viewer.