Changes in / [034bf0e:bc77bfa] in mainline


Ignore:
Files:
1 deleted
37 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r034bf0e rbc77bfa  
    4343        $(MAKE) -C kernel clean
    4444        $(MAKE) -C kernel EXTRA_TOOL=stanse
    45         $(STANSE) --checker ReachabilityChecker --jobfile kernel/kernel.job
     45        $(STANSE) --checker ReachabilityChecker --checker ThreadChecker:contrib/$(STANSE)/ThreadChecker.xml --jobfile kernel/kernel.job
    4646
    4747cscope:
  • kernel/arch/amd64/src/amd64.c

    r034bf0e rbc77bfa  
    6767#include <ddi/irq.h>
    6868#include <sysinfo/sysinfo.h>
    69 #include <memstr.h>
    7069
    7170/** Disable I/O on non-privileged levels
  • kernel/arch/arm32/include/atomic.h

    r034bf0e rbc77bfa  
    3737#define KERN_arm32_ATOMIC_H_
    3838
    39 #include <arch/asm.h>
    40 
    4139/** Atomic addition.
    4240 *
     
    4947static inline long atomic_add(atomic_t *val, int i)
    5048{
    51         long ret;
    52 
    53         /*
    54          * This implementation is for UP pre-ARMv6 systems where we do not have
    55          * the LDREX and STREX instructions.
    56          */
    57         ipl_t ipl = interrupts_disable();
    58         val->count += i;
    59         ret = val->count;
    60         interrupts_restore(ipl);
     49        int ret;
     50        volatile long *mem = &(val->count);
     51       
     52        asm volatile (
     53                "1:\n"
     54                        "ldr r2, [%[mem]]\n"
     55                        "add r3, r2, %[i]\n"
     56                        "str r3, %[ret]\n"
     57                        "swp r3, r3, [%[mem]]\n"
     58                        "cmp r3, r2\n"
     59                        "bne 1b\n"
     60                : [ret] "=m" (ret)
     61                : [mem] "r" (mem), [i] "r" (i)
     62                : "r3", "r2"
     63        );
    6164       
    6265        return ret;
  • kernel/arch/arm32/src/mm/as.c

    r034bf0e rbc77bfa  
    3636#include <arch/mm/as.h>
    3737#include <genarch/mm/as_pt.h>
    38 #include <genarch/mm/page_pt.h>
    3938#include <genarch/mm/asid_fifo.h>
    4039#include <mm/as.h>
  • kernel/arch/ia32/src/ia32.c

    r034bf0e rbc77bfa  
    6868#include <sysinfo/sysinfo.h>
    6969#include <arch/boot/boot.h>
    70 #include <memstr.h>
    7170
    7271#ifdef CONFIG_SMP
  • kernel/arch/ia64/src/cpu/cpu.c

    r034bf0e rbc77bfa  
    3737#include <arch/register.h>
    3838#include <print.h>
    39 #include <memstr.h>
    4039
    4140void cpu_arch_init(void)
  • kernel/arch/ppc32/src/mm/as.c

    r034bf0e rbc77bfa  
    3535#include <arch/mm/as.h>
    3636#include <genarch/mm/as_pt.h>
    37 #include <genarch/mm/page_pt.h>
    3837#include <genarch/mm/asid_fifo.h>
    3938#include <arch.h>
  • kernel/arch/ppc32/src/mm/tlb.c

    r034bf0e rbc77bfa  
    3838#include <interrupt.h>
    3939#include <mm/as.h>
    40 #include <mm/page.h>
    4140#include <arch.h>
    4241#include <print.h>
  • kernel/arch/ppc32/src/ppc32.c

    r034bf0e rbc77bfa  
    4444#include <genarch/ofw/pci.h>
    4545#include <userspace.h>
    46 #include <mm/page.h>
    4746#include <proc/uarg.h>
    4847#include <console/console.h>
  • kernel/arch/sparc64/src/mm/tlb.c

    r034bf0e rbc77bfa  
    3737#include <mm/as.h>
    3838#include <mm/asid.h>
    39 #include <genarch/mm/page_ht.h>
    4039#include <arch/mm/frame.h>
    4140#include <arch/mm/page.h>
  • kernel/genarch/src/drivers/via-cuda/cuda.c

    r034bf0e rbc77bfa  
    4141#include <ddi/device.h>
    4242#include <synch/spinlock.h>
    43 #include <memstr.h>
    4443
    4544static irq_ownership_t cuda_claim(irq_t *irq);
  • kernel/genarch/src/fb/fb.c

    r034bf0e rbc77bfa  
    4141#include <console/console.h>
    4242#include <sysinfo/sysinfo.h>
    43 #include <mm/page.h>
    4443#include <mm/slab.h>
    4544#include <align.h>
  • kernel/generic/include/arch.h

    r034bf0e rbc77bfa  
    3939#include <proc/thread.h>
    4040#include <proc/task.h>
    41 #include <mm/as.h>
    4241
    4342#define DEFAULT_CONTEXT         0
  • kernel/generic/include/proc/task.h

    r034bf0e rbc77bfa  
    5555#include <udebug/udebug.h>
    5656#include <ipc/kbox.h>
    57 #include <mm/as.h>
    5857
    5958#define TASK_NAME_BUFLEN        20
  • kernel/generic/include/proc/thread.h

    r034bf0e rbc77bfa  
    225225
    226226extern void thread_init(void);
    227 extern thread_t *thread_create(void (*)(void *), void *, task_t *, int, char *,
    228     bool);
    229 extern void thread_attach(thread_t *, task_t *);
    230 extern void thread_ready(thread_t *);
     227extern thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
     228    int flags, char *name, bool uncounted);
     229extern void thread_attach(thread_t *t, task_t *task);
     230extern void thread_ready(thread_t *t);
    231231extern void thread_exit(void) __attribute__((noreturn));
    232232
    233233#ifndef thread_create_arch
    234 extern void thread_create_arch(thread_t *);
     234extern void thread_create_arch(thread_t *t);
    235235#endif
    236236#ifndef thr_constructor_arch
    237 extern void thr_constructor_arch(thread_t *);
     237extern void thr_constructor_arch(thread_t *t);
    238238#endif
    239239#ifndef thr_destructor_arch
    240 extern void thr_destructor_arch(thread_t *);
    241 #endif
    242 
    243 extern void thread_sleep(uint32_t);
    244 extern void thread_usleep(uint32_t);
     240extern void thr_destructor_arch(thread_t *t);
     241#endif
     242
     243extern void thread_sleep(uint32_t sec);
     244extern void thread_usleep(uint32_t usec);
    245245
    246246#define thread_join(t) \
    247247        thread_join_timeout((t), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE)
    248 extern int thread_join_timeout(thread_t *, uint32_t, int);
    249 extern void thread_detach(thread_t *);
    250 
    251 extern void thread_register_call_me(void (*)(void *), void *);
     248extern int thread_join_timeout(thread_t *t, uint32_t usec, int flags);
     249extern void thread_detach(thread_t *t);
     250
     251extern void thread_register_call_me(void (* call_me)(void *),
     252    void *call_me_with);
    252253extern void thread_print_list(void);
    253 extern void thread_destroy(thread_t *);
     254extern void thread_destroy(thread_t *t);
    254255extern void thread_update_accounting(void);
    255 extern bool thread_exists(thread_t *);
     256extern bool thread_exists(thread_t *t);
    256257
    257258/** Fpu context slab cache. */
     
    259260
    260261/* Thread syscall prototypes. */
    261 extern unative_t sys_thread_create(uspace_arg_t *, char *, size_t,
    262     thread_id_t *);
    263 extern unative_t sys_thread_exit(int);
    264 extern unative_t sys_thread_get_id(thread_id_t *);
    265 extern unative_t sys_thread_usleep(uint32_t);
     262extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg,
     263    char *uspace_name, size_t name_len, thread_id_t *uspace_thread_id);
     264extern unative_t sys_thread_exit(int uspace_status);
     265extern unative_t sys_thread_get_id(thread_id_t *uspace_thread_id);
    266266
    267267#endif
  • kernel/generic/include/synch/futex.h

    r034bf0e rbc77bfa  
    3838#include <arch/types.h>
    3939#include <synch/waitq.h>
     40#include <genarch/mm/page_ht.h>
     41#include <genarch/mm/page_pt.h>
    4042
    4143/** Kernel-side futex structure. */
     
    5254
    5355extern void futex_init(void);
    54 extern unative_t sys_futex_sleep(uintptr_t);
    55 extern unative_t sys_futex_wakeup(uintptr_t);
     56extern unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec,
     57    int flags);
     58extern unative_t sys_futex_wakeup(uintptr_t uaddr);
    5659
    5760extern void futex_cleanup(void);
  • kernel/generic/include/syscall/syscall.h

    r034bf0e rbc77bfa  
    4343        SYS_THREAD_EXIT,
    4444        SYS_THREAD_GET_ID,
    45         SYS_THREAD_USLEEP,
    4645       
    4746        SYS_TASK_GET_ID,
  • kernel/generic/src/mm/backend_phys.c

    r034bf0e rbc77bfa  
    4040#include <arch/types.h>
    4141#include <mm/as.h>
    42 #include <mm/page.h>
    4342#include <mm/frame.h>
    4443#include <mm/slab.h>
  • kernel/generic/src/proc/task.c

    r034bf0e rbc77bfa  
    5454#include <func.h>
    5555#include <string.h>
    56 #include <memstr.h>
    5756#include <syscall/copy.h>
    5857#include <macros.h>
  • kernel/generic/src/proc/thread.c

    r034bf0e rbc77bfa  
    501501void thread_sleep(uint32_t sec)
    502502{
    503         /* Sleep in 1000 second steps to support
    504            full argument range */
    505         while (sec > 0) {
    506                 uint32_t period = (sec > 1000) ? 1000 : sec;
    507        
    508                 thread_usleep(period * 1000000);
    509                 sec -= period;
    510         }
     503        thread_usleep(sec * 1000000);
    511504}
    512505
     
    582575{
    583576        waitq_t wq;
    584        
     577                                 
    585578        waitq_initialize(&wq);
    586        
     579
    587580        (void) waitq_sleep_timeout(&wq, usec, SYNCH_FLAGS_NON_BLOCKING);
    588581}
     
    819812}
    820813
    821 /** Syscall wrapper for sleeping. */
    822 unative_t sys_thread_usleep(uint32_t usec)
    823 {
    824         thread_usleep(usec);
    825         return 0;
    826 }
    827 
    828814/** @}
    829815 */
  • kernel/generic/src/synch/futex.c

    r034bf0e rbc77bfa  
    9090/** Initialize kernel futex structure.
    9191 *
    92  * @param futex         Kernel futex structure.
     92 * @param futex Kernel futex structure.
    9393 */
    9494void futex_initialize(futex_t *futex)
     
    102102/** Sleep in futex wait queue.
    103103 *
    104  * @param uaddr         Userspace address of the futex counter.
    105  *
    106  * @return              If there is no physical mapping for uaddr ENOENT is
    107  *                      returned. Otherwise returns a wait result as defined in
    108  *                      synch.h.
    109  */
    110 unative_t sys_futex_sleep(uintptr_t uaddr)
     104 * @param uaddr Userspace address of the futex counter.
     105 * @param usec If non-zero, number of microseconds this thread is willing to
     106 *     sleep.
     107 * @param flags Select mode of operation.
     108 *
     109 * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See
     110 *     synch.h. If there is no physical mapping for uaddr ENOENT is returned.
     111 */
     112unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec, int flags)
    111113{
    112114        futex_t *futex;
     
    138140        udebug_stoppable_begin();
    139141#endif
    140         rc = waitq_sleep_timeout(&futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE);
     142        rc = waitq_sleep_timeout(&futex->wq, usec, flags |
     143            SYNCH_FLAGS_INTERRUPTIBLE);
     144
    141145#ifdef CONFIG_UDEBUG
    142146        udebug_stoppable_end();
     
    147151/** Wakeup one thread waiting in futex wait queue.
    148152 *
    149  * @param uaddr         Userspace address of the futex counter.
    150  *
    151  * @return              ENOENT if there is no physical mapping for uaddr.
     153 * @param uaddr Userspace address of the futex counter.
     154 *
     155 * @return ENOENT if there is no physical mapping for uaddr.
    152156 */
    153157unative_t sys_futex_wakeup(uintptr_t uaddr)
     
    186190 * If the structure does not exist already, a new one is created.
    187191 *
    188  * @param paddr         Physical address of the userspace futex counter.
    189  *
    190  * @return              Address of the kernel futex structure.
     192 * @param paddr Physical address of the userspace futex counter.
     193 *
     194 * @return Address of the kernel futex structure.
    191195 */
    192196futex_t *futex_find(uintptr_t paddr)
     
    280284/** Compute hash index into futex hash table.
    281285 *
    282  * @param key           Address where the key (i.e. physical address of futex
    283  *                      counter) is stored.
    284  *
    285  * @return              Index into futex hash table.
     286 * @param key Address where the key (i.e. physical address of futex counter) is
     287 *    stored.
     288 *
     289 * @return Index into futex hash table.
    286290 */
    287291size_t futex_ht_hash(unative_t *key)
     
    292296/** Compare futex hash table item with a key.
    293297 *
    294  * @param key           Address where the key (i.e. physical address of futex
    295  *                      counter) is stored.
    296  *
    297  * @return              True if the item matches the key. False otherwise.
     298 * @param key Address where the key (i.e. physical address of futex counter) is
     299 *    stored.
     300 *
     301 * @return True if the item matches the key. False otherwise.
    298302 */
    299303bool futex_ht_compare(unative_t *key, size_t keys, link_t *item)
     
    309313/** Callback for removal items from futex hash table.
    310314 *
    311  * @param item          Item removed from the hash table.
     315 * @param item Item removed from the hash table.
    312316 */
    313317void futex_ht_remove_callback(link_t *item)
  • kernel/generic/src/syscall/syscall.c

    r034bf0e rbc77bfa  
    6262
    6363#ifdef CONFIG_UDEBUG
     64        bool debug;
     65
    6466        /*
    6567         * Early check for undebugged tasks. We do not lock anything as this
    66          * test need not be precise in either direction.
     68         * test need not be precise in either way.
    6769         */
    68         if (THREAD->udebug.active) {
     70        debug = THREAD->udebug.active;
     71       
     72        if (debug) {
    6973                udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, 0, false);
    7074        }
     
    8387       
    8488#ifdef CONFIG_UDEBUG
    85         if (THREAD->udebug.active) {
     89        if (debug) {
    8690                udebug_syscall_event(a1, a2, a3, a4, a5, a6, id, rc, true);
    8791       
     
    107111        (syshandler_t) sys_thread_exit,
    108112        (syshandler_t) sys_thread_get_id,
    109         (syshandler_t) sys_thread_usleep,
    110113       
    111114        (syshandler_t) sys_task_get_id,
     
    114117       
    115118        /* Synchronization related syscalls. */
    116         (syshandler_t) sys_futex_sleep,
     119        (syshandler_t) sys_futex_sleep_timeout,
    117120        (syshandler_t) sys_futex_wakeup,
    118121        (syshandler_t) sys_smc_coherence,
  • kernel/generic/src/udebug/udebug_ops.c

    r034bf0e rbc77bfa  
    5050#include <udebug/udebug.h>
    5151#include <udebug/udebug_ops.h>
    52 #include <memstr.h>
    5352
    5453/**
  • uspace/lib/libc/arch/amd64/include/atomic.h

    r034bf0e rbc77bfa  
    3737#ifndef LIBC_amd64_ATOMIC_H_
    3838#define LIBC_amd64_ATOMIC_H_
    39 
    40 #define LIBC_ARCH_ATOMIC_H_
    41 
    42 #include <atomicdflt.h>
    4339
    4440static inline void atomic_inc(atomic_t *val) {
  • uspace/lib/libc/arch/arm32/include/atomic.h

    r034bf0e rbc77bfa  
    3737#define LIBC_arm32_ATOMIC_H_
    3838
    39 #include <bool.h>
    40 
    41 typedef struct atomic {
    42         volatile long count;
    43 } atomic_t;
    44 
    45 static inline void atomic_set(atomic_t *val, long i)
    46 {
    47         val->count = i;
    48 }
    49 
    50 static inline long atomic_get(atomic_t *val)
    51 {
    52         return val->count;
    53 }
    54 
    55 static inline bool cas(atomic_t *val, long ov, long nv)
    56 {
    57         /* FIXME: is not atomic */
    58         if (val->count == ov) {
    59                 val->count = nv;
    60                 return true;
    61         }
    62         return false;
    63 }
    64 
    6539/** Atomic addition.
    6640 *
     
    7549        volatile long * mem = &(val->count);
    7650
    77         /* FIXME: is not atomic, is broken */
    7851        asm volatile (
    7952        "1:\n"
  • uspace/lib/libc/arch/ia32/Makefile.inc

    r034bf0e rbc77bfa  
    3939        arch/$(UARCH)/src/setjmp.S
    4040
    41 GCC_CFLAGS += -march=pentium
    4241LFLAGS += -N
    4342
  • uspace/lib/libc/arch/ia32/include/atomic.h

    r034bf0e rbc77bfa  
    3535#ifndef LIBC_ia32_ATOMIC_H_
    3636#define LIBC_ia32_ATOMIC_H_
    37 
    38 #define LIBC_ARCH_ATOMIC_H_
    39 
    40 #include <atomicdflt.h>
    4137
    4238static inline void atomic_inc(atomic_t *val) {
  • uspace/lib/libc/arch/ia64/include/atomic.h

    r034bf0e rbc77bfa  
    3535#ifndef LIBC_ia64_ATOMIC_H_
    3636#define LIBC_ia64_ATOMIC_H_
    37 
    38 #define LIBC_ARCH_ATOMIC_H_
    39 
    40 #include <atomicdflt.h>
    4137
    4238static inline void atomic_inc(atomic_t *val)
  • uspace/lib/libc/arch/mips32/include/atomic.h

    r034bf0e rbc77bfa  
    3636#ifndef LIBC_mips32_ATOMIC_H_
    3737#define LIBC_mips32_ATOMIC_H_
    38 
    39 #define LIBC_ARCH_ATOMIC_H_
    40 
    41 #include <atomicdflt.h>
    4238
    4339#define atomic_inc(x)   ((void) atomic_add(x, 1))
  • uspace/lib/libc/arch/ppc32/include/atomic.h

    r034bf0e rbc77bfa  
    3535#ifndef LIBC_ppc32_ATOMIC_H_
    3636#define LIBC_ppc32_ATOMIC_H_
    37 
    38 #define LIBC_ARCH_ATOMIC_H_
    39 
    40 #include <atomicdflt.h>
    4137
    4238static inline void atomic_inc(atomic_t *val)
  • uspace/lib/libc/arch/sparc64/include/atomic.h

    r034bf0e rbc77bfa  
    3636#define LIBC_sparc64_ATOMIC_H_
    3737
    38 #define LIBC_ARCH_ATOMIC_H_
    39 
    40 #include <atomicdflt.h>
    4138#include <sys/types.h>
    4239
  • uspace/lib/libc/generic/futex.c

    r034bf0e rbc77bfa  
    3636#include <atomic.h>
    3737#include <libc.h>
     38#include <stdio.h>
    3839#include <sys/types.h>
     40#include <kernel/synch/synch.h>
     41
     42/*
     43 * Note about race conditions.
     44 * Because of non-atomic nature of operations performed sequentially on the
     45 * futex counter and the futex wait queue, there is a race condition:
     46 *
     47 * (wq->missed_wakeups == 1) && (futex->count = 1)
     48 *
     49 * Scenario 1 (wait queue timeout vs. futex_up()):
     50 * 1. assume wq->missed_wakeups == 0 && futex->count == -1
     51 *    (ie. thread A sleeping, thread B in the critical section)
     52 * 2. A receives timeout and gets removed from the wait queue
     53 * 3. B wants to leave the critical section and calls futex_up()
     54 * 4. B thus changes futex->count from -1 to 0
     55 * 5. B has to call SYS_FUTEX_WAKEUP syscall to wake up the sleeping thread
     56 * 6. B finds the wait queue empty and changes wq->missed_wakeups from 0 to 1
     57 * 7. A fixes futex->count (i.e. the number of waiting threads) by changing it
     58 *    from 0 to 1
     59 *
     60 * Scenario 2 (conditional down operation vs. futex_up)
     61 * 1. assume wq->missed_wakeups == 0 && futex->count == 0
     62 *    (i.e. thread A is in the critical section)
     63 * 2. thread B performs futex_trydown() operation and changes futex->count from
     64 *    0 to -1
     65 *    B is now obliged to call SYS_FUTEX_SLEEP syscall
     66 * 3. A wants to leave the critical section and does futex_up()
     67 * 4. A thus changes futex->count from -1 to 0 and must call SYS_FUTEX_WAKEUP
     68 *    syscall
     69 * 5. B finds the wait queue empty and immediatelly aborts the conditional sleep
     70 * 6. No thread is queueing in the wait queue so wq->missed_wakeups changes from
     71 *    0 to 1
     72 * 6. B fixes futex->count (i.e. the number of waiting threads) by changing it
     73 *    from 0 to 1
     74 *
     75 * Both scenarios allow two threads to be in the critical section
     76 * simultaneously. One without kernel intervention and the other through
     77 * wq->missed_wakeups being 1.
     78 *
     79 * To mitigate this problem, futex_down_timeout() detects that the syscall
     80 * didn't sleep in the wait queue, fixes the futex counter and RETRIES the
     81 * whole operation again.
     82 */
    3983
    4084/** Initialize futex counter.
     
    4892}
    4993
     94int futex_down(futex_t *futex)
     95{
     96        return futex_down_timeout(futex, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
     97}
     98
     99int futex_trydown(futex_t *futex)
     100{
     101        return futex_down_timeout(futex, SYNCH_NO_TIMEOUT,
     102            SYNCH_FLAGS_NON_BLOCKING);
     103}
     104
    50105/** Try to down the futex.
    51106 *
    52107 * @param futex         Futex.
    53  * @return              Non-zero if the futex was acquired.
    54  * @return              Zero if the futex was not acquired.
     108 * @param usec          Microseconds to wait. Zero value means sleep without
     109 *                      timeout.
     110 * @param flags         Select mode of operation. See comment for
     111 *                      waitq_sleep_timeout().
     112 *
     113 * @return              ENOENT if there is no such virtual address. One of
     114 *                      ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED on success or
     115 *                      ESYNCH_TIMEOUT if the lock was not acquired because of
     116 *                      a timeout or ESYNCH_WOULD_BLOCK if the operation could
     117 *                      not be carried out atomically (if requested so).
    55118 */
    56 int futex_trydown(futex_t *futex)
     119int futex_down_timeout(futex_t *futex, uint32_t usec, int flags)
    57120{
    58         return cas(futex, 1, 0);
    59 }
     121        int rc;
     122       
     123        while (atomic_predec(futex) < 0) {
     124                rc = __SYSCALL3(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count,
     125                    (sysarg_t) usec, (sysarg_t) flags);
     126               
     127                switch (rc) {
     128                case ESYNCH_OK_ATOMIC:
     129                        /*
     130                         * Because of a race condition between timeout and
     131                         * futex_up() and between conditional
     132                         * futex_down_timeout() and futex_up(), we have to give
     133                         * up and try again in this special case.
     134                         */
     135                        atomic_inc(futex);
     136                        break;
    60137
    61 /** Down the futex.
    62  *
    63  * @param futex         Futex.
    64  * @return              ENOENT if there is no such virtual address.
    65  * @return              Zero in the uncontended case.
    66  * @return              Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED.
    67  */
    68 int futex_down(futex_t *futex)
    69 {
    70         if (atomic_predec(futex) < 0)
    71                 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count);
     138                case ESYNCH_TIMEOUT:
     139                        atomic_inc(futex);
     140                        return ESYNCH_TIMEOUT;
     141                        break;
    72142
    73         return 0;
     143                case ESYNCH_WOULD_BLOCK:
     144                        /*
     145                         * The conditional down operation should be implemented
     146                         * this way. The userspace-only variant tends to
     147                         * accumulate missed wakeups in the kernel futex wait
     148                         * queue.
     149                         */
     150                        atomic_inc(futex);
     151                        return ESYNCH_WOULD_BLOCK;
     152                        break;
     153
     154                case ESYNCH_OK_BLOCKED:
     155                        /*
     156                         * Enter the critical section.
     157                         * The futex counter has already been incremented for
     158                         * us.
     159                         */
     160                        return ESYNCH_OK_BLOCKED;
     161                        break;
     162                default:
     163                        return rc;
     164                }
     165        }
     166
     167        /*
     168         * Enter the critical section.
     169         */
     170        return ESYNCH_OK_ATOMIC;
    74171}
    75172
     
    77174 *
    78175 * @param futex         Futex.
    79  * @return              ENOENT if there is no such virtual address.
    80  * @return              Zero in the uncontended case.
     176 *
     177 * @return              ENOENT if there is no such virtual address. Otherwise
     178 *                      zero.
    81179 */
    82180int futex_up(futex_t *futex)
    83181{
    84         if (atomic_postinc(futex) < 0)
     182        long val;
     183       
     184        val = atomic_postinc(futex);
     185        if (val < 0)
    85186                return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count);
    86187               
  • uspace/lib/libc/generic/io/io.c

    r034bf0e rbc77bfa  
    341341size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
    342342{
    343         size_t left, done;
    344 
    345         if (size == 0 || nmemb == 0)
    346                 return 0;
    347 
     343        size_t left = size * nmemb;
     344        size_t done = 0;
     345       
    348346        /* Make sure no data is pending write. */
    349347        _fflushbuf(stream);
    350 
    351         left = size * nmemb;
    352         done = 0;
    353348       
    354349        while ((left > 0) && (!stream->error) && (!stream->eof)) {
     
    370365static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
    371366{
    372         size_t left;
    373         size_t done;
    374 
    375         if (size == 0 || nmemb == 0)
    376                 return 0;
    377 
    378         left = size * nmemb;
    379         done = 0;
    380 
     367        size_t left = size * nmemb;
     368        size_t done = 0;
     369       
    381370        while ((left > 0) && (!stream->error)) {
    382371                ssize_t wr;
     
    432421        uint8_t b;
    433422        bool need_flush;
    434 
    435         if (size == 0 || nmemb == 0)
    436                 return 0;
    437 
     423       
    438424        /* If not buffered stream, write out directly. */
    439425        if (stream->btype == _IONBF) {
  • uspace/lib/libc/generic/time.c

    r034bf0e rbc77bfa  
    3131 */
    3232/** @file
    33  */
     33 */ 
    3434
    3535#include <sys/time.h>
     
    4040#include <unistd.h>
    4141#include <atomic.h>
     42#include <futex.h>
    4243#include <sysinfo.h>
    4344#include <ipc/services.h>
    44 #include <libc.h>
    4545
    4646#include <sysinfo.h>
     
    189189
    190190/** Wait unconditionally for specified number of microseconds */
    191 int usleep(useconds_t usec)
    192 {
    193         (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
     191int usleep(unsigned long usec)
     192{
     193        atomic_t futex = FUTEX_INITIALIZER;
     194
     195        futex_initialize(&futex, 0);
     196        futex_down_timeout(&futex, usec, 0);
    194197        return 0;
    195198}
    196199
    197200/** Wait unconditionally for specified number of seconds */
    198 unsigned int sleep(unsigned int sec)
    199 {
     201unsigned int sleep(unsigned int seconds)
     202{
     203        atomic_t futex = FUTEX_INITIALIZER;
     204
     205        futex_initialize(&futex, 0);
     206       
    200207        /* Sleep in 1000 second steps to support
    201208           full argument range */
    202         while (sec > 0) {
    203                 unsigned int period = (sec > 1000) ? 1000 : sec;
     209        while (seconds > 0) {
     210                unsigned int period = (seconds > 1000) ? 1000 : seconds;
    204211       
    205                 usleep(period * 1000000);
    206                 sec -= period;
     212                futex_down_timeout(&futex, period * 1000000, 0);
     213                seconds -= period;
    207214        }
    208215        return 0;
  • uspace/lib/libc/include/atomic.h

    r034bf0e rbc77bfa  
    11/*
    2  * Copyright (c) 2009 Jakub Jermar
     2 * Copyright (c) 2006 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3636#define LIBC_ATOMIC_H_
    3737
     38typedef struct atomic {
     39        volatile long count;
     40} atomic_t;
     41
    3842#include <libarch/atomic.h>
     43
     44static inline void atomic_set(atomic_t *val, long i)
     45{
     46        val->count = i;
     47}
     48
     49static inline long atomic_get(atomic_t *val)
     50{
     51        return val->count;
     52}
    3953
    4054#endif
  • uspace/lib/libc/include/futex.h

    r034bf0e rbc77bfa  
    4646extern int futex_down(futex_t *futex);
    4747extern int futex_trydown(futex_t *futex);
     48extern int futex_down_timeout(futex_t *futex, uint32_t usec, int flags);
    4849extern int futex_up(futex_t *futex);
    4950
  • uspace/lib/libc/include/unistd.h

    r034bf0e rbc77bfa  
    5151#endif
    5252
    53 typedef uint32_t useconds_t;
    54 
    5553extern int dup2(int oldfd, int newfd);
    5654
     
    7068
    7169extern void _exit(int status) __attribute__ ((noreturn));
    72 extern int usleep(useconds_t uses);
    73 extern unsigned int sleep(unsigned int se);
     70extern int usleep(unsigned long usec);
     71extern unsigned int sleep(unsigned int seconds);
    7472
    7573#endif
Note: See TracChangeset for help on using the changeset viewer.