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


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

File:
1 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 };
Note: See TracChangeset for help on using the changeset viewer.