Changeset fbcfc4da in mainline for uspace/lib


Ignore:
Timestamp:
2009-12-03T19:25:17Z (16 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9510be2
Parents:
cb3d641a (diff), 22e6802 (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 mainline changes.

Location:
uspace/lib/libc
Files:
1 added
21 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/arch/amd64/include/atomic.h

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

    rcb3d641a rfbcfc4da  
    3737#define LIBC_arm32_ATOMIC_H_
    3838
     39#include <bool.h>
     40
     41typedef struct atomic {
     42        volatile long count;
     43} atomic_t;
     44
     45static inline void atomic_set(atomic_t *val, long i)
     46{
     47        val->count = i;
     48}
     49
     50static inline long atomic_get(atomic_t *val)
     51{
     52        return val->count;
     53}
     54
     55static 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
    3965/** Atomic addition.
    4066 *
     
    4975        volatile long * mem = &(val->count);
    5076
     77        /* FIXME: is not atomic, is broken */
    5178        asm volatile (
    5279        "1:\n"
  • uspace/lib/libc/arch/ia32/Makefile.inc

    rcb3d641a rfbcfc4da  
    3939        arch/$(UARCH)/src/setjmp.S
    4040
     41GCC_CFLAGS += -march=pentium
    4142LFLAGS += -N
    4243
  • uspace/lib/libc/arch/ia32/include/atomic.h

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

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

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

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

    rcb3d641a rfbcfc4da  
    3636#define LIBC_sparc64_ATOMIC_H_
    3737
     38#define LIBC_ARCH_ATOMIC_H_
     39
     40#include <atomicdflt.h>
    3841#include <sys/types.h>
    3942
  • uspace/lib/libc/generic/async.c

    rcb3d641a rfbcfc4da  
    392392        /* If nothing in queue, wait until something arrives */
    393393        while (list_empty(&conn->msg_queue)) {
     394                if (conn->close_callid) {
     395                        /*
     396                         * Handle the case when the connection was already
     397                         * closed by the client but the server did not notice
     398                         * the first IPC_M_PHONE_HUNGUP call and continues to
     399                         * call async_get_call_timeout(). Repeat
     400                         * IPC_M_PHONE_HUNGUP until the caller notices.
     401                         */
     402                        memset(call, 0, sizeof(ipc_call_t));
     403                        IPC_SET_METHOD(*call, IPC_M_PHONE_HUNGUP);
     404                        futex_up(&async_futex);
     405                        return conn->close_callid;
     406                }
     407
    394408                if (usecs)
    395409                        async_insert_timeout(&conn->wdata);
     
    528542        list_initialize(&conn->msg_queue);
    529543        conn->callid = callid;
    530         conn->close_callid = false;
     544        conn->close_callid = 0;
    531545       
    532546        if (call)
  • uspace/lib/libc/generic/futex.c

    rcb3d641a rfbcfc4da  
    3636#include <atomic.h>
    3737#include <libc.h>
    38 #include <stdio.h>
    3938#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  */
    8339
    8440/** Initialize futex counter.
     
    9248}
    9349
    94 int futex_down(futex_t *futex)
    95 {
    96         return futex_down_timeout(futex, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
    97 }
    98 
    99 int futex_trydown(futex_t *futex)
    100 {
    101         return futex_down_timeout(futex, SYNCH_NO_TIMEOUT,
    102             SYNCH_FLAGS_NON_BLOCKING);
    103 }
    104 
    10550/** Try to down the futex.
    10651 *
    10752 * @param futex         Futex.
    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().
     53 * @return              Non-zero if the futex was acquired.
     54 * @return              Zero if the futex was not acquired.
     55 */
     56int futex_trydown(futex_t *futex)
     57{
     58        return cas(futex, 1, 0);
     59}
     60
     61/** Down the futex.
    11262 *
    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).
     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.
    11867 */
    119 int futex_down_timeout(futex_t *futex, uint32_t usec, int flags)
     68int futex_down(futex_t *futex)
    12069{
    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;
     70        if (atomic_predec(futex) < 0)
     71                return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count);
    13772
    138                 case ESYNCH_TIMEOUT:
    139                         atomic_inc(futex);
    140                         return ESYNCH_TIMEOUT;
    141                         break;
    142 
    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;
     73        return 0;
    17174}
    17275
     
    17477 *
    17578 * @param futex         Futex.
    176  *
    177  * @return              ENOENT if there is no such virtual address. Otherwise
    178  *                      zero.
     79 * @return              ENOENT if there is no such virtual address.
     80 * @return              Zero in the uncontended case.
    17981 */
    18082int futex_up(futex_t *futex)
    18183{
    182         long val;
    183        
    184         val = atomic_postinc(futex);
    185         if (val < 0)
     84        if (atomic_postinc(futex) < 0)
    18685                return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count);
    18786               
  • uspace/lib/libc/generic/io/console.c

    rcb3d641a rfbcfc4da  
    9494}
    9595
     96int console_get_pos(int phone, int *col, int *row)
     97{
     98        ipcarg_t col_v;
     99        ipcarg_t row_v;
     100        int rc;
     101
     102        rc = async_req_0_2(phone, CONSOLE_GET_POS, &col_v, &row_v);
     103
     104        *col = (int) col_v;
     105        *row = (int) row_v;
     106        return rc;
     107}
     108
    96109void console_goto(int phone, int col, int row)
    97110{
  • uspace/lib/libc/generic/io/klog.c

    rcb3d641a rfbcfc4da  
    4242size_t klog_write(const void *buf, size_t size)
    4343{
    44         return (size_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
     44        ssize_t ret = (ssize_t) __SYSCALL3(SYS_KLOG, 1, (sysarg_t) buf, size);
     45       
     46        if (ret >= 0)
     47                return (size_t) ret;
     48       
     49        return 0;
    4550}
    4651
  • uspace/lib/libc/generic/string.c

    rcb3d641a rfbcfc4da  
    471471 * null-terminated and containing only complete characters.
    472472 *
    473  * @param dst   Destination buffer.
     473 * @param dest   Destination buffer.
    474474 * @param count Size of the destination buffer (must be > 0).
    475475 * @param src   Source string.
     
    505505 * have to be null-terminated.
    506506 *
    507  * @param dst   Destination buffer.
     507 * @param dest   Destination buffer.
    508508 * @param count Size of the destination buffer (must be > 0).
    509509 * @param src   Source string.
     
    537537 * null-terminated and containing only complete characters.
    538538 *
    539  * @param dst   Destination buffer.
     539 * @param dest   Destination buffer.
    540540 * @param count Size of the destination buffer.
    541541 * @param src   Source string.
     
    549549}
    550550
    551 /** Copy NULL-terminated wide string to string
    552  *
    553  * Copy source wide string @a src to destination buffer @a dst.
    554  * No more than @a size bytes are written. NULL-terminator is always
    555  * written after the last succesfully copied character (i.e. if the
    556  * destination buffer is has at least 1 byte, it will be always
    557  * NULL-terminated).
    558  *
    559  * @param src   Source wide string.
    560  * @param dst   Destination buffer.
    561  * @param count Size of the destination buffer.
    562  *
    563  */
    564 void wstr_nstr(char *dst, const wchar_t *src, size_t size)
    565 {
    566         /* No space for the NULL-terminator in the buffer */
    567         if (size == 0)
    568                 return;
    569        
     551/** Convert wide string to string.
     552 *
     553 * Convert wide string @a src to string. The output is written to the buffer
     554 * specified by @a dest and @a size. @a size must be non-zero and the string
     555 * written will always be well-formed.
     556 *
     557 * @param dest  Destination buffer.
     558 * @param size  Size of the destination buffer.
     559 * @param src   Source wide string.
     560 */
     561void wstr_to_str(char *dest, size_t size, const wchar_t *src)
     562{
    570563        wchar_t ch;
    571         size_t src_idx = 0;
    572         size_t dst_off = 0;
    573        
     564        size_t src_idx;
     565        size_t dest_off;
     566
     567        /* There must be space for a null terminator in the buffer. */
     568        assert(size > 0);
     569       
     570        src_idx = 0;
     571        dest_off = 0;
     572
    574573        while ((ch = src[src_idx++]) != 0) {
    575                 if (chr_encode(ch, dst, &dst_off, size) != EOK)
     574                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    576575                        break;
    577576        }
    578        
    579         if (dst_off >= size)
    580                 dst[size - 1] = 0;
    581         else
    582                 dst[dst_off] = 0;
     577
     578        dest[dest_off] = '\0';
     579}
     580
     581/** Convert wide string to new string.
     582 *
     583 * Convert wide string @a src to string. Space for the new string is allocated
     584 * on the heap.
     585 *
     586 * @param src   Source wide string.
     587 * @return      New string.
     588 */
     589char *wstr_to_astr(const wchar_t *src)
     590{
     591        char dbuf[STR_BOUNDS(1)];
     592        char *str;
     593        wchar_t ch;
     594
     595        size_t src_idx;
     596        size_t dest_off;
     597        size_t dest_size;
     598
     599        /* Compute size of encoded string. */
     600
     601        src_idx = 0;
     602        dest_size = 0;
     603
     604        while ((ch = src[src_idx++]) != 0) {
     605                dest_off = 0;
     606                if (chr_encode(ch, dbuf, &dest_off, STR_BOUNDS(1)) != EOK)
     607                        break;
     608                dest_size += dest_off;
     609        }
     610
     611        str = malloc(dest_size + 1);
     612        if (str == NULL)
     613                return NULL;
     614
     615        /* Encode string. */
     616
     617        src_idx = 0;
     618        dest_off = 0;
     619
     620        while ((ch = src[src_idx++]) != 0) {
     621                if (chr_encode(ch, str, &dest_off, dest_size) != EOK)
     622                        break;
     623        }
     624
     625        str[dest_size] = '\0';
     626        return str;
     627}
     628
     629
     630/** Convert string to wide string.
     631 *
     632 * Convert string @a src to wide string. The output is written to the
     633 * buffer specified by @a dest and @a dlen. @a dlen must be non-zero
     634 * and the wide string written will always be null-terminated.
     635 *
     636 * @param dest  Destination buffer.
     637 * @param dlen  Length of destination buffer (number of wchars).
     638 * @param src   Source string.
     639 */
     640void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
     641{
     642        size_t offset;
     643        size_t di;
     644        wchar_t c;
     645
     646        assert(dlen > 0);
     647
     648        offset = 0;
     649        di = 0;
     650
     651        do {
     652                if (di >= dlen - 1)
     653                        break;
     654
     655                c = str_decode(src, &offset, STR_NO_LIMIT);
     656                dest[di++] = c;
     657        } while (c != '\0');
     658
     659        dest[dlen - 1] = '\0';
    583660}
    584661
  • uspace/lib/libc/generic/time.c

    rcb3d641a rfbcfc4da  
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    3535#include <sys/time.h>
     
    4040#include <unistd.h>
    4141#include <atomic.h>
    42 #include <futex.h>
    4342#include <sysinfo.h>
    4443#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(unsigned long usec)
    192 {
    193         atomic_t futex = FUTEX_INITIALIZER;
    194 
    195         futex_initialize(&futex, 0);
    196         futex_down_timeout(&futex, usec, 0);
     191int usleep(useconds_t usec)
     192{
     193        (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
    197194        return 0;
    198195}
    199196
    200197/** Wait unconditionally for specified number of seconds */
    201 unsigned int sleep(unsigned int seconds)
    202 {
    203         atomic_t futex = FUTEX_INITIALIZER;
    204 
    205         futex_initialize(&futex, 0);
    206        
     198unsigned int sleep(unsigned int sec)
     199{
    207200        /* Sleep in 1000 second steps to support
    208201           full argument range */
    209         while (seconds > 0) {
    210                 unsigned int period = (seconds > 1000) ? 1000 : seconds;
     202        while (sec > 0) {
     203                unsigned int period = (sec > 1000) ? 1000 : sec;
    211204       
    212                 futex_down_timeout(&futex, period * 1000000, 0);
    213                 seconds -= period;
     205                usleep(period * 1000000);
     206                sec -= period;
    214207        }
    215208        return 0;
  • uspace/lib/libc/generic/vfs/canonify.c

    rcb3d641a rfbcfc4da  
    142142        t->start[-1] = '\0';
    143143}
    144 /** Eat the extra '/'..
     144/** Eat the extra '/'.
    145145 *
    146146 * @param t             The current TK_SLASH token.
     
    288288 *
    289289 * A file system path is canonical, if the following holds:
    290  * 1) the path is absolute (i.e. a/b/c is not canonical)
    291  * 2) there is no trailing slash in the path (i.e. /a/b/c is not canonical)
    292  * 3) there is no extra slash in the path (i.e. /a//b/c is not canonical)
    293  * 4) there is no '.' component in the path (i.e. /a/./b/c is not canonical)
    294  * 5) there is no '..' component in the path (i.e. /a/b/../c is not canonical)
     290 *
     291 * 1) the path is absolute
     292 *    (i.e. a/b/c is not canonical)
     293 * 2) there is no trailing slash in the path if it has components
     294 *    (i.e. /a/b/c/ is not canonical)
     295 * 3) there is no extra slash in the path
     296 *    (i.e. /a//b/c is not canonical)
     297 * 4) there is no '.' component in the path
     298 *    (i.e. /a/./b/c is not canonical)
     299 * 5) there is no '..' component in the path
     300 *    (i.e. /a/b/../c is not canonical)
    295301 *
    296302 * This function makes a potentially non-canonical file system path canonical.
  • uspace/lib/libc/include/atomic.h

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

    rcb3d641a rfbcfc4da  
    4646extern int futex_down(futex_t *futex);
    4747extern int futex_trydown(futex_t *futex);
    48 extern int futex_down_timeout(futex_t *futex, uint32_t usec, int flags);
    4948extern int futex_up(futex_t *futex);
    5049
  • uspace/lib/libc/include/io/console.h

    rcb3d641a rfbcfc4da  
    6969
    7070extern int console_get_size(int phone, int *cols, int *rows);
     71extern int console_get_pos(int phone, int *col, int *row);
    7172extern void console_goto(int phone, int col, int row);
    7273
  • uspace/lib/libc/include/ipc/console.h

    rcb3d641a rfbcfc4da  
    4343        CONSOLE_GET_COLOR_CAP,
    4444        CONSOLE_GET_EVENT,
     45        CONSOLE_GET_POS,
    4546        CONSOLE_GOTO,
    4647        CONSOLE_CLEAR,
  • uspace/lib/libc/include/string.h

    rcb3d641a rfbcfc4da  
    7373extern void str_append(char *dest, size_t size, const char *src);
    7474
    75 extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
     75extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
     76extern char *wstr_to_astr(const wchar_t *src);
     77extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
    7678
    7779extern char *str_chr(const char *str, wchar_t ch);
  • uspace/lib/libc/include/unistd.h

    rcb3d641a rfbcfc4da  
    5151#endif
    5252
     53typedef uint32_t useconds_t;
     54
    5355extern int dup2(int oldfd, int newfd);
    5456
     
    6870
    6971extern void _exit(int status) __attribute__ ((noreturn));
    70 extern int usleep(unsigned long usec);
    71 extern unsigned int sleep(unsigned int seconds);
     72extern int usleep(useconds_t uses);
     73extern unsigned int sleep(unsigned int se);
    7274
    7375#endif
Note: See TracChangeset for help on using the changeset viewer.