Changeset 58775d30 in mainline for uspace/lib/c


Ignore:
Timestamp:
2015-03-16T16:07:21Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2003739
Parents:
6069061 (diff), 795e2bf (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:

Mainline changes

Location:
uspace/lib/c
Files:
3 added
22 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/Makefile

    r6069061 r58775d30  
    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/arch/ia32/Makefile.common

    r6069061 r58775d30  
    3232        GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
    3333endif
     34
    3435CLANG_CFLAGS += -fno-omit-frame-pointer
    3536
  • uspace/lib/c/arch/ia64/include/libarch/types.h

    r6069061 r58775d30  
    4646#define SSIZE_MAX  INT64_MAX
    4747
    48 typedef struct {
    49         uint64_t lo;
    50         int64_t hi;
    51 } __attribute__((aligned(16))) int128_t;
    52 
    53 typedef struct {
    54         uint64_t lo;
    55         uint64_t hi;
    56 } __attribute__((aligned(16))) uint128_t;
    57 
    5848typedef uint64_t sysarg_t;
    5949typedef int64_t native_t;
  • uspace/lib/c/generic/adt/hash_table.c

    r6069061 r58775d30  
    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

    r6069061 r58775d30  
    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. */
     
    820820        if (usecs) {
    821821                getuptime(&conn->wdata.to_event.expires);
    822                 tv_add(&conn->wdata.to_event.expires, usecs);
     822                tv_add_diff(&conn->wdata.to_event.expires, usecs);
    823823        } else
    824824                conn->wdata.to_event.inlist = false;
     
    12141214
    12151215                        } else {
    1216                                 timeout = tv_sub(&waiter->to_event.expires, &tv);
     1216                                timeout = tv_sub_diff(&waiter->to_event.expires,
     1217                                    &tv);
    12171218                                futex_up(&async_futex);
    12181219                        }
     
    15051506
    15061507        getuptime(&msg->wdata.to_event.expires);
    1507         tv_add(&msg->wdata.to_event.expires, timeout);
     1508        tv_add_diff(&msg->wdata.to_event.expires, timeout);
    15081509       
    15091510        /*
     
    15871588       
    15881589        getuptime(&msg->wdata.to_event.expires);
    1589         tv_add(&msg->wdata.to_event.expires, timeout);
     1590        tv_add_diff(&msg->wdata.to_event.expires, timeout);
    15901591       
    15911592        futex_down(&async_futex);
  • uspace/lib/c/generic/fibril.c

    r6069061 r58775d30  
    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/fibril_synch.c

    r6069061 r58775d30  
    380380        if (timeout) {
    381381                getuptime(&wdata.to_event.expires);
    382                 tv_add(&wdata.to_event.expires, timeout);
     382                tv_add_diff(&wdata.to_event.expires, timeout);
    383383                async_insert_timeout(&wdata);
    384384        }
  • uspace/lib/c/generic/futex.c

    r6069061 r58775d30  
    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/io/console.c

    r6069061 r58775d30  
    259259        struct timeval t1;
    260260        gettimeofday(&t1, NULL);
    261         *timeout -= tv_sub(&t1, &t0);
     261        *timeout -= tv_sub_diff(&t1, &t0);
    262262       
    263263        return true;
  • uspace/lib/c/generic/io/window.c

    r6069061 r58775d30  
    4040#include <stdio.h>
    4141
    42 int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out)
     42int win_register(async_sess_t *sess, window_flags_t flags, service_id_t *in,
     43    service_id_t *out)
    4344{
    4445        async_exch_t *exch = async_exchange_begin(sess);
    45         int ret = async_req_0_2(exch, WINDOW_REGISTER, in, out);
     46        int ret = async_req_1_2(exch, WINDOW_REGISTER, flags, in, out);
    4647        async_exchange_end(exch);
    4748       
  • uspace/lib/c/generic/ipc.c

    r6069061 r58775d30  
    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

    r6069061 r58775d30  
    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

    r6069061 r58775d30  
    6767/** Heap shrink granularity
    6868 *
    69  * Try not to pump and stress the heap to much
     69 * Try not to pump and stress the heap too much
    7070 * by shrinking and enlarging it too often.
    71  * A heap area won't shrunk if it the released
     71 * A heap area won't shrink if the released
    7272 * free block is smaller than this constant.
    7373 *
     
    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

    r6069061 r58775d30  
    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/generic/time.c

    r6069061 r58775d30  
    5959#define MINS_PER_HOUR  60
    6060#define SECS_PER_MIN   60
     61#define USECS_PER_SEC  1000000
    6162#define MINS_PER_DAY   (MINS_PER_HOUR * HOURS_PER_DAY)
    6263#define SECS_PER_HOUR  (SECS_PER_MIN * MINS_PER_HOUR)
     
    252253 * Optionally add specified amount of seconds.
    253254 *
    254  * @param tm      Broken-down time to normalize.
    255  * @param sec_add Seconds to add.
     255 * @param tm Broken-down time to normalize.
     256 * @param tv Timeval to add.
    256257 *
    257258 * @return 0 on success, -1 on overflow
    258259 *
    259260 */
    260 static int normalize_time(struct tm *tm, time_t sec_add)
     261static int normalize_tm_tv(struct tm *tm, const struct timeval *tv)
    261262{
    262263        // TODO: DST correction
    263264       
    264265        /* Set initial values. */
    265         time_t sec = tm->tm_sec + sec_add;
     266        time_t usec = tm->tm_usec + tv->tv_usec;
     267        time_t sec = tm->tm_sec + tv->tv_sec;
    266268        time_t min = tm->tm_min;
    267269        time_t hour = tm->tm_hour;
     
    271273       
    272274        /* Adjust time. */
     275        sec += floor_div(usec, USECS_PER_SEC);
     276        usec = floor_mod(usec, USECS_PER_SEC);
    273277        min += floor_div(sec, SECS_PER_MIN);
    274278        sec = floor_mod(sec, SECS_PER_MIN);
     
    319323       
    320324        /* And put the values back to the struct. */
     325        tm->tm_usec = (int) usec;
    321326        tm->tm_sec = (int) sec;
    322327        tm->tm_min = (int) min;
     
    335340}
    336341
     342static int normalize_tm_time(struct tm *tm, time_t time)
     343{
     344        struct timeval tv = {
     345                .tv_sec = time,
     346                .tv_usec = 0
     347        };
     348
     349        return normalize_tm_tv(tm, &tv);
     350}
     351
     352
    337353/** Which day the week-based year starts on.
    338354 *
     
    442458}
    443459
     460static void tv_normalize(struct timeval *tv)
     461{
     462        while (tv->tv_usec > USECS_PER_SEC) {
     463                tv->tv_sec++;
     464                tv->tv_usec -= USECS_PER_SEC;
     465        }
     466        while (tv->tv_usec < 0) {
     467                tv->tv_sec--;
     468                tv->tv_usec += USECS_PER_SEC;
     469        }
     470}
     471
    444472/** Add microseconds to given timeval.
    445473 *
     
    448476 *
    449477 */
    450 void tv_add(struct timeval *tv, suseconds_t usecs)
    451 {
    452         tv->tv_sec += usecs / 1000000;
    453         tv->tv_usec += usecs % 1000000;
    454        
    455         if (tv->tv_usec > 1000000) {
    456                 tv->tv_sec++;
    457                 tv->tv_usec -= 1000000;
    458         }
    459 }
    460 
    461 /** Subtract two timevals.
     478void tv_add_diff(struct timeval *tv, suseconds_t usecs)
     479{
     480        tv->tv_sec += usecs / USECS_PER_SEC;
     481        tv->tv_usec += usecs % USECS_PER_SEC;
     482        tv_normalize(tv);
     483}
     484
     485/** Add two timevals.
    462486 *
    463487 * @param tv1 First timeval.
    464488 * @param tv2 Second timeval.
     489 */
     490void tv_add(struct timeval *tv1, struct timeval *tv2)
     491{
     492        tv1->tv_sec += tv2->tv_sec;
     493        tv1->tv_usec += tv2->tv_usec;
     494        tv_normalize(tv1);
     495}
     496
     497/** Subtract two timevals.
     498 *
     499 * @param tv1 First timeval.
     500 * @param tv2 Second timeval.
    465501 *
    466502 * @return Difference between tv1 and tv2 (tv1 - tv2) in
     
    468504 *
    469505 */
    470 suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
     506suseconds_t tv_sub_diff(struct timeval *tv1, struct timeval *tv2)
    471507{
    472508        return (tv1->tv_usec - tv2->tv_usec) +
    473             ((tv1->tv_sec - tv2->tv_sec) * 1000000);
     509            ((tv1->tv_sec - tv2->tv_sec) * USECS_PER_SEC);
     510}
     511
     512/** Subtract two timevals.
     513 *
     514 * @param tv1 First timeval.
     515 * @param tv2 Second timeval.
     516 *
     517 */
     518void tv_sub(struct timeval *tv1, struct timeval *tv2)
     519{
     520        tv1->tv_sec -= tv2->tv_sec;
     521        tv1->tv_usec -= tv2->tv_usec;
     522        tv_normalize(tv1);
    474523}
    475524
     
    573622                goto fallback;
    574623       
    575         tv->tv_usec = 0;
     624        tv->tv_usec = time.tm_usec;
    576625        tv->tv_sec = mktime(&time);
    577626       
     
    689738        // TODO: detect overflow
    690739       
    691         normalize_time(tm, 0);
     740        normalize_tm_time(tm, 0);
    692741        return secs_since_epoch(tm);
    693742}
     
    944993       
    945994        /* Set result to epoch. */
     995        result->tm_usec = 0;
    946996        result->tm_sec = 0;
    947997        result->tm_min = 0;
     
    9511001        result->tm_year = 70; /* 1970 */
    9521002       
    953         if (normalize_time(result, time) == -1)
     1003        if (normalize_tm_time(result, time) == -1)
    9541004                return EOVERFLOW;
    9551005       
     
    10141064 * Time is expressed relative to the user's specified timezone.
    10151065 *
    1016  * @param timer  Time to convert.
     1066 * @param tv     Timeval to convert.
    10171067 * @param result Structure to store the result to.
    10181068 *
     
    10201070 *
    10211071 */
    1022 int time_local2tm(const time_t time, struct tm *restrict result)
     1072int time_tv2tm(const struct timeval *tv, struct tm *restrict result)
    10231073{
    10241074        // TODO: Deal with timezones.
     
    10261076       
    10271077        /* Set result to epoch. */
     1078        result->tm_usec = 0;
    10281079        result->tm_sec = 0;
    10291080        result->tm_min = 0;
     
    10331084        result->tm_year = 70; /* 1970 */
    10341085       
    1035         if (normalize_time(result, time) == -1)
     1086        if (normalize_tm_tv(result, tv) == -1)
    10361087                return EOVERFLOW;
    10371088       
    10381089        return EOK;
     1090}
     1091
     1092/** Converts a time value to a broken-down local time.
     1093 *
     1094 * Time is expressed relative to the user's specified timezone.
     1095 *
     1096 * @param timer  Time to convert.
     1097 * @param result Structure to store the result to.
     1098 *
     1099 * @return EOK on success or a negative error code.
     1100 *
     1101 */
     1102int time_local2tm(const time_t time, struct tm *restrict result)
     1103{
     1104        struct timeval tv = {
     1105                .tv_sec = time,
     1106                .tv_usec = 0
     1107        };
     1108
     1109        return time_tv2tm(&tv, result);
    10391110}
    10401111
  • uspace/lib/c/include/adt/list.h

    r6069061 r58775d30  
    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

    r6069061 r58775d30  
    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/io/window.h

    r6069061 r58775d30  
    4242#include <io/kbd_event.h>
    4343#include <io/pos_event.h>
     44
     45typedef enum {
     46        WINDOW_MAIN = 1,
     47        WINDOW_DECORATED = 2,
     48        WINDOW_RESIZEABLE = 4
     49} window_flags_t;
    4450
    4551typedef enum {
     
    108114} window_event_t;
    109115
    110 extern int win_register(async_sess_t *, service_id_t *, service_id_t *);
     116extern int win_register(async_sess_t *, window_flags_t, service_id_t *,
     117    service_id_t *);
    111118
    112119extern int win_get_event(async_sess_t *, window_event_t *);
  • uspace/lib/c/include/ipc/common.h

    r6069061 r58775d30  
    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

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

    r6069061 r58775d30  
    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

    r6069061 r58775d30  
    5050
    5151struct tm {
     52        int tm_usec;   /* Microseconds [0,999999]. */
    5253        int tm_sec;    /* Seconds [0,60]. */
    5354        int tm_min;    /* Minutes [0,59]. */
     
    7172};
    7273
    73 extern void tv_add(struct timeval *, suseconds_t);
    74 extern suseconds_t tv_sub(struct timeval *, struct timeval *);
     74extern void tv_add_diff(struct timeval *, suseconds_t);
     75extern void tv_add(struct timeval *, struct timeval *);
     76extern suseconds_t tv_sub_diff(struct timeval *, struct timeval *);
     77extern void tv_sub(struct timeval *, struct timeval *);
    7578extern int tv_gt(struct timeval *, struct timeval *);
    7679extern int tv_gteq(struct timeval *, struct timeval *);
     
    7982
    8083extern void udelay(useconds_t);
     84extern int usleep(useconds_t);
    8185
    8286extern time_t mktime(struct tm *);
     
    8488extern int time_utc2str(const time_t, char *);
    8589extern void time_tm2str(const struct tm *, char *);
     90extern int time_tv2tm(const struct timeval *, struct tm *);
    8691extern int time_local2tm(const time_t, struct tm *);
    8792extern int time_local2str(const time_t, char *);
Note: See TracChangeset for help on using the changeset viewer.