Changeset b1c57a8 in mainline for uspace


Ignore:
Timestamp:
2014-10-09T15:03:55Z (11 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e367939c
Parents:
21799398 (diff), 207e8880 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~adam-hraska+lp/helenos/rcu/.

Only merge from the feature branch and resolve all conflicts.

Location:
uspace
Files:
10 added
17 edited

Legend:

Unmodified
Added
Removed
  • uspace/Makefile

    r21799398 rb1c57a8  
    6161        app/nterm \
    6262        app/redir \
     63        app/rcutest \
     64        app/rcubench \
    6365        app/sbi \
    6466        app/sportdmp \
     
    227229        lib/trackmod \
    228230        lib/uri \
     231        lib/urcu \
    229232        lib/usb \
    230233        lib/usbhost \
  • uspace/Makefile.common

    r21799398 rb1c57a8  
    156156LIBGPT_PREFIX = $(LIB_PREFIX)/gpt
    157157
     158LIBURCU_PREFIX = $(LIB_PREFIX)/urcu
     159
    158160ifeq ($(STATIC_NEEDED),y)
    159161        STATIC_BUILD = y
     
    281283JOBFILE = $(LIBC_PREFIX)/../../../tools/jobfile.py
    282284
     285ifeq ($(FUTEX_UPGRADABLE),y)
     286        CFLAGS += -I$(LIBURCU_PREFIX)/
     287        LIBS += $(LIBURCU_PREFIX)/liburcu.a
     288endif
     289
    283290ifeq ($(COMPILER),gcc_cross)
    284291        CFLAGS += $(GCC_CFLAGS) $(EXTRA_CFLAGS)
  • uspace/lib/c/Makefile

    r21799398 rb1c57a8  
    4747LSONAME = libc.so0
    4848
     49LIBS = $(LIBURCU_PREFIX)/liburcu.a
     50EXTRA_CFLAGS += -I$(LIBURCU_PREFIX)
     51
    4952-include $(CONFIG_MAKEFILE)
    5053-include arch/$(UARCH)/Makefile.inc
     
    8891        generic/pcb.c \
    8992        generic/smc.c \
     93        generic/smp_memory_barrier.c \
    9094        generic/thread.c \
    9195        generic/tls.c \
  • uspace/lib/c/generic/adt/hash_table.c

    r21799398 rb1c57a8  
    134134        free(h->bucket);
    135135
    136         h->bucket = 0;
     136        h->bucket = NULL;
    137137        h->bucket_cnt = 0;
    138138}
  • uspace/lib/c/generic/async.c

    r21799398 rb1c57a8  
    167167
    168168/** Async framework global futex */
    169 atomic_t async_futex = FUTEX_INITIALIZER;
     169futex_t async_futex = FUTEX_INITIALIZER;
    170170
    171171/** Number of threads waiting for IPC in the kernel. */
  • uspace/lib/c/generic/fibril.c

    r21799398 rb1c57a8  
    4949#include <assert.h>
    5050#include <async.h>
     51#include <futex.h>
     52
     53#ifdef FUTEX_UPGRADABLE
     54#include <rcu.h>
     55#endif
    5156
    5257/**
     
    5459 * serialized_list and manager_list.
    5560 */
    56 static atomic_t fibril_futex = FUTEX_INITIALIZER;
     61static futex_t fibril_futex = FUTEX_INITIALIZER;
    5762
    5863static LIST_INITIALIZE(ready_list);
     
    8388{
    8489        fibril_t *fibril = __tcb_get()->fibril_data;
     90
     91#ifdef FUTEX_UPGRADABLE
     92        rcu_register_fibril();
     93#endif
    8594       
    8695        /* Call the implementing function. */
     
    146155        int retval = 0;
    147156       
    148         futex_down(&fibril_futex);
     157        futex_lock(&fibril_futex);
    149158       
    150159        if (stype == FIBRIL_PREEMPT && list_empty(&ready_list))
     
    168177        if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
    169178                while (list_empty(&manager_list)) {
    170                         futex_up(&fibril_futex);
     179                        futex_unlock(&fibril_futex);
    171180                        async_create_manager();
    172                         futex_down(&fibril_futex);
     181                        futex_lock(&fibril_futex);
    173182                }
    174183        }
     
    203212                        }
    204213                       
    205                         return 1;       /* futex_up already done here */
     214                        return 1;       /* futex_unlock already done here */
    206215                }
    207216               
     
    246255        list_remove(&dstf->link);
    247256       
    248         futex_up(&fibril_futex);
     257        futex_unlock(&fibril_futex);
     258       
     259#ifdef FUTEX_UPGRADABLE
     260        if (stype == FIBRIL_FROM_DEAD) {
     261                rcu_deregister_fibril();
     262        }
     263#endif
     264       
    249265        context_restore(&dstf->ctx);
    250266        /* not reached */
    251267       
    252268ret_0:
    253         futex_up(&fibril_futex);
     269        futex_unlock(&fibril_futex);
    254270        return retval;
    255271}
     
    318334        fibril_t *fibril = (fibril_t *) fid;
    319335       
    320         futex_down(&fibril_futex);
     336        futex_lock(&fibril_futex);
    321337       
    322338        if ((fibril->flags & FIBRIL_SERIALIZED))
     
    325341                list_append(&fibril->link, &ready_list);
    326342       
    327         futex_up(&fibril_futex);
     343        futex_unlock(&fibril_futex);
    328344}
    329345
     
    338354        fibril_t *fibril = (fibril_t *) fid;
    339355       
    340         futex_down(&fibril_futex);
     356        futex_lock(&fibril_futex);
    341357        list_append(&fibril->link, &manager_list);
    342         futex_up(&fibril_futex);
     358        futex_unlock(&fibril_futex);
    343359}
    344360
     
    346362void fibril_remove_manager(void)
    347363{
    348         futex_down(&fibril_futex);
     364        futex_lock(&fibril_futex);
    349365       
    350366        if (!list_empty(&manager_list))
    351367                list_remove(list_first(&manager_list));
    352368       
    353         futex_up(&fibril_futex);
     369        futex_unlock(&fibril_futex);
    354370}
    355371
  • uspace/lib/c/generic/futex.c

    r21799398 rb1c57a8  
    3535#include <futex.h>
    3636#include <atomic.h>
    37 #include <libarch/barrier.h>
    38 #include <libc.h>
    39 #include <sys/types.h>
    4037
    4138/** Initialize futex counter.
     
    4744void futex_initialize(futex_t *futex, int val)
    4845{
    49         atomic_set(futex, val);
     46        atomic_set(&futex->val, val);
    5047}
    5148
    52 /** Try to down the futex.
    53  *
    54  * @param futex Futex.
    55  *
    56  * @return Non-zero if the futex was acquired.
    57  * @return Zero if the futex was not acquired.
    58  *
    59  */
    60 int futex_trydown(futex_t *futex)
     49
     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         int rc;
    63 
    64         rc = cas(futex, 1, 0);
    65         CS_ENTER_BARRIER();
    66 
    67         return rc;
     57        futex_down(&upg_and_wait_futex);
     58       
     59        if (!_upgrade_futexes) {
     60                rcu_assign(_upgrade_futexes, 1);
     61                _rcu_synchronize(BM_BLOCK_THREAD);
     62        }
     63       
     64        futex_up(&upg_and_wait_futex);
    6865}
    6966
    70 /** Down the futex.
    71  *
    72  * @param futex Futex.
    73  *
    74  * @return ENOENT if there is no such virtual address.
    75  * @return Zero in the uncontended case.
    76  * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED.
    77  *
    78  */
    79 int futex_down(futex_t *futex)
    80 {
    81         atomic_signed_t nv;
    82 
    83         nv = (atomic_signed_t) atomic_predec(futex);
    84         CS_ENTER_BARRIER();
    85         if (nv < 0)
    86                 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count);
    87        
    88         return 0;
    89 }
    90 
    91 /** Up the futex.
    92  *
    93  * @param futex Futex.
    94  *
    95  * @return ENOENT if there is no such virtual address.
    96  * @return Zero in the uncontended case.
    97  *
    98  */
    99 int futex_up(futex_t *futex)
    100 {
    101         CS_LEAVE_BARRIER();
    102 
    103         if ((atomic_signed_t) atomic_postinc(futex) < 0)
    104                 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count);
    105        
    106         return 0;
    107 }
     67#endif
    10868
    10969/** @}
  • uspace/lib/c/generic/ipc.c

    r21799398 rb1c57a8  
    8181LIST_INITIALIZE(queued_calls);
    8282
    83 static atomic_t ipc_futex = FUTEX_INITIALIZER;
     83static futex_t ipc_futex = FUTEX_INITIALIZER;
    8484
    8585/** Send asynchronous message via syscall.
     
    136136        if (!call) {
    137137                /* Nothing to do regardless if failed or not */
    138                 futex_up(&ipc_futex);
     138                futex_unlock(&ipc_futex);
    139139                return;
    140140        }
    141141       
    142142        if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
    143                 futex_up(&ipc_futex);
     143                futex_unlock(&ipc_futex);
    144144               
    145145                /* Call asynchronous handler with error code */
     
    152152       
    153153        if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
    154                 futex_up(&ipc_futex);
     154                futex_unlock(&ipc_futex);
    155155               
    156156                call->u.msg.phoneid = phoneid;
     
    175175        /* Add call to the list of dispatched calls */
    176176        list_append(&call->list, &dispatched_calls);
    177         futex_up(&ipc_futex);
     177        futex_unlock(&ipc_futex);
    178178}
    179179
     
    219219         */
    220220       
    221         futex_down(&ipc_futex);
     221        futex_lock(&ipc_futex);
    222222        ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,
    223223            imethod, arg1, arg2, arg3, arg4);
     
    226226                if (!call) {
    227227                        call = ipc_prepare_async(private, callback);
    228                         if (!call)
     228                        if (!call) {
     229                                futex_unlock(&ipc_futex);
    229230                                return;
     231                        }
    230232                }
    231233               
     
    289291         */
    290292       
    291         futex_down(&ipc_futex);
     293        futex_lock(&ipc_futex);
    292294        ipc_callid_t callid =
    293295            ipc_call_async_internal(phoneid, &call->u.msg.data);
     
    384386                        call->u.callid = callid;
    385387                       
    386                         futex_down(&ipc_futex);
     388                        futex_lock(&ipc_futex);
    387389                        list_append(&call->list, &dispatched_calls);
    388                         futex_up(&ipc_futex);
     390                        futex_unlock(&ipc_futex);
    389391                }
    390392               
     
    412414        callid &= ~IPC_CALLID_ANSWERED;
    413415       
    414         futex_down(&ipc_futex);
     416        futex_lock(&ipc_futex);
    415417       
    416418        link_t *item;
     
    423425                        list_remove(&call->list);
    424426                       
    425                         futex_up(&ipc_futex);
     427                        futex_unlock(&ipc_futex);
    426428                       
    427429                        if (call->callback)
     
    434436        }
    435437       
    436         futex_up(&ipc_futex);
     438        futex_unlock(&ipc_futex);
    437439}
    438440
  • uspace/lib/c/generic/libc.c

    r21799398 rb1c57a8  
    5252#include "private/io.h"
    5353
     54#ifdef FUTEX_UPGRADABLE
     55#include <rcu.h>
     56#endif
     57
    5458#ifdef CONFIG_RTLD
    5559#include <rtld/rtld.h>
    5660#endif
     61
    5762
    5863static bool env_setup = false;
     
    6267        /* Initialize user task run-time environment */
    6368        __malloc_init();
    64         __async_init();
    6569       
    6670        fibril_t *fibril = fibril_setup();
     
    7276        /* Save the PCB pointer */
    7377        __pcb = (pcb_t *) pcb_ptr;
     78       
     79#ifdef FUTEX_UPGRADABLE
     80        rcu_register_fibril();
     81#endif
     82       
     83        __async_init();
    7484       
    7585        /* The basic run-time environment is setup */
  • uspace/lib/c/generic/malloc.c

    r21799398 rb1c57a8  
    200200        do { \
    201201                if (!(expr)) {\
    202                         futex_up(&malloc_futex); \
     202                        heap_unlock(); \
    203203                        assert_abort(#expr, __FILE__, __LINE__); \
    204204                } \
     
    210210
    211211#endif /* NDEBUG */
     212
     213
     214#ifdef FUTEX_UPGRADABLE
     215/** True if the heap may be accessed from multiple threads. */
     216static bool multithreaded = false;
     217
     218/** Makes accesses to the heap thread safe. */
     219void malloc_enable_multithreaded(void)
     220{
     221        multithreaded = true;
     222}
     223
     224/** Serializes access to the heap from multiple threads. */
     225static inline void heap_lock(void)
     226{
     227        if (multithreaded) {
     228                futex_down(&malloc_futex);
     229        } else {
     230                /*
     231                 * Malloc never switches fibrils while the heap is locked.
     232                 * Similarly, it never creates new threads from within the
     233                 * locked region. Therefore, if there are no other threads
     234                 * except this one, the whole operation will complete without
     235                 * any interruptions.
     236                 */
     237        }
     238}
     239
     240/** Serializes access to the heap from multiple threads. */
     241static inline void heap_unlock(void)
     242{
     243        if (multithreaded) {
     244                futex_up(&malloc_futex);
     245        } else {
     246                /*
     247                 * Malloc never switches fibrils while the heap is locked.
     248                 * Similarly, it never creates new threads from within the
     249                 * locked region. Therefore, if there are no other threads
     250                 * except this one, the whole operation will complete without
     251                 * any interruptions.
     252                 */
     253        }
     254}
     255
     256#else
     257
     258/** Makes accesses to the heap thread safe. */
     259void malloc_enable_multithreaded(void)
     260{
     261        /* No-op. Already using thread-safe heap locking operations. */
     262}
     263
     264/** Serializes access to the heap from multiple threads. */
     265static inline void heap_lock(void)
     266{
     267        futex_down(&malloc_futex);
     268}
     269
     270/** Serializes access to the heap from multiple threads. */
     271static inline void heap_unlock(void)
     272{
     273        futex_up(&malloc_futex);
     274}
     275#endif
     276
    212277
    213278/** Initialize a heap block
     
    785850void *malloc(const size_t size)
    786851{
    787         futex_down(&malloc_futex);
     852        heap_lock();
    788853        void *block = malloc_internal(size, BASE_ALIGN);
    789         futex_up(&malloc_futex);
    790        
     854        heap_unlock();
     855
    791856        return block;
    792857}
     
    807872        size_t palign =
    808873            1 << (fnzb(max(sizeof(void *), align) - 1) + 1);
    809        
    810         futex_down(&malloc_futex);
     874
     875        heap_lock();
    811876        void *block = malloc_internal(size, palign);
    812         futex_up(&malloc_futex);
    813        
     877        heap_unlock();
     878
    814879        return block;
    815880}
     
    828893                return malloc(size);
    829894       
    830         futex_down(&malloc_futex);
     895        heap_lock();
    831896       
    832897        /* Calculate the position of the header. */
     
    885950        }
    886951       
    887         futex_up(&malloc_futex);
     952        heap_unlock();
    888953       
    889954        if (reloc) {
     
    908973                return;
    909974       
    910         futex_down(&malloc_futex);
     975        heap_lock();
    911976       
    912977        /* Calculate the position of the header. */
     
    9531018        heap_shrink(area);
    9541019       
    955         futex_up(&malloc_futex);
     1020        heap_unlock();
    9561021}
    9571022
    9581023void *heap_check(void)
    9591024{
    960         futex_down(&malloc_futex);
     1025        heap_lock();
    9611026       
    9621027        if (first_heap_area == NULL) {
    963                 futex_up(&malloc_futex);
     1028                heap_unlock();
    9641029                return (void *) -1;
    9651030        }
     
    9751040                    (((uintptr_t) area->start % PAGE_SIZE) != 0) ||
    9761041                    (((uintptr_t) area->end % PAGE_SIZE) != 0)) {
    977                         futex_up(&malloc_futex);
     1042                        heap_unlock();
    9781043                        return (void *) area;
    9791044                }
     
    9861051                        /* Check heap block consistency */
    9871052                        if (head->magic != HEAP_BLOCK_HEAD_MAGIC) {
    988                                 futex_up(&malloc_futex);
     1053                                heap_unlock();
    9891054                                return (void *) head;
    9901055                        }
     
    9941059                        if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) ||
    9951060                            (head->size != foot->size)) {
    996                                 futex_up(&malloc_futex);
     1061                                heap_unlock();
    9971062                                return (void *) foot;
    9981063                        }
     
    10001065        }
    10011066       
    1002         futex_up(&malloc_futex);
     1067        heap_unlock();
    10031068       
    10041069        return NULL;
  • uspace/lib/c/generic/thread.c

    r21799398 rb1c57a8  
    4646#include "private/thread.h"
    4747
     48#ifdef FUTEX_UPGRADABLE
     49#include <rcu.h>
     50#endif
     51
     52
    4853/** Main thread function.
    4954 *
     
    6368        __tcb_set(fibril->tcb);
    6469       
     70#ifdef FUTEX_UPGRADABLE
     71        rcu_register_fibril();
     72        futex_upgrade_all_and_wait();
     73#endif
     74       
    6575        uarg->uspace_thread_function(uarg->uspace_thread_arg);
    6676        /*
     
    7383        /* If there is a manager, destroy it */
    7484        async_destroy_manager();
     85
     86#ifdef FUTEX_UPGRADABLE
     87        rcu_deregister_fibril();
     88#endif
     89       
    7590        fibril_teardown(fibril);
    7691       
     
    106121                return ENOMEM;
    107122        }
     123       
     124        /* Make heap thread safe. */
     125        malloc_enable_multithreaded();
    108126       
    109127        uarg->uspace_entry = (void *) FADDR(__thread_entry);
  • uspace/lib/c/include/adt/list.h

    r21799398 rb1c57a8  
    5858 */
    5959#define LIST_INITIALIZE(name) \
    60         list_t name = { \
     60        list_t name = LIST_INITIALIZER(name)
     61
     62/** Initializer for statically allocated list.
     63 *
     64 * @code
     65 * struct named_list {
     66 *     const char *name;
     67 *     list_t list;
     68 * } var = {
     69 *     .name = "default name",
     70 *     .list = LIST_INITIALIZER(name_list.list)
     71 * };
     72 * @endcode
     73 *
     74 * @param name Name of the new statically allocated list.
     75 *
     76 */
     77#define LIST_INITIALIZER(name) \
     78        { \
    6179                .head = { \
    6280                        .prev = &(name).head, \
  • uspace/lib/c/include/futex.h

    r21799398 rb1c57a8  
    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
  • uspace/lib/c/include/ipc/common.h

    r21799398 rb1c57a8  
    4040#include <atomic.h>
    4141#include <abi/proc/task.h>
     42#include <futex.h>
    4243
    4344#define IPC_FLAG_BLOCKING  0x01
     
    5152typedef sysarg_t ipc_callid_t;
    5253
    53 extern atomic_t async_futex;
     54extern futex_t async_futex;
    5455
    5556#endif
  • uspace/lib/c/include/malloc.h

    r21799398 rb1c57a8  
    4848extern void *heap_check(void);
    4949
     50extern void malloc_enable_multithreaded(void);
    5051#endif
    5152
  • uspace/lib/c/include/rwlock.h

    r21799398 rb1c57a8  
    4949
    5050#define rwlock_initialize(rwlock)       futex_initialize((rwlock), 1)
    51 #define rwlock_read_lock(rwlock)        futex_down((rwlock))
    52 #define rwlock_write_lock(rwlock)       futex_down((rwlock))
    53 #define rwlock_read_unlock(rwlock)      futex_up((rwlock))
    54 #define rwlock_write_unlock(rwlock)     futex_up((rwlock))
     51#define rwlock_read_lock(rwlock)        futex_lock((rwlock))
     52#define rwlock_write_lock(rwlock)       futex_lock((rwlock))
     53#define rwlock_read_unlock(rwlock)      futex_unlock((rwlock))
     54#define rwlock_write_unlock(rwlock)     futex_unlock((rwlock))
    5555
    5656#endif
  • uspace/lib/c/include/sys/time.h

    r21799398 rb1c57a8  
    7979
    8080extern void udelay(useconds_t);
     81extern int usleep(useconds_t);
    8182
    8283extern time_t mktime(struct tm *tm);
Note: See TracChangeset for help on using the changeset viewer.