Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/include/futex.h

    r9d58539 r156b6406  
    3838#include <atomic.h>
    3939#include <sys/types.h>
     40#include <libc.h>
    4041
    41 #define FUTEX_INITIALIZER  {1}
     42typedef struct futex {
     43        atomic_t val;
     44#ifdef FUTEX_UPGRADABLE
     45        int upgraded;
     46#endif
     47} futex_t;
    4248
    43 typedef atomic_t futex_t;
    4449
    4550extern void futex_initialize(futex_t *futex, int value);
    46 extern int futex_down(futex_t *futex);
    47 extern int futex_trydown(futex_t *futex);
    48 extern int futex_up(futex_t *futex);
     51
     52#ifdef FUTEX_UPGRADABLE
     53#include <rcu.h>
     54
     55#define FUTEX_INITIALIZE(val) {{ (val) }, 0}
     56
     57#define futex_lock(fut) \
     58({ \
     59        rcu_read_lock(); \
     60        (fut)->upgraded = rcu_access(_upgrade_futexes); \
     61        if ((fut)->upgraded) \
     62                (void) futex_down((fut)); \
     63})
     64
     65#define futex_trylock(fut) \
     66({ \
     67        rcu_read_lock(); \
     68        int _upgraded = rcu_access(_upgrade_futexes); \
     69        if (_upgraded) { \
     70                int _acquired = futex_trydown((fut)); \
     71                if (!_acquired) { \
     72                        rcu_read_unlock(); \
     73                } else { \
     74                        (fut)->upgraded = true; \
     75                } \
     76                _acquired; \
     77        } else { \
     78                (fut)->upgraded = false; \
     79                1; \
     80        } \
     81})
     82               
     83#define futex_unlock(fut) \
     84({ \
     85        if ((fut)->upgraded) \
     86                (void) futex_up((fut)); \
     87        rcu_read_unlock(); \
     88})
     89
     90extern int _upgrade_futexes;
     91
     92extern void futex_upgrade_all_and_wait(void);
     93               
     94#else
     95
     96#define FUTEX_INITIALIZE(val) {{ (val) }}
     97
     98#define futex_lock(fut)     (void) futex_down((fut))
     99#define futex_trylock(fut)  futex_trydown((fut))
     100#define futex_unlock(fut)   (void) futex_up((fut))
     101               
     102#endif
     103
     104#define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
     105
     106/** Try to down the futex.
     107 *
     108 * @param futex Futex.
     109 *
     110 * @return Non-zero if the futex was acquired.
     111 * @return Zero if the futex was not acquired.
     112 *
     113 */
     114static inline int futex_trydown(futex_t *futex)
     115{
     116        return cas(&futex->val, 1, 0);
     117}
     118
     119/** Down the futex.
     120 *
     121 * @param futex Futex.
     122 *
     123 * @return ENOENT if there is no such virtual address.
     124 * @return Zero in the uncontended case.
     125 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED.
     126 *
     127 */
     128static inline int futex_down(futex_t *futex)
     129{
     130        if ((atomic_signed_t) atomic_predec(&futex->val) < 0)
     131                return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count);
     132       
     133        return 0;
     134}
     135
     136/** Up the futex.
     137 *
     138 * @param futex Futex.
     139 *
     140 * @return ENOENT if there is no such virtual address.
     141 * @return Zero in the uncontended case.
     142 *
     143 */
     144static inline int futex_up(futex_t *futex)
     145{
     146        if ((atomic_signed_t) atomic_postinc(&futex->val) < 0)
     147                return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count);
     148       
     149        return 0;
     150}
    49151
    50152#endif
Note: See TracChangeset for help on using the changeset viewer.