Changeset 508b0df1 in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2018-09-06T20:21:52Z (7 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:
78de83de, fc10e1b
Parents:
4621d23
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-08-13 03:53:39)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-09-06 20:21:52)
Message:

Remove uspace <atomic.h>, use <stdatomic.h> instead

Location:
uspace/lib/c/generic
Files:
3 edited

Legend:

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

    r4621d23 r508b0df1  
    3737
    3838#include <assert.h>
    39 #include <atomic.h>
     39#include <stdatomic.h>
    4040#include <errno.h>
    4141#include <libc.h>
     
    4343
    4444typedef struct futex {
    45         atomic_t val;
     45        volatile atomic_int val;
    4646#ifdef CONFIG_DEBUG_FUTEX
    4747        void *owner;
     
    5353#ifdef CONFIG_DEBUG_FUTEX
    5454
    55 #define FUTEX_INITIALIZE(val) {{ (val) }, NULL }
     55#define FUTEX_INITIALIZE(val) { (val) , NULL }
    5656#define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
    5757
     
    7373#else
    7474
    75 #define FUTEX_INITIALIZE(val) {{ (val) }}
     75#define FUTEX_INITIALIZE(val) { (val) }
    7676#define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
    7777
     
    107107        // TODO: Add tests for this.
    108108
    109         if ((atomic_signed_t) atomic_predec(&futex->val) >= 0)
     109        if (atomic_fetch_sub_explicit(&futex->val, 1, memory_order_acquire) > 0)
    110110                return EOK;
     111
     112        /* There wasn't any token. We must defer to the underlying semaphore. */
    111113
    112114        usec_t timeout;
     
    129131        }
    130132
    131         return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout);
     133        return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) futex, (sysarg_t) timeout);
    132134}
    133135
     
    143145static inline errno_t futex_up(futex_t *futex)
    144146{
    145         if ((atomic_signed_t) atomic_postinc(&futex->val) < 0)
    146                 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count);
     147        if (atomic_fetch_add_explicit(&futex->val, 1, memory_order_release) < 0)
     148                return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) futex);
    147149
    148150        return EOK;
     
    152154    const struct timespec *expires)
    153155{
    154         if (expires && expires->tv_sec == 0 && expires->tv_nsec == 0) {
    155                 /* Nonblocking down. */
    156 
    157                 /*
    158                  * Try good old CAS a few times.
    159                  * Not too much though, we don't want to bloat the caller.
    160                  */
    161                 for (int i = 0; i < 2; i++) {
    162                         atomic_signed_t old = atomic_get(&futex->val);
    163                         if (old <= 0)
    164                                 return ETIMEOUT;
    165 
    166                         if (cas(&futex->val, old, old - 1))
    167                                 return EOK;
    168                 }
    169 
    170                 // TODO: builtin atomics with relaxed ordering can make this
    171                 //       faster.
    172 
    173                 /*
    174                  * If we don't succeed with CAS, we can't just return failure
    175                  * because that would lead to spurious failures where
    176                  * futex_down_timeout returns ETIMEOUT despite there being
    177                  * available tokens. That could break some algorithms.
    178                  * We also don't want to loop on CAS indefinitely, because
    179                  * that would make the semaphore not wait-free, even when all
    180                  * atomic operations and the underlying base semaphore are all
    181                  * wait-free.
    182                  * Instead, we fall back to regular down_timeout(), with
    183                  * an already expired deadline. That way we delegate all these
    184                  * concerns to the base semaphore.
    185                  */
    186         }
    187 
    188156        /*
    189157         * This combination of a "composable" sleep followed by futex_up() on
     
    208176{
    209177        /*
    210          * down_timeout with an already expired deadline should behave like
    211          * trydown.
     178         * We can't just use CAS here.
     179         * If we don't succeed with CAS, we can't return failure
     180         * because that would lead to spurious failures where
     181         * futex_down_timeout returns ETIMEOUT despite there being
     182         * available tokens. That would break some algorithms.
     183         * We also don't want to loop on CAS indefinitely, because
     184         * that would make the semaphore not wait-free, even when all
     185         * atomic operations and the underlying base semaphore are all
     186         * wait-free.
     187         * It's much less trouble (and code bloat) to just do regular
     188         * down_timeout(), with an already expired deadline.
    212189         */
    213190        struct timespec tv = { .tv_sec = 0, .tv_nsec = 0 };
  • uspace/lib/c/generic/thread/fibril.c

    r4621d23 r508b0df1  
    8888/* This futex serializes access to global data. */
    8989static futex_t fibril_futex = FUTEX_INITIALIZER;
    90 static futex_t ready_semaphore = FUTEX_INITIALIZE(0);
     90static futex_t ready_semaphore;
    9191static long ready_st_count;
    9292
     
    117117}
    118118
    119 static inline long _ready_count(void)
    120 {
    121         /*
    122          * The number of available tokens is always equal to the number
    123          * of fibrils in the ready list + the number of free IPC buffer
    124          * buckets.
    125          */
    126 
    127         if (multithreaded)
    128                 return atomic_get(&ready_semaphore.val);
    129 
    130         _ready_debug_check();
    131         return ready_st_count;
    132 }
    133 
    134119static inline void _ready_up(void)
    135120{
     
    152137}
    153138
    154 static atomic_t threads_in_ipc_wait = { 0 };
     139static atomic_int threads_in_ipc_wait;
    155140
    156141/** Function that spans the whole life-cycle of a fibril.
     
    303288        fibril_t *f = list_pop(&ready_list, fibril_t, link);
    304289        if (!f)
    305                 atomic_inc(&threads_in_ipc_wait);
     290                atomic_fetch_add_explicit(&threads_in_ipc_wait, 1,
     291                    memory_order_relaxed);
    306292        if (!locked)
    307293                futex_unlock(&fibril_futex);
     
    317303        rc = _ipc_wait(&call, expires);
    318304
    319         atomic_dec(&threads_in_ipc_wait);
     305        atomic_fetch_sub_explicit(&threads_in_ipc_wait, 1,
     306            memory_order_relaxed);
    320307
    321308        if (rc != EOK && rc != ENOENT) {
     
    386373        _ready_up();
    387374
    388         if (atomic_get(&threads_in_ipc_wait)) {
     375        if (atomic_load_explicit(&threads_in_ipc_wait, memory_order_relaxed)) {
    389376                DPRINTF("Poking.\n");
    390377                /* Wakeup one thread sleeping in SYS_IPC_WAIT. */
     
    811798        if (!multithreaded) {
    812799                _ready_debug_check();
    813                 atomic_set(&ready_semaphore.val, ready_st_count);
     800                futex_initialize(&ready_semaphore, ready_st_count);
    814801                multithreaded = true;
    815802        }
  • uspace/lib/c/generic/thread/futex.c

    r4621d23 r508b0df1  
    3434
    3535#include <assert.h>
    36 #include <atomic.h>
     36#include <stdatomic.h>
    3737#include <fibril.h>
    3838#include <io/kio.h>
     
    5252void futex_initialize(futex_t *futex, int val)
    5353{
    54         atomic_set(&futex->val, val);
     54        atomic_store_explicit(&futex->val, val, memory_order_relaxed);
    5555}
    5656
     
    5959void __futex_assert_is_locked(futex_t *futex, const char *name)
    6060{
    61         void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     61        void *owner = atomic_load_explicit(&futex->owner, memory_order_relaxed);
    6262        fibril_t *self = (fibril_t *) fibril_get_id();
    6363        if (owner != self) {
     
    6969void __futex_assert_is_not_locked(futex_t *futex, const char *name)
    7070{
    71         void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     71        void *owner = atomic_load_explicit(&futex->owner, memory_order_relaxed);
    7272        fibril_t *self = (fibril_t *) fibril_get_id();
    7373        if (owner == self) {
     
    9191        futex_down(futex);
    9292
    93         void *prev_owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     93        void *prev_owner = atomic_load_explicit(&futex->owner,
     94            memory_order_relaxed);
    9495        assert(prev_owner == NULL);
    95         __atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED);
     96        atomic_store_explicit(&futex->owner, self, memory_order_relaxed);
    9697}
    9798
     
    101102        DPRINTF("Unlocking futex %s (%p) by fibril %p.\n", name, futex, self);
    102103        __futex_assert_is_locked(futex, name);
    103         __atomic_store_n(&futex->owner, NULL, __ATOMIC_RELAXED);
     104        atomic_store_explicit(&futex->owner, NULL, memory_order_relaxed);
    104105        futex_up(futex);
    105106}
     
    110111        bool success = futex_trydown(futex);
    111112        if (success) {
    112                 void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
     113                void *owner = atomic_load_explicit(&futex->owner,
     114                    memory_order_relaxed);
    113115                assert(owner == NULL);
    114116
    115                 __atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED);
     117                atomic_store_explicit(&futex->owner, self, memory_order_relaxed);
    116118
    117119                DPRINTF("Trylock on futex %s (%p) by fibril %p succeeded.\n", name, futex, self);
     
    130132
    131133        __futex_assert_is_locked(futex, name);
    132         __atomic_store_n(&futex->owner, new_owner, __ATOMIC_RELAXED);
     134        atomic_store_explicit(&futex->owner, new_owner, memory_order_relaxed);
    133135}
    134136
Note: See TracChangeset for help on using the changeset viewer.