Changeset 04803bf in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2011-03-21T22:00:17Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
143932e3
Parents:
b50b5af2 (diff), 7308e84 (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 (needs fixes).

Location:
uspace/lib/c/generic
Files:
32 added
38 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/adt/hash_table.c

    rb50b5af2 r04803bf  
    4242#include <malloc.h>
    4343#include <assert.h>
    44 #include <stdio.h>
    45 #include <string.h>
     44#include <str.h>
    4645
    4746/** Create chained hash table.
    4847 *
    49  * @param h             Hash table structure. Will be initialized by this call.
    50  * @param m             Number of hash table buckets.
    51  * @param max_keys      Maximal number of keys needed to identify an item.
    52  * @param op            Hash table operations structure.
    53  * @return              True on success
     48 * @param h        Hash table structure. Will be initialized by this call.
     49 * @param m        Number of hash table buckets.
     50 * @param max_keys Maximal number of keys needed to identify an item.
     51 * @param op       Hash table operations structure.
     52 *
     53 * @return True on success
     54 *
    5455 */
    5556int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
    5657    hash_table_operations_t *op)
    5758{
    58         hash_count_t i;
    59 
    6059        assert(h);
    6160        assert(op && op->hash && op->compare);
     
    6362       
    6463        h->entry = malloc(m * sizeof(link_t));
    65         if (!h->entry) {
    66                 printf("cannot allocate memory for hash table\n");
     64        if (!h->entry)
    6765                return false;
    68         }
     66       
    6967        memset((void *) h->entry, 0,  m * sizeof(link_t));
    7068       
     69        hash_count_t i;
    7170        for (i = 0; i < m; i++)
    7271                list_initialize(&h->entry[i]);
     
    7574        h->max_keys = max_keys;
    7675        h->op = op;
     76       
    7777        return true;
    7878}
     
    8080/** Destroy a hash table instance.
    8181 *
    82  * @param h             Hash table to be destroyed.
     82 * @param h Hash table to be destroyed.
     83 *
    8384 */
    8485void hash_table_destroy(hash_table_t *h)
     
    8687        assert(h);
    8788        assert(h->entry);
     89       
    8890        free(h->entry);
    8991}
     
    9193/** Insert item into a hash table.
    9294 *
    93  * @param h             Hash table.
    94  * @param key           Array of all keys necessary to compute hash index.
    95  * @param item          Item to be inserted into the hash table.
     95 * @param h    Hash table.
     96 * @param key  Array of all keys necessary to compute hash index.
     97 * @param item Item to be inserted into the hash table.
    9698 */
    9799void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
    98100{
    99         hash_index_t chain;
    100 
    101101        assert(item);
    102102        assert(h && h->op && h->op->hash && h->op->compare);
    103 
    104         chain = h->op->hash(key);
     103       
     104        hash_index_t chain = h->op->hash(key);
    105105        assert(chain < h->entries);
    106106       
     
    110110/** Search hash table for an item matching keys.
    111111 *
    112  * @param h             Hash table.
    113  * @param key           Array of all keys needed to compute hash index.
    114  *
    115  * @return              Matching item on success, NULL if there is no such item.
     112 * @param h   Hash table.
     113 * @param key Array of all keys needed to compute hash index.
     114 *
     115 * @return Matching item on success, NULL if there is no such item.
     116 *
    116117 */
    117118link_t *hash_table_find(hash_table_t *h, unsigned long key[])
    118119{
     120        assert(h && h->op && h->op->hash && h->op->compare);
     121       
     122        hash_index_t chain = h->op->hash(key);
     123        assert(chain < h->entries);
     124       
    119125        link_t *cur;
    120         hash_index_t chain;
    121 
    122         assert(h && h->op && h->op->hash && h->op->compare);
    123 
    124         chain = h->op->hash(key);
    125         assert(chain < h->entries);
    126        
    127126        for (cur = h->entry[chain].next; cur != &h->entry[chain];
    128127            cur = cur->next) {
     
    142141 * For each removed item, h->remove_callback() is called.
    143142 *
    144  * @param h             Hash table.
    145  * @param key           Array of keys that will be compared against items of
    146  *                      the hash table.
    147  * @param keys          Number of keys in the 'key' array.
     143 * @param h    Hash table.
     144 * @param key  Array of keys that will be compared against items of
     145 *             the hash table.
     146 * @param keys Number of keys in the 'key' array.
     147 *
    148148 */
    149149void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
    150150{
    151         hash_index_t chain;
    152         link_t *cur;
    153 
    154151        assert(h && h->op && h->op->hash && h->op->compare &&
    155152            h->op->remove_callback);
    156153        assert(keys <= h->max_keys);
    157154       
     155        link_t *cur;
     156       
    158157        if (keys == h->max_keys) {
    159 
    160158                /*
    161159                 * All keys are known, hash_table_find() can be used to find the
    162160                 * entry.
    163161                 */
    164        
     162               
    165163                cur = hash_table_find(h, key);
    166164                if (cur) {
     
    168166                        h->op->remove_callback(cur);
    169167                }
     168               
    170169                return;
    171170        }
     
    175174         * Any partially matching entries are to be removed.
    176175         */
     176        hash_index_t chain;
    177177        for (chain = 0; chain < h->entries; chain++) {
    178178                for (cur = h->entry[chain].next; cur != &h->entry[chain];
     
    193193}
    194194
     195/** Apply fucntion to all items in hash table.
     196 *
     197 * @param h   Hash table.
     198 * @param f   Function to be applied.
     199 * @param arg Argument to be passed to the function.
     200 *
     201 */
     202void hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg)
     203{
     204        hash_index_t bucket;
     205        link_t *cur;
     206       
     207        for (bucket = 0; bucket < h->entries; bucket++) {
     208                for (cur = h->entry[bucket].next; cur != &h->entry[bucket];
     209                    cur = cur->next) {
     210                        f(cur, arg);
     211                }
     212        }
     213}
     214
    195215/** @}
    196216 */
  • uspace/lib/c/generic/as.c

    rb50b5af2 r04803bf  
    4040#include <bitops.h>
    4141#include <malloc.h>
    42 
    43 /** Last position allocated by as_get_mappable_page */
    44 static uintptr_t last_allocated = 0;
     42#include "private/libc.h"
    4543
    4644/** Create address space area.
     
    103101}
    104102
    105 /** Return pointer to some unmapped area, where fits new as_area
     103/** Return pointer to unmapped address space area
    106104 *
    107105 * @param size Requested size of the allocation.
    108106 *
    109  * @return pointer to the beginning
     107 * @return Pointer to the beginning of unmapped address space area.
    110108 *
    111109 */
    112110void *as_get_mappable_page(size_t size)
    113111{
    114         if (size == 0)
    115                 return NULL;
    116        
    117         size_t sz = 1 << (fnzb(size - 1) + 1);
    118         if (last_allocated == 0)
    119                 last_allocated = get_max_heap_addr();
    120        
    121         /*
    122          * Make sure we allocate from naturally aligned address.
    123          */
    124         uintptr_t res = ALIGN_UP(last_allocated, sz);
    125         last_allocated = res + ALIGN_UP(size, PAGE_SIZE);
    126        
    127         return ((void *) res);
     112        return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA,
     113            (sysarg_t) __entry, (sysarg_t) size);
    128114}
    129115
  • uspace/lib/c/generic/cap.c

    rb50b5af2 r04803bf  
    3131 */
    3232/**
    33  * @file        cap.c
    34  * @brief       Functions to grant/revoke capabilities to/from a task.
     33 * @file  cap.c
     34 * @brief Functions to grant/revoke capabilities to/from a task.
    3535 */
    3636
     
    3838#include <task.h>
    3939#include <libc.h>
    40 #include <kernel/syscall/sysarg64.h>
    4140
    4241/** Grant capabilities to a task.
    4342 *
    44  * @param id Destination task ID.
     43 * @param id   Destination task ID.
    4544 * @param caps Capabilities to grant.
    4645 *
    4746 * @return Zero on success or a value from @ref errno.h on failure.
     47 *
    4848 */
    4949int cap_grant(task_id_t id, unsigned int caps)
    5050{
    51         sysarg64_t arg;
     51#ifdef __32_BITS__
     52        sysarg64_t arg = (sysarg64_t) id;
     53        return __SYSCALL2(SYS_CAP_GRANT, (sysarg_t) &arg, (sysarg_t) caps);
     54#endif
    5255       
    53         arg.value = (unsigned long long) id;
    54 
    55         return __SYSCALL2(SYS_CAP_GRANT, (sysarg_t) &arg, (sysarg_t) caps);
     56#ifdef __64_BITS__
     57        return __SYSCALL2(SYS_CAP_GRANT, (sysarg_t) id, (sysarg_t) caps);
     58#endif
    5659}
    5760
    5861/** Revoke capabilities from a task.
    5962 *
    60  * @param id Destination task ID.
     63 * @param id   Destination task ID.
    6164 * @param caps Capabilities to revoke.
    6265 *
    6366 * @return Zero on success or a value from @ref errno.h on failure.
     67 *
    6468 */
    6569int cap_revoke(task_id_t id, unsigned int caps)
    6670{
    67         sysarg64_t arg;
     71#ifdef __32_BITS__
     72        sysarg64_t arg = (sysarg64_t) id;
     73        return __SYSCALL2(SYS_CAP_REVOKE, (sysarg_t) &arg, (sysarg_t) caps);
     74#endif
    6875       
    69         arg.value = (unsigned long long) id;
    70 
    71         return __SYSCALL2(SYS_CAP_REVOKE, (sysarg_t) &arg, (sysarg_t) caps);
     76#ifdef __64_BITS__
     77        return __SYSCALL2(SYS_CAP_REVOKE, (sysarg_t) id, (sysarg_t) caps);
     78#endif
    7279}
    7380
  • uspace/lib/c/generic/ddi.c

    rb50b5af2 r04803bf  
    9696}
    9797
    98 /** Interrupt control
    99  *
    100  * @param enable        1 - enable interrupts, 0 - disable interrupts
    101  */
    102 int preemption_control(int enable)
    103 {
    104         return __SYSCALL1(SYS_PREEMPT_CONTROL, (sysarg_t) enable);
    105 }
    106 
    10798/** Enable PIO for specified I/O range.
    10899 *
     
    136127}
    137128
     129/** Register IRQ notification.
     130 *
     131 * @param inr    IRQ number.
     132 * @param devno  Device number of the device generating inr.
     133 * @param method Use this method for notifying me.
     134 * @param ucode  Top-half pseudocode handler.
     135 *
     136 * @return Value returned by the kernel.
     137 *
     138 */
     139int register_irq(int inr, int devno, int method, irq_code_t *ucode)
     140{
     141        return __SYSCALL4(SYS_REGISTER_IRQ, inr, devno, method,
     142            (sysarg_t) ucode);
     143}
     144
     145/** Unregister IRQ notification.
     146 *
     147 * @param inr   IRQ number.
     148 * @param devno Device number of the device generating inr.
     149 *
     150 * @return Value returned by the kernel.
     151 *
     152 */
     153int unregister_irq(int inr, int devno)
     154{
     155        return __SYSCALL2(SYS_UNREGISTER_IRQ, inr, devno);
     156}
     157
    138158/** @}
    139159 */
  • uspace/lib/c/generic/event.c

    rb50b5af2 r04803bf  
    3535 */
    3636/** @file
    37  */ 
     37 */
    3838
    3939#include <libc.h>
    4040#include <event.h>
    4141#include <kernel/ipc/event_types.h>
    42 #include <ipc/ipc.h>
    4342
    4443/** Subscribe for event notifications.
     
    4948 * @return Value returned by the kernel.
    5049 */
    51 int event_subscribe(event_type_t e, ipcarg_t method)
     50int event_subscribe(event_type_t e, sysarg_t method)
    5251{
    5352        return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method);
  • uspace/lib/c/generic/fibril.c

    rb50b5af2 r04803bf  
    4141#include <unistd.h>
    4242#include <stdio.h>
     43#include <arch/barrier.h>
    4344#include <libarch/faddr.h>
    4445#include <futex.h>
     
    4748
    4849#ifndef FIBRIL_INITIAL_STACK_PAGES_NO
    49 #define FIBRIL_INITIAL_STACK_PAGES_NO   1
     50        #define FIBRIL_INITIAL_STACK_PAGES_NO  1
    5051#endif
    5152
    5253/**
    53  * This futex serializes access to ready_list, serialized_list and manager_list.
    54  */
     54 * This futex serializes access to ready_list,
     55 * serialized_list and manager_list.
     56 */
    5557static atomic_t fibril_futex = FUTEX_INITIALIZER;
    5658
     
    5961static LIST_INITIALIZE(manager_list);
    6062
    61 static void fibril_main(void);
    62 
    6363/** Number of threads that are executing a manager fibril. */
    6464static int threads_in_manager;
    65 /** Number of threads that are executing a manager fibril and are serialized. */
    66 static int serialized_threads;  /* Protected by async_futex */
     65
     66/**
     67 * Number of threads that are executing a manager fibril
     68 * and are serialized. Protected by async_futex.
     69 */
     70static int serialized_threads;
     71
    6772/** Fibril-local count of serialization. If > 0, we must not preempt */
    6873static fibril_local int serialization_count;
    69 
    70 /** Setup fibril information into TCB structure */
    71 fibril_t *fibril_setup(void)
    72 {
    73         fibril_t *f;
    74         tcb_t *tcb;
    75 
    76         tcb = __make_tls();
    77         if (!tcb)
    78                 return NULL;
    79 
    80         f = malloc(sizeof(fibril_t));
    81         if (!f) {
    82                 __free_tls(tcb);
    83                 return NULL;
    84         }
    85 
    86         tcb->fibril_data = f;
    87         f->tcb = tcb;
    88 
    89         f->func = NULL;
    90         f->arg = NULL;
    91         f->stack = NULL;
    92         f->clean_after_me = NULL;
    93         f->retval = 0;
    94         f->flags = 0;
    95 
    96         return f;
    97 }
    98 
    99 void fibril_teardown(fibril_t *f)
    100 {
    101         __free_tls(f->tcb);
    102         free(f);
    103 }
    10474
    10575/** Function that spans the whole life-cycle of a fibril.
     
    10878 * the fibril logic is called.  After its return, the return value is saved.
    10979 * The fibril then switches to another fibril, which cleans up after it.
    110  */
    111 void fibril_main(void)
    112 {
    113         fibril_t *f = __tcb_get()->fibril_data;
    114 
     80 *
     81 */
     82static void fibril_main(void)
     83{
     84        fibril_t *fibril = __tcb_get()->fibril_data;
     85       
    11586        /* Call the implementing function. */
    116         f->retval = f->func(f->arg);
    117 
     87        fibril->retval = fibril->func(fibril->arg);
     88       
    11889        fibril_switch(FIBRIL_FROM_DEAD);
    119         /* not reached */
     90        /* Not reached */
     91}
     92
     93/** Setup fibril information into TCB structure
     94 *
     95 */
     96fibril_t *fibril_setup(void)
     97{
     98        tcb_t *tcb = __make_tls();
     99        if (!tcb)
     100                return NULL;
     101       
     102        fibril_t *fibril = malloc(sizeof(fibril_t));
     103        if (!fibril) {
     104                __free_tls(tcb);
     105                return NULL;
     106        }
     107       
     108        tcb->fibril_data = fibril;
     109        fibril->tcb = tcb;
     110       
     111        fibril->func = NULL;
     112        fibril->arg = NULL;
     113        fibril->stack = NULL;
     114        fibril->clean_after_me = NULL;
     115        fibril->retval = 0;
     116        fibril->flags = 0;
     117       
     118        fibril->waits_for = NULL;
     119       
     120        return fibril;
     121}
     122
     123void fibril_teardown(fibril_t *fibril)
     124{
     125        __free_tls(fibril->tcb);
     126        free(fibril);
    120127}
    121128
     
    125132 * held.
    126133 *
    127  * @param stype         Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
    128  *                      FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter
    129  *                      describes the circumstances of the switch.
    130  * @return              Return 0 if there is no ready fibril,
    131  *                      return 1 otherwise.
     134 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
     135 *              FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter
     136 *              describes the circumstances of the switch.
     137 *
     138 * @return 0 if there is no ready fibril,
     139 * @return 1 otherwise.
     140 *
    132141 */
    133142int fibril_switch(fibril_switch_type_t stype)
    134143{
    135         fibril_t *srcf, *dstf;
    136144        int retval = 0;
    137145       
    138146        futex_down(&fibril_futex);
    139 
     147       
    140148        if (stype == FIBRIL_PREEMPT && list_empty(&ready_list))
    141149                goto ret_0;
    142 
     150       
    143151        if (stype == FIBRIL_FROM_MANAGER) {
    144                 if (list_empty(&ready_list) && list_empty(&serialized_list))
     152                if ((list_empty(&ready_list)) && (list_empty(&serialized_list)))
    145153                        goto ret_0;
     154               
    146155                /*
    147156                 * Do not preempt if there is not enough threads to run the
    148157                 * ready fibrils which are not serialized.
    149158                 */
    150                 if (list_empty(&serialized_list) &&
    151                     threads_in_manager <= serialized_threads) {
     159                if ((list_empty(&serialized_list)) &&
     160                    (threads_in_manager <= serialized_threads)) {
    152161                        goto ret_0;
    153162                }
    154163        }
     164       
    155165        /* If we are going to manager and none exists, create it */
    156         if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
     166        if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
    157167                while (list_empty(&manager_list)) {
    158168                        futex_up(&fibril_futex);
     
    162172        }
    163173       
    164         srcf = __tcb_get()->fibril_data;
     174        fibril_t *srcf = __tcb_get()->fibril_data;
    165175        if (stype != FIBRIL_FROM_DEAD) {
     176               
    166177                /* Save current state */
    167178                if (!context_save(&srcf->ctx)) {
    168179                        if (serialization_count)
    169180                                srcf->flags &= ~FIBRIL_SERIALIZED;
     181                       
    170182                        if (srcf->clean_after_me) {
    171183                                /*
     
    173185                                 * restored context here.
    174186                                 */
    175                                 void *stack = srcf->clean_after_me->stack; 
     187                                void *stack = srcf->clean_after_me->stack;
    176188                                if (stack) {
    177189                                        /*
     
    188200                                srcf->clean_after_me = NULL;
    189201                        }
     202                       
    190203                        return 1;       /* futex_up already done here */
    191204                }
    192 
     205               
    193206                /* Save myself to the correct run list */
    194207                if (stype == FIBRIL_PREEMPT)
     
    197210                        list_append(&srcf->link, &manager_list);
    198211                        threads_in_manager--;
    199                 } else {       
     212                } else {
    200213                        /*
    201214                         * If stype == FIBRIL_TO_MANAGER, don't put ourselves to
     
    207220       
    208221        /* Choose a new fibril to run */
    209         if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
     222        fibril_t *dstf;
     223        if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
    210224                dstf = list_get_instance(manager_list.next, fibril_t, link);
    211225                if (serialization_count && stype == FIBRIL_TO_MANAGER) {
     
    214228                }
    215229                threads_in_manager++;
    216 
     230               
    217231                if (stype == FIBRIL_FROM_DEAD)
    218232                        dstf->clean_after_me = srcf;
     
    228242        }
    229243        list_remove(&dstf->link);
    230 
     244       
    231245        futex_up(&fibril_futex);
    232246        context_restore(&dstf->ctx);
    233247        /* not reached */
    234 
     248       
    235249ret_0:
    236250        futex_up(&fibril_futex);
     
    240254/** Create a new fibril.
    241255 *
    242  * @param func          Implementing function of the new fibril.
    243  * @param arg           Argument to pass to func.
    244  *
    245  * @return              Return 0 on failure or TLS of the new fibril.
     256 * @param func Implementing function of the new fibril.
     257 * @param arg Argument to pass to func.
     258 *
     259 * @return 0 on failure or TLS of the new fibril.
     260 *
    246261 */
    247262fid_t fibril_create(int (*func)(void *), void *arg)
    248263{
    249         fibril_t *f;
    250 
    251         f = fibril_setup();
    252         if (!f)
     264        fibril_t *fibril;
     265       
     266        fibril = fibril_setup();
     267        if (fibril == NULL)
    253268                return 0;
    254         f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO *
    255             getpagesize());
    256         if (!f->stack) {
    257                 fibril_teardown(f);
     269       
     270        fibril->stack =
     271            (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize());
     272        if (!fibril->stack) {
     273                fibril_teardown(fibril);
    258274                return 0;
    259275        }
    260276       
    261         f->func = func;
    262         f->arg = arg;
    263 
    264         context_save(&f->ctx);
    265         context_set(&f->ctx, FADDR(fibril_main), f->stack,
    266             FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f->tcb);
    267 
    268         return (fid_t) f;
     277        fibril->func = func;
     278        fibril->arg = arg;
     279
     280        context_save(&fibril->ctx);
     281        context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack,
     282            FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), fibril->tcb);
     283
     284        return (fid_t) fibril;
    269285}
    270286
    271287/** Add a fibril to the ready list.
    272288 *
    273  * @param fid           Pointer to the fibril structure of the fibril to be
    274  *                      added.
     289 * @param fid Pointer to the fibril structure of the fibril to be
     290 *            added.
     291 *
    275292 */
    276293void fibril_add_ready(fid_t fid)
    277294{
    278         fibril_t *f;
    279 
    280         f = (fibril_t *) fid;
     295        fibril_t *fibril = (fibril_t *) fid;
     296       
    281297        futex_down(&fibril_futex);
    282         if ((f->flags & FIBRIL_SERIALIZED))
    283                 list_append(&f->link, &serialized_list);
     298       
     299        if ((fibril->flags & FIBRIL_SERIALIZED))
     300                list_append(&fibril->link, &serialized_list);
    284301        else
    285                 list_append(&f->link, &ready_list);
     302                list_append(&fibril->link, &ready_list);
     303       
    286304        futex_up(&fibril_futex);
    287305}
     
    289307/** Add a fibril to the manager list.
    290308 *
    291  * @param fid           Pointer to the fibril structure of the fibril to be
    292  *                      added.
     309 * @param fid Pointer to the fibril structure of the fibril to be
     310 *            added.
     311 *
    293312 */
    294313void fibril_add_manager(fid_t fid)
    295314{
    296         fibril_t *f;
    297 
    298         f = (fibril_t *) fid;
    299 
     315        fibril_t *fibril = (fibril_t *) fid;
     316       
    300317        futex_down(&fibril_futex);
    301         list_append(&f->link, &manager_list);
     318        list_append(&fibril->link, &manager_list);
    302319        futex_up(&fibril_futex);
    303320}
     
    307324{
    308325        futex_down(&fibril_futex);
    309         if (list_empty(&manager_list)) {
    310                 futex_up(&fibril_futex);
    311                 return;
    312         }
    313         list_remove(manager_list.next);
     326       
     327        if (!list_empty(&manager_list))
     328                list_remove(manager_list.next);
     329       
    314330        futex_up(&fibril_futex);
    315331}
     
    345361}
    346362
     363int fibril_get_sercount(void)
     364{
     365        return serialization_count;
     366}
     367
    347368/** @}
    348369 */
  • uspace/lib/c/generic/getopt.c

    rb50b5af2 r04803bf  
    3838#include <getopt.h>
    3939#include <stdlib.h>
    40 #include <string.h>
     40#include <str.h>
    4141
    4242/* HelenOS Port : We're incorporating only the modern getopt_long with wrappers
  • uspace/lib/c/generic/io/asprintf.c

    rb50b5af2 r04803bf  
    3737#include <stdio.h>
    3838#include <stdlib.h>
    39 #include <string.h>
     39#include <str.h>
    4040#include <io/printf_core.h>
    4141
     
    6161int asprintf(char **strp, const char *fmt, ...)
    6262{
    63         struct printf_spec ps = {
     63        printf_spec_t ps = {
    6464                asprintf_str_write,
    6565                asprintf_wstr_write,
  • uspace/lib/c/generic/io/console.c

    rb50b5af2 r04803bf  
    4545}
    4646
    47 int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols)
     47int console_get_size(int phone, sysarg_t *cols, sysarg_t *rows)
    4848{
    49         return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols);
     49        return async_req_0_2(phone, CONSOLE_GET_SIZE, cols, rows);
    5050}
    5151
    52 void console_set_style(int phone, int style)
     52void console_set_style(int phone, uint8_t style)
    5353{
    5454        async_msg_1(phone, CONSOLE_SET_STYLE, style);
    5555}
    5656
    57 void console_set_color(int phone, int fg_color, int bg_color, int flags)
     57void console_set_color(int phone, uint8_t fg_color, uint8_t bg_color,
     58    uint8_t flags)
    5859{
    5960        async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
    6061}
    6162
    62 void console_set_rgb_color(int phone, int fg_color, int bg_color)
     63void console_set_rgb_color(int phone, uint32_t fg_color, uint32_t bg_color)
    6364{
    6465        async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
     
    6768void console_cursor_visibility(int phone, bool show)
    6869{
    69         async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false);
     70        async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, (show != false));
    7071}
    7172
    72 int console_get_color_cap(int phone, int *ccap)
     73int console_get_color_cap(int phone, sysarg_t *ccap)
    7374{
    74         ipcarg_t ccap_tmp;
    75         int rc;
    76 
    77         rc = async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, &ccap_tmp);
    78         *ccap = ccap_tmp;
    79 
    80         return rc;
     75        return async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, ccap);
    8176}
    8277
     
    8681}
    8782
    88 void console_goto(int phone, ipcarg_t row, ipcarg_t col)
     83int console_get_pos(int phone, sysarg_t *col, sysarg_t *row)
    8984{
    90         async_msg_2(phone, CONSOLE_GOTO, row, col);
     85        return async_req_0_2(phone, CONSOLE_GET_POS, col, row);
     86}
     87
     88void console_set_pos(int phone, sysarg_t col, sysarg_t row)
     89{
     90        async_msg_2(phone, CONSOLE_GOTO, col, row);
    9191}
    9292
    9393bool console_get_event(int phone, console_event_t *event)
    9494{
    95         ipcarg_t type;
    96         ipcarg_t key;
    97         ipcarg_t mods;
    98         ipcarg_t c;
     95        sysarg_t type;
     96        sysarg_t key;
     97        sysarg_t mods;
     98        sysarg_t c;
    9999       
    100100        int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
  • uspace/lib/c/generic/io/io.c

    rb50b5af2 r04803bf  
    3737#include <fcntl.h>
    3838#include <assert.h>
    39 #include <string.h>
     39#include <str.h>
    4040#include <errno.h>
    4141#include <bool.h>
    4242#include <malloc.h>
     43#include <async.h>
    4344#include <io/klog.h>
    4445#include <vfs/vfs.h>
    4546#include <ipc/devmap.h>
    4647#include <adt/list.h>
    47 
     48#include "../private/io.h"
     49
     50static void _ffillbuf(FILE *stream);
    4851static void _fflushbuf(FILE *stream);
    4952
     
    5760        .buf = NULL,
    5861        .buf_size = 0,
    59         .buf_head = NULL
     62        .buf_head = NULL,
     63        .buf_tail = NULL,
     64        .buf_state = _bs_empty
    6065};
    6166
     
    6974        .buf = NULL,
    7075        .buf_size = BUFSIZ,
    71         .buf_head = NULL
     76        .buf_head = NULL,
     77        .buf_tail = NULL,
     78        .buf_state = _bs_empty
    7279};
    7380
     
    8188        .buf = NULL,
    8289        .buf_size = 0,
    83         .buf_head = NULL
     90        .buf_head = NULL,
     91        .buf_tail = NULL,
     92        .buf_state = _bs_empty
    8493};
    8594
     
    179188        stream->buf_size = size;
    180189        stream->buf_head = stream->buf;
     190        stream->buf_tail = stream->buf;
     191        stream->buf_state = _bs_empty;
    181192}
    182193
     
    210221       
    211222        stream->buf_head = stream->buf;
     223        stream->buf_tail = stream->buf;
    212224        return 0;
    213225}
     
    243255        stream->klog = false;
    244256        stream->phone = -1;
     257        stream->need_sync = false;
    245258        _setvbuf(stream);
    246259       
     
    264277        stream->klog = false;
    265278        stream->phone = -1;
     279        stream->need_sync = false;
    266280        _setvbuf(stream);
    267281       
     
    295309        stream->klog = false;
    296310        stream->phone = -1;
     311        stream->need_sync = false;
    297312        _setvbuf(stream);
    298313       
     
    309324       
    310325        if (stream->phone >= 0)
    311                 ipc_hangup(stream->phone);
     326                async_hangup(stream->phone);
    312327       
    313328        if (stream->fd >= 0)
     
    331346}
    332347
    333 /** Read from a stream.
     348/** Read from a stream (unbuffered).
    334349 *
    335350 * @param buf    Destination buffer.
     
    337352 * @param nmemb  Number of records to read.
    338353 * @param stream Pointer to the stream.
    339  *
    340  */
    341 size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
    342 {
    343         size_t left = size * nmemb;
    344         size_t done = 0;
    345        
    346         /* Make sure no data is pending write. */
    347         _fflushbuf(stream);
     354 */
     355static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream)
     356{
     357        size_t left, done;
     358
     359        if (size == 0 || nmemb == 0)
     360                return 0;
     361
     362        left = size * nmemb;
     363        done = 0;
    348364       
    349365        while ((left > 0) && (!stream->error) && (!stream->eof)) {
     
    363379}
    364380
     381/** Write to a stream (unbuffered).
     382 *
     383 * @param buf    Source buffer.
     384 * @param size   Size of each record.
     385 * @param nmemb  Number of records to write.
     386 * @param stream Pointer to the stream.
     387 */
    365388static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
    366389{
    367         size_t left = size * nmemb;
    368         size_t done = 0;
    369        
     390        size_t left;
     391        size_t done;
     392
     393        if (size == 0 || nmemb == 0)
     394                return 0;
     395
     396        left = size * nmemb;
     397        done = 0;
     398
    370399        while ((left > 0) && (!stream->error)) {
    371400                ssize_t wr;
     
    383412                }
    384413        }
     414
     415        if (done > 0)
     416                stream->need_sync = true;
    385417       
    386418        return (done / size);
    387419}
    388420
    389 /** Drain stream buffer, do not sync stream. */
     421/** Read some data in stream buffer. */
     422static void _ffillbuf(FILE *stream)
     423{
     424        ssize_t rc;
     425
     426        stream->buf_head = stream->buf_tail = stream->buf;
     427
     428        rc = read(stream->fd, stream->buf, stream->buf_size);
     429        if (rc < 0) {
     430                stream->error = true;
     431                return;
     432        }
     433
     434        if (rc == 0) {
     435                stream->eof = true;
     436                return;
     437        }
     438
     439        stream->buf_head += rc;
     440        stream->buf_state = _bs_read;
     441}
     442
     443/** Write out stream buffer, do not sync stream. */
    390444static void _fflushbuf(FILE *stream)
    391445{
    392446        size_t bytes_used;
    393        
     447
    394448        if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error))
    395449                return;
    396        
    397         bytes_used = stream->buf_head - stream->buf;
     450
     451        bytes_used = stream->buf_head - stream->buf_tail;
    398452        if (bytes_used == 0)
    399453                return;
    400        
    401         (void) _fwrite(stream->buf, 1, bytes_used, stream);
     454
     455        /* If buffer has prefetched read data, we need to seek back. */
     456        if (stream->buf_state == _bs_read)
     457                lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR);
     458
     459        /* If buffer has unwritten data, we need to write them out. */
     460        if (stream->buf_state == _bs_write)
     461                (void) _fwrite(stream->buf_tail, 1, bytes_used, stream);
     462
    402463        stream->buf_head = stream->buf;
    403 }
     464        stream->buf_tail = stream->buf;
     465        stream->buf_state = _bs_empty;
     466}
     467
     468/** Read from a stream.
     469 *
     470 * @param dest   Destination buffer.
     471 * @param size   Size of each record.
     472 * @param nmemb  Number of records to read.
     473 * @param stream Pointer to the stream.
     474 *
     475 */
     476size_t fread(void *dest, size_t size, size_t nmemb, FILE *stream)
     477{
     478        uint8_t *dp;
     479        size_t bytes_left;
     480        size_t now;
     481        size_t data_avail;
     482        size_t total_read;
     483        size_t i;
     484
     485        if (size == 0 || nmemb == 0)
     486                return 0;
     487
     488        /* If not buffered stream, read in directly. */
     489        if (stream->btype == _IONBF) {
     490                now = _fread(dest, size, nmemb, stream);
     491                return now;
     492        }
     493
     494        /* Make sure no data is pending write. */
     495        if (stream->buf_state == _bs_write)
     496                _fflushbuf(stream);
     497
     498        /* Perform lazy allocation of stream buffer. */
     499        if (stream->buf == NULL) {
     500                if (_fallocbuf(stream) != 0)
     501                        return 0; /* Errno set by _fallocbuf(). */
     502        }
     503
     504        bytes_left = size * nmemb;
     505        total_read = 0;
     506        dp = (uint8_t *) dest;
     507
     508        while ((!stream->error) && (!stream->eof) && (bytes_left > 0)) {
     509                if (stream->buf_head == stream->buf_tail)
     510                        _ffillbuf(stream);
     511
     512                if (stream->error || stream->eof)
     513                        break;
     514
     515                data_avail = stream->buf_head - stream->buf_tail;
     516
     517                if (bytes_left > data_avail)
     518                        now = data_avail;
     519                else
     520                        now = bytes_left;
     521
     522                for (i = 0; i < now; i++) {
     523                        dp[i] = stream->buf_tail[i];
     524                }
     525
     526                dp += now;
     527                stream->buf_tail += now;
     528                bytes_left -= now;
     529                total_read += now;
     530        }
     531
     532        return (total_read / size);
     533}
     534
    404535
    405536/** Write to a stream.
     
    421552        uint8_t b;
    422553        bool need_flush;
    423        
     554
     555        if (size == 0 || nmemb == 0)
     556                return 0;
     557
    424558        /* If not buffered stream, write out directly. */
    425559        if (stream->btype == _IONBF) {
     
    428562                return now;
    429563        }
    430        
     564
     565        /* Make sure buffer contains no prefetched data. */
     566        if (stream->buf_state == _bs_read)
     567                _fflushbuf(stream);
     568
     569
    431570        /* Perform lazy allocation of stream buffer. */
    432571        if (stream->buf == NULL) {
     
    468607        }
    469608       
     609        if (total_written > 0)
     610                stream->buf_state = _bs_write;
     611
    470612        if (need_flush)
    471613                fflush(stream);
     
    480622       
    481623        if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) {
    482                 size_t wr = fwrite(buf, sz, 1, stream);
     624                size_t wr = fwrite(buf, 1, sz, stream);
    483625               
    484626                if (wr < sz)
     
    522664}
    523665
     666char *fgets(char *str, int size, FILE *stream)
     667{
     668        int c;
     669        int idx;
     670
     671        idx = 0;
     672        while (idx < size - 1) {
     673                c = fgetc(stream);
     674                if (c == EOF)
     675                        break;
     676
     677                str[idx++] = c;
     678
     679                if (c == '\n')
     680                        break;
     681        }
     682
     683        if (ferror(stream))
     684                return NULL;
     685
     686        if (idx == 0)
     687                return NULL;
     688
     689        str[idx] = '\0';
     690        return str;
     691}
     692
    524693int getchar(void)
    525694{
     
    527696}
    528697
    529 int fseek(FILE *stream, long offset, int origin)
    530 {
    531         off_t rc = lseek(stream->fd, offset, origin);
    532         if (rc == (off_t) (-1)) {
    533                 /* errno has been set by lseek. */
     698int fseek(FILE *stream, off64_t offset, int whence)
     699{
     700        off64_t rc;
     701
     702        _fflushbuf(stream);
     703
     704        rc = lseek(stream->fd, offset, whence);
     705        if (rc == (off64_t) (-1)) {
     706                /* errno has been set by lseek64. */
    534707                return -1;
    535708        }
    536        
     709
    537710        stream->eof = false;
    538        
    539711        return 0;
     712}
     713
     714off64_t ftell(FILE *stream)
     715{
     716        return lseek(stream->fd, 0, SEEK_CUR);
    540717}
    541718
     
    554731        }
    555732       
    556         if (stream->fd >= 0)
     733        if (stream->fd >= 0 && stream->need_sync) {
     734                /**
     735                 * Better than syncing always, but probably still not the
     736                 * right thing to do.
     737                 */
     738                stream->need_sync = false;
    557739                return fsync(stream->fd);
     740        }
    558741       
    559742        return ENOENT;
     
    568751{
    569752        return stream->error;
     753}
     754
     755void clearerr(FILE *stream)
     756{
     757        stream->eof = false;
     758        stream->error = false;
     759}
     760
     761int fileno(FILE *stream)
     762{
     763        if (stream->klog) {
     764                errno = EBADF;
     765                return -1;
     766        }
     767       
     768        return stream->fd;
    570769}
    571770
  • uspace/lib/c/generic/io/klog.c

    rb50b5af2 r04803bf  
    3535
    3636#include <libc.h>
    37 #include <string.h>
     37#include <str.h>
    3838#include <sys/types.h>
    3939#include <unistd.h>
     
    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
    4752void klog_update(void)
    4853{
    49         (void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
     54        (void) __SYSCALL3(SYS_KLOG, 1, (uintptr_t) NULL, 0);
    5055}
    5156
  • uspace/lib/c/generic/io/printf_core.c

    rb50b5af2 r04803bf  
    4141#include <io/printf_core.h>
    4242#include <ctype.h>
    43 #include <string.h>
     43#include <str.h>
    4444
    4545/** show prefixes 0x or 0 */
    4646#define __PRINTF_FLAG_PREFIX       0x00000001
     47
    4748/** signed / unsigned number */
    4849#define __PRINTF_FLAG_SIGNED       0x00000002
     50
    4951/** print leading zeroes */
    5052#define __PRINTF_FLAG_ZEROPADDED   0x00000004
     53
    5154/** align to left */
    5255#define __PRINTF_FLAG_LEFTALIGNED  0x00000010
     56
    5357/** always show + sign */
    5458#define __PRINTF_FLAG_SHOWPLUS     0x00000020
     59
    5560/** print space instead of plus */
    5661#define __PRINTF_FLAG_SPACESIGN    0x00000040
     62
    5763/** show big characters */
    5864#define __PRINTF_FLAG_BIGCHARS     0x00000080
     65
    5966/** number has - sign */
    6067#define __PRINTF_FLAG_NEGATIVE     0x00000100
     
    7582        PrintfQualifierLong,
    7683        PrintfQualifierLongLong,
    77         PrintfQualifierPointer
     84        PrintfQualifierPointer,
     85        PrintfQualifierSize
    7886} qualifier_t;
    7987
    80 static char nullstr[] = "(NULL)";
    81 static char digits_small[] = "0123456789abcdef";
    82 static char digits_big[] = "0123456789ABCDEF";
    83 static char invalch = U_SPECIAL;
     88static const char *nullstr = "(NULL)";
     89static const char *digits_small = "0123456789abcdef";
     90static const char *digits_big = "0123456789ABCDEF";
     91static const char invalch = U_SPECIAL;
    8492
    8593/** Print one or more characters without adding newline.
     
    253261        if (str == NULL)
    254262                return printf_putstr(nullstr, ps);
    255 
     263       
    256264        /* Print leading spaces. */
    257265        size_t strw = str_length(str);
    258266        if (precision == 0)
    259267                precision = strw;
    260 
     268       
    261269        /* Left padding */
    262270        size_t counter = 0;
     
    268276                }
    269277        }
    270 
     278       
    271279        /* Part of @a str fitting into the alloted space. */
    272280        int retval;
     
    350358    uint32_t flags, printf_spec_t *ps)
    351359{
    352         char *digits;
     360        const char *digits;
    353361        if (flags & __PRINTF_FLAG_BIGCHARS)
    354362                digits = digits_big;
     
    383391         */
    384392        if (flags & __PRINTF_FLAG_PREFIX) {
    385                 switch(base) {
     393                switch (base) {
    386394                case 2:
    387395                        /* Binary formating is not standard, but usefull */
     
    447455        /* Print prefix */
    448456        if (flags & __PRINTF_FLAG_PREFIX) {
    449                 switch(base) {
     457                switch (base) {
    450458                case 2:
    451459                        /* Binary formating is not standard, but usefull */
     
    545553 *  - ""   Signed or unsigned int (default value).@n
    546554 *  - "l"  Signed or unsigned long int.@n
    547  *         If conversion is "c", the character is wchar_t (wide character).@n
     555 *         If conversion is "c", the character is wint_t (wide character).@n
    548556 *         If conversion is "s", the string is wchar_t * (wide string).@n
    549557 *  - "ll" Signed or unsigned long long int.@n
     558 *  - "z"  Signed or unsigned ssize_t or site_t.@n
    550559 *
    551560 * CONVERSION:@n
     
    562571 *
    563572 *  - P, p Print value of a pointer. Void * value is expected and it is
    564  *         printed in hexadecimal notation with prefix (as with \%#X / \%#x
    565  *         for 32-bit or \%#X / \%#x for 64-bit long pointers).
     573 *         printed in hexadecimal notation with prefix (as with
     574 *         \%#0.8X / \%#0.8x for 32-bit or \%#0.16lX / \%#0.16lx for 64-bit
     575 *         long pointers).
    566576 *
    567577 *  - b Print value as unsigned binary number. Prefix is not printed by
     
    728738                                }
    729739                                break;
     740                        case 'z':
     741                                qualifier = PrintfQualifierSize;
     742                                i = nxt;
     743                                uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
     744                                break;
    730745                        default:
    731746                                /* Default type */
     
    755770                        case 'c':
    756771                                if (qualifier == PrintfQualifierLong)
    757                                         retval = print_wchar(va_arg(ap, wchar_t), width, flags, ps);
     772                                        retval = print_wchar(va_arg(ap, wint_t), width, flags, ps);
    758773                                else
    759774                                        retval = print_char(va_arg(ap, unsigned int), width, flags, ps);
     
    776791                        case 'p':
    777792                                flags |= __PRINTF_FLAG_PREFIX;
     793                                flags |= __PRINTF_FLAG_ZEROPADDED;
    778794                                base = 16;
    779795                                qualifier = PrintfQualifierPointer;
     
    838854                        case PrintfQualifierPointer:
    839855                                size = sizeof(void *);
    840                                 number = (uint64_t) (unsigned long) va_arg(ap, void *);
     856                                precision = size << 1;
     857                                number = (uint64_t) (uintptr_t) va_arg(ap, void *);
     858                                break;
     859                        case PrintfQualifierSize:
     860                                size = sizeof(size_t);
     861                                number = (uint64_t) va_arg(ap, size_t);
    841862                                break;
    842863                        default:
  • uspace/lib/c/generic/io/screenbuffer.c

    rb50b5af2 r04803bf  
    3333 */
    3434
    35 #include <screenbuffer.h>
    3635#include <io/style.h>
     36#include <io/screenbuffer.h>
    3737#include <malloc.h>
    3838#include <unistd.h>
     
    6767 *
    6868 */
    69 screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y)
     69screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, sysarg_t size_x,
     70    sysarg_t size_y)
    7071{
    7172        scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y);
     
    109110 *
    110111 */
    111 void screenbuffer_clear_line(screenbuffer_t *scr, size_t line)
     112void screenbuffer_clear_line(screenbuffer_t *scr, sysarg_t line)
    112113{
    113         size_t x;
     114        sysarg_t x;
    114115       
    115116        for (x = 0; x < scr->size_x; x++) {
     
    140141 *
    141142 */
    142 void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y)
     143void screenbuffer_goto(screenbuffer_t *scr, sysarg_t x, sysarg_t y)
    143144{
    144145        scr->position_x = x % scr->size_x;
     
    166167 *
    167168 */
    168 void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags)
     169void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color,
     170    uint8_t bg_color, uint8_t flags)
    169171{
    170172        scr->attrs.t = at_idx;
     
    181183 *
    182184 */
    183 void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color)
     185void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color,
     186    uint32_t bg_color)
    184187{
    185188        scr->attrs.t = at_rgb;
  • uspace/lib/c/generic/io/vprintf.c

    rb50b5af2 r04803bf  
    3737#include <unistd.h>
    3838#include <io/printf_core.h>
    39 #include <futex.h>
     39#include <fibril_synch.h>
    4040#include <async.h>
    41 #include <string.h>
     41#include <str.h>
    4242
    43 static atomic_t printf_futex = FUTEX_INITIALIZER;
     43static FIBRIL_MUTEX_INITIALIZE(printf_mutex);
    4444
    4545static int vprintf_str_write(const char *str, size_t size, void *stream)
     
    7676int vfprintf(FILE *stream, const char *fmt, va_list ap)
    7777{
    78         struct printf_spec ps = {
     78        printf_spec_t ps = {
    7979                vprintf_str_write,
    8080                vprintf_wstr_write,
     
    8585         * Prevent other threads to execute printf_core()
    8686         */
    87         futex_down(&printf_futex);
    88        
    89         /*
    90          * Prevent other fibrils of the same thread
    91          * to execute printf_core()
    92          */
    93         async_serialize_start();
     87        fibril_mutex_lock(&printf_mutex);
    9488       
    9589        int ret = printf_core(fmt, &ps, ap);
    9690       
    97         async_serialize_end();
    98         futex_up(&printf_futex);
     91        fibril_mutex_unlock(&printf_mutex);
    9992       
    10093        return ret;
  • uspace/lib/c/generic/io/vsnprintf.c

    rb50b5af2 r04803bf  
    3535#include <stdarg.h>
    3636#include <stdio.h>
    37 #include <string.h>
     37#include <str.h>
    3838#include <io/printf_core.h>
    3939#include <errno.h>
  • uspace/lib/c/generic/libc.c

    rb50b5af2 r04803bf  
    4242
    4343#include <libc.h>
    44 #include <stdio.h>
    45 #include <unistd.h>
    46 #include <malloc.h>
     44#include <stdlib.h>
    4745#include <tls.h>
    48 #include <thread.h>
    4946#include <fibril.h>
    50 #include <ipc/ipc.h>
    51 #include <async.h>
    52 #include <as.h>
     47#include <task.h>
    5348#include <loader/pcb.h>
     49#include "private/libc.h"
     50#include "private/async.h"
     51#include "private/async_sess.h"
     52#include "private/malloc.h"
     53#include "private/io.h"
    5454
    5555/* From librtld. */
    5656#include <rtld.h>
    57 #include <string.h>
     57//#include <string.h>
    5858
    59 extern int main(int argc, char *argv[]);
    60 
    61 void _exit(int status)
    62 {
    63         thread_exit(status);
    64 }
     59static bool env_setup = false;
    6560
    6661void __main(void *pcb_ptr)
    6762{
    68         int retval;
    69 
    70         __heap_init();
     63        /* Initialize user task run-time environment */
     64        __malloc_init();
    7165        __async_init();
     66        __async_sess_init();
     67       
    7268        fibril_t *fibril = fibril_setup();
     69        if (fibril == NULL)
     70                abort();
     71       
    7372        __tcb_set(fibril->tcb);
    7473       
    7574        /* Save the PCB pointer */
    7675        __pcb = (pcb_t *) pcb_ptr;
     76       
     77        /* The basic run-time environment is setup */
     78        env_setup = true;
    7779       
    7880        int argc;
     
    8486        }
    8587#endif
    86 
     88        /*
     89         * Get command line arguments and initialize
     90         * standard input and output
     91         */
    8792        if (__pcb == NULL) {
    8893                argc = 0;
     
    9398                argv = __pcb->argv;
    9499                __stdio_init(__pcb->filc, __pcb->filv);
     100                (void) chdir(__pcb->cwd);
    95101        }
    96102       
    97         retval = main(argc, argv);
    98 
    99         __stdio_done();
    100         (void) task_retval(retval);
     103        /*
     104         * Run main() and set task return value
     105         * according the result
     106         */
     107        int retval = main(argc, argv);
     108        exit(retval);
    101109}
    102110
    103 void __exit(void)
     111void exit(int status)
    104112{
    105         fibril_teardown(__tcb_get()->fibril_data);
    106         _exit(0);
     113        if (env_setup) {
     114                __stdio_done();
     115                task_retval(status);
     116                fibril_teardown(__tcb_get()->fibril_data);
     117        }
     118       
     119        __SYSCALL1(SYS_TASK_EXIT, false);
     120       
     121        /* Unreachable */
     122        while (1);
     123}
     124
     125void abort(void)
     126{
     127        __SYSCALL1(SYS_TASK_EXIT, true);
     128       
     129        /* Unreachable */
     130        while (1);
    107131}
    108132
  • uspace/lib/c/generic/loader.c

    rb50b5af2 r04803bf  
    3333 */
    3434
    35 #include <ipc/ipc.h>
    3635#include <ipc/loader.h>
    3736#include <ipc/services.h>
     37#include <ipc/ns.h>
    3838#include <libc.h>
    3939#include <task.h>
    40 #include <string.h>
     40#include <str.h>
    4141#include <stdlib.h>
    4242#include <async.h>
     
    6363loader_t *loader_connect(void)
    6464{
    65         int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
     65        int phone_id = service_connect_blocking(SERVICE_LOAD, 0, 0);
    6666        if (phone_id < 0)
    6767                return NULL;
     
    9090        ipc_call_t answer;
    9191        aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
    92         int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
    93         if (rc != EOK) {
    94                 async_wait_for(req, NULL);
    95                 return rc;
    96         }
    97        
    98         ipcarg_t retval;
     92        int rc = async_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
     93        if (rc != EOK) {
     94                async_wait_for(req, NULL);
     95                return rc;
     96        }
     97       
     98        sysarg_t retval;
     99        async_wait_for(req, &retval);
     100        return (int) retval;
     101}
     102
     103/** Set current working directory for the loaded task.
     104 *
     105 * Sets the current working directory for the loaded task.
     106 *
     107 * @param ldr  Loader connection structure.
     108 *
     109 * @return Zero on success or negative error code.
     110 *
     111 */
     112int loader_set_cwd(loader_t *ldr)
     113{
     114        char *cwd;
     115        size_t len;
     116
     117        cwd = (char *) malloc(MAX_PATH_LEN + 1);
     118        if (!cwd)
     119                return ENOMEM;
     120        if (!getcwd(cwd, MAX_PATH_LEN + 1))
     121                str_cpy(cwd, MAX_PATH_LEN + 1, "/");
     122        len = str_length(cwd);
     123       
     124        ipc_call_t answer;
     125        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_CWD, &answer);
     126        int rc = async_data_write_start(ldr->phone_id, cwd, len);
     127        free(cwd);
     128        if (rc != EOK) {
     129                async_wait_for(req, NULL);
     130                return rc;
     131        }
     132       
     133        sysarg_t retval;
    99134        async_wait_for(req, &retval);
    100135        return (int) retval;
     
    123158        ipc_call_t answer;
    124159        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
    125         int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len);
    126         if (rc != EOK) {
     160        int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
     161        if (rc != EOK) {
     162                free(pa);
    127163                async_wait_for(req, NULL);
    128164                return rc;
     
    131167        free(pa);
    132168       
    133         ipcarg_t retval;
     169        sysarg_t retval;
    134170        async_wait_for(req, &retval);
    135171        return (int) retval;
     
    148184 *
    149185 */
    150 int loader_set_args(loader_t *ldr, char *const argv[])
     186int loader_set_args(loader_t *ldr, const char *const argv[])
    151187{
    152188        /*
     
    154190         * compute size of the buffer needed.
    155191         */
    156         char *const *ap = argv;
     192        const char *const *ap = argv;
    157193        size_t buffer_size = 0;
    158194        while (*ap != NULL) {
     
    178214        ipc_call_t answer;
    179215        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
    180         ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
     216        sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
    181217        if (rc != EOK) {
    182218                async_wait_for(req, NULL);
     
    232268        ipc_call_t answer;
    233269        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
    234         ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf,
     270        sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) files_buf,
    235271            count * sizeof(fdi_node_t));
    236272        if (rc != EOK) {
     
    284320                return rc;
    285321       
    286         ipc_hangup(ldr->phone_id);
     322        async_hangup(ldr->phone_id);
    287323        ldr->phone_id = 0;
    288324        return EOK;
     
    302338void loader_abort(loader_t *ldr)
    303339{
    304         ipc_hangup(ldr->phone_id);
     340        async_hangup(ldr->phone_id);
    305341        ldr->phone_id = 0;
    306342}
  • uspace/lib/c/generic/mem.c

    rb50b5af2 r04803bf  
    222222/** Compare two memory areas.
    223223 *
    224  * @param s1            Pointer to the first area to compare.
    225  * @param s2            Pointer to the second area to compare.
    226  * @param len           Size of the first area in bytes. Both areas must have
    227  *                      the same length.
    228  * @return              If len is 0, return zero. If the areas match, return
    229  *                      zero. Otherwise return non-zero.
    230  */
    231 int bcmp(const char *s1, const char *s2, size_t len)
    232 {
    233         for (; len && *s1++ == *s2++; len--)
    234                 ;
     224 * @param s1  Pointer to the first area to compare.
     225 * @param s2  Pointer to the second area to compare.
     226 * @param len Size of the first area in bytes. Both areas must have
     227 *            the same length.
     228 *
     229 * @return If len is 0, return zero. If the areas match, return
     230 *         zero. Otherwise return non-zero.
     231 *
     232 */
     233int bcmp(const void *s1, const void *s2, size_t len)
     234{
     235        uint8_t *u1 = (uint8_t *) s1;
     236        uint8_t *u2 = (uint8_t *) s2;
     237       
     238        for (; (len != 0) && (*u1++ == *u2++); len--);
     239       
    235240        return len;
    236241}
  • uspace/lib/c/generic/mman.c

    rb50b5af2 r04803bf  
    3939
    4040void *mmap(void *start, size_t length, int prot, int flags, int fd,
    41     off_t offset)
     41    aoff64_t offset)
    4242{
    4343        if (!start)
  • uspace/lib/c/generic/private/async_sess.h

    rb50b5af2 r04803bf  
    11/*
    2  * Copyright (c) 2005 Martin Decky
     2 * Copyright (c) 2011 Martin Decky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup amd64debug
     29/** @addtogroup libc
    3030 * @{
    3131 */
     
    3333 */
    3434
    35 #ifndef KERN_ia32_DEBUG_H_
    36 #define KERN_ia32_DEBUG_H_
     35#ifndef LIBC_PRIVATE_ASYNC_SESS_H_
     36#define LIBC_PRIVATE_ASYNC_SESS_H_
    3737
    38 #include <arch/asm.h>
    39 
    40 #define HERE get_ip()
     38extern void __async_sess_init(void);
    4139
    4240#endif
  • uspace/lib/c/generic/private/libc.h

    rb50b5af2 r04803bf  
    11/*
    2  * Copyright (c) 2006 Jakub Jermar
     2 * Copyright (c) 2011 Martin Decky
    33 * All rights reserved.
    44 *
     
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    35 #include <libc.h>
    36 #include <sysinfo.h>
    37 #include <string.h>
     35#ifndef LIBC_PRIVATE_LIBC_H_
     36#define LIBC_PRIVATE_LIBC_H_
    3837
    39 sysarg_t sysinfo_value(char *name)
    40 {
    41         return __SYSCALL2(SYS_SYSINFO_VALUE, (sysarg_t ) name,
    42             (sysarg_t) str_size(name));
    43 }
     38extern void __entry(void);
     39extern void __main(void *) __attribute__((noreturn));
     40extern int main(int, char *[]);
     41
     42#endif
    4443
    4544/** @}
  • uspace/lib/c/generic/str.c

    rb50b5af2 r04803bf  
    3434 */
    3535
    36 #include <string.h>
     36#include <str.h>
    3737#include <stdlib.h>
    3838#include <assert.h>
    39 #include <limits.h>
     39#include <stdint.h>
    4040#include <ctype.h>
    4141#include <malloc.h>
     
    4343#include <align.h>
    4444#include <mem.h>
    45 #include <string.h>
     45#include <str.h>
    4646
    4747/** Byte mask consisting of lowest @n bits (out of 8) */
     
    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.
     
    477477void str_cpy(char *dest, size_t size, const char *src)
    478478{
    479         wchar_t ch;
    480         size_t src_off;
    481         size_t dest_off;
    482 
    483479        /* There must be space for a null terminator in the buffer. */
    484480        assert(size > 0);
    485481       
    486         src_off = 0;
    487         dest_off = 0;
    488 
     482        size_t src_off = 0;
     483        size_t dest_off = 0;
     484       
     485        wchar_t ch;
    489486        while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) {
    490487                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    491488                        break;
    492489        }
    493 
     490       
    494491        dest[dest_off] = '\0';
    495492}
     
    505502 * have to be null-terminated.
    506503 *
    507  * @param dst   Destination buffer.
     504 * @param dest  Destination buffer.
    508505 * @param count Size of the destination buffer (must be > 0).
    509506 * @param src   Source string.
    510  * @param n     Maximum number of bytes to read from @a src.
     507 * @param n     Maximum number of bytes to read from @a src.
    511508 */
    512509void str_ncpy(char *dest, size_t size, const char *src, size_t n)
    513510{
    514         wchar_t ch;
    515         size_t src_off;
    516         size_t dest_off;
    517 
    518511        /* There must be space for a null terminator in the buffer. */
    519512        assert(size > 0);
    520513       
    521         src_off = 0;
    522         dest_off = 0;
    523 
     514        size_t src_off = 0;
     515        size_t dest_off = 0;
     516       
     517        wchar_t ch;
    524518        while ((ch = str_decode(src, &src_off, n)) != 0) {
    525519                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    526520                        break;
    527521        }
    528 
     522       
    529523        dest[dest_off] = '\0';
    530524}
     
    537531 * null-terminated and containing only complete characters.
    538532 *
    539  * @param dst   Destination buffer.
     533 * @param dest   Destination buffer.
    540534 * @param count Size of the destination buffer.
    541535 * @param src   Source string.
     
    549543}
    550544
    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        
     545/** Convert wide string to string.
     546 *
     547 * Convert wide string @a src to string. The output is written to the buffer
     548 * specified by @a dest and @a size. @a size must be non-zero and the string
     549 * written will always be well-formed.
     550 *
     551 * @param dest  Destination buffer.
     552 * @param size  Size of the destination buffer.
     553 * @param src   Source wide string.
     554 */
     555void wstr_to_str(char *dest, size_t size, const wchar_t *src)
     556{
    570557        wchar_t ch;
    571         size_t src_idx = 0;
    572         size_t dst_off = 0;
    573        
     558        size_t src_idx;
     559        size_t dest_off;
     560
     561        /* There must be space for a null terminator in the buffer. */
     562        assert(size > 0);
     563       
     564        src_idx = 0;
     565        dest_off = 0;
     566
    574567        while ((ch = src[src_idx++]) != 0) {
    575                 if (chr_encode(ch, dst, &dst_off, size) != EOK)
     568                if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
    576569                        break;
    577570        }
    578        
    579         if (dst_off >= size)
    580                 dst[size - 1] = 0;
    581         else
    582                 dst[dst_off] = 0;
     571
     572        dest[dest_off] = '\0';
     573}
     574
     575/** Convert wide string to new string.
     576 *
     577 * Convert wide string @a src to string. Space for the new string is allocated
     578 * on the heap.
     579 *
     580 * @param src   Source wide string.
     581 * @return      New string.
     582 */
     583char *wstr_to_astr(const wchar_t *src)
     584{
     585        char dbuf[STR_BOUNDS(1)];
     586        char *str;
     587        wchar_t ch;
     588
     589        size_t src_idx;
     590        size_t dest_off;
     591        size_t dest_size;
     592
     593        /* Compute size of encoded string. */
     594
     595        src_idx = 0;
     596        dest_size = 0;
     597
     598        while ((ch = src[src_idx++]) != 0) {
     599                dest_off = 0;
     600                if (chr_encode(ch, dbuf, &dest_off, STR_BOUNDS(1)) != EOK)
     601                        break;
     602                dest_size += dest_off;
     603        }
     604
     605        str = malloc(dest_size + 1);
     606        if (str == NULL)
     607                return NULL;
     608
     609        /* Encode string. */
     610
     611        src_idx = 0;
     612        dest_off = 0;
     613
     614        while ((ch = src[src_idx++]) != 0) {
     615                if (chr_encode(ch, str, &dest_off, dest_size) != EOK)
     616                        break;
     617        }
     618
     619        str[dest_size] = '\0';
     620        return str;
     621}
     622
     623
     624/** Convert string to wide string.
     625 *
     626 * Convert string @a src to wide string. The output is written to the
     627 * buffer specified by @a dest and @a dlen. @a dlen must be non-zero
     628 * and the wide string written will always be null-terminated.
     629 *
     630 * @param dest  Destination buffer.
     631 * @param dlen  Length of destination buffer (number of wchars).
     632 * @param src   Source string.
     633 */
     634void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
     635{
     636        size_t offset;
     637        size_t di;
     638        wchar_t c;
     639
     640        assert(dlen > 0);
     641
     642        offset = 0;
     643        di = 0;
     644
     645        do {
     646                if (di >= dlen - 1)
     647                        break;
     648
     649                c = str_decode(src, &offset, STR_NO_LIMIT);
     650                dest[di++] = c;
     651        } while (c != '\0');
     652
     653        dest[dlen - 1] = '\0';
    583654}
    584655
     
    819890}
    820891
     892/** Duplicate string.
     893 *
     894 * Allocate a new string and copy characters from the source
     895 * string into it. The duplicate string is allocated via sleeping
     896 * malloc(), thus this function can sleep in no memory conditions.
     897 *
     898 * The allocation cannot fail and the return value is always
     899 * a valid pointer. The duplicate string is always a well-formed
     900 * null-terminated UTF-8 string, but it can differ from the source
     901 * string on the byte level.
     902 *
     903 * @param src Source string.
     904 *
     905 * @return Duplicate string.
     906 *
     907 */
     908char *str_dup(const char *src)
     909{
     910        size_t size = str_size(src) + 1;
     911        char *dest = (char *) malloc(size);
     912        if (dest == NULL)
     913                return (char *) NULL;
     914       
     915        str_cpy(dest, size, src);
     916        return dest;
     917}
     918
     919/** Duplicate string with size limit.
     920 *
     921 * Allocate a new string and copy up to @max_size bytes from the source
     922 * string into it. The duplicate string is allocated via sleeping
     923 * malloc(), thus this function can sleep in no memory conditions.
     924 * No more than @max_size + 1 bytes is allocated, but if the size
     925 * occupied by the source string is smaller than @max_size + 1,
     926 * less is allocated.
     927 *
     928 * The allocation cannot fail and the return value is always
     929 * a valid pointer. The duplicate string is always a well-formed
     930 * null-terminated UTF-8 string, but it can differ from the source
     931 * string on the byte level.
     932 *
     933 * @param src Source string.
     934 * @param n   Maximum number of bytes to duplicate.
     935 *
     936 * @return Duplicate string.
     937 *
     938 */
     939char *str_ndup(const char *src, size_t n)
     940{
     941        size_t size = str_size(src);
     942        if (size > n)
     943                size = n;
     944       
     945        char *dest = (char *) malloc(size + 1);
     946        if (dest == NULL)
     947                return (char *) NULL;
     948       
     949        str_ncpy(dest, size + 1, src, size);
     950        return dest;
     951}
     952
    821953
    822954/** Convert initial part of string to unsigned long according to given base.
     
    843975}
    844976
    845 char *str_dup(const char *src)
    846 {
    847         size_t size = str_size(src);
    848         void *dest = malloc(size + 1);
    849 
    850         if (dest == NULL)
    851                 return (char *) NULL;
    852 
    853         return (char *) memcpy(dest, src, size + 1);
    854 }
    855 
    856977char *strtok(char *s, const char *delim)
    857978{
     
    8861007}
    8871008
     1009/** Convert string to uint64_t (internal variant).
     1010 *
     1011 * @param nptr   Pointer to string.
     1012 * @param endptr Pointer to the first invalid character is stored here.
     1013 * @param base   Zero or number between 2 and 36 inclusive.
     1014 * @param neg    Indication of unary minus is stored here.
     1015 * @apram result Result of the conversion.
     1016 *
     1017 * @return EOK if conversion was successful.
     1018 *
     1019 */
     1020static int str_uint(const char *nptr, char **endptr, unsigned int base,
     1021    bool *neg, uint64_t *result)
     1022{
     1023        assert(endptr != NULL);
     1024        assert(neg != NULL);
     1025        assert(result != NULL);
     1026       
     1027        *neg = false;
     1028        const char *str = nptr;
     1029       
     1030        /* Ignore leading whitespace */
     1031        while (isspace(*str))
     1032                str++;
     1033       
     1034        if (*str == '-') {
     1035                *neg = true;
     1036                str++;
     1037        } else if (*str == '+')
     1038                str++;
     1039       
     1040        if (base == 0) {
     1041                /* Decode base if not specified */
     1042                base = 10;
     1043               
     1044                if (*str == '0') {
     1045                        base = 8;
     1046                        str++;
     1047                       
     1048                        switch (*str) {
     1049                        case 'b':
     1050                        case 'B':
     1051                                base = 2;
     1052                                str++;
     1053                                break;
     1054                        case 'o':
     1055                        case 'O':
     1056                                base = 8;
     1057                                str++;
     1058                                break;
     1059                        case 'd':
     1060                        case 'D':
     1061                        case 't':
     1062                        case 'T':
     1063                                base = 10;
     1064                                str++;
     1065                                break;
     1066                        case 'x':
     1067                        case 'X':
     1068                                base = 16;
     1069                                str++;
     1070                                break;
     1071                        default:
     1072                                str--;
     1073                        }
     1074                }
     1075        } else {
     1076                /* Check base range */
     1077                if ((base < 2) || (base > 36)) {
     1078                        *endptr = (char *) str;
     1079                        return EINVAL;
     1080                }
     1081        }
     1082       
     1083        *result = 0;
     1084        const char *startstr = str;
     1085       
     1086        while (*str != 0) {
     1087                unsigned int digit;
     1088               
     1089                if ((*str >= 'a') && (*str <= 'z'))
     1090                        digit = *str - 'a' + 10;
     1091                else if ((*str >= 'A') && (*str <= 'Z'))
     1092                        digit = *str - 'A' + 10;
     1093                else if ((*str >= '0') && (*str <= '9'))
     1094                        digit = *str - '0';
     1095                else
     1096                        break;
     1097               
     1098                if (digit >= base)
     1099                        break;
     1100               
     1101                uint64_t prev = *result;
     1102                *result = (*result) * base + digit;
     1103               
     1104                if (*result < prev) {
     1105                        /* Overflow */
     1106                        *endptr = (char *) str;
     1107                        return EOVERFLOW;
     1108                }
     1109               
     1110                str++;
     1111        }
     1112       
     1113        if (str == startstr) {
     1114                /*
     1115                 * No digits were decoded => first invalid character is
     1116                 * the first character of the string.
     1117                 */
     1118                str = nptr;
     1119        }
     1120       
     1121        *endptr = (char *) str;
     1122       
     1123        if (str == nptr)
     1124                return EINVAL;
     1125       
     1126        return EOK;
     1127}
     1128
     1129/** Convert string to uint64_t.
     1130 *
     1131 * @param nptr   Pointer to string.
     1132 * @param endptr If not NULL, pointer to the first invalid character
     1133 *               is stored here.
     1134 * @param base   Zero or number between 2 and 36 inclusive.
     1135 * @param strict Do not allow any trailing characters.
     1136 * @param result Result of the conversion.
     1137 *
     1138 * @return EOK if conversion was successful.
     1139 *
     1140 */
     1141int str_uint64(const char *nptr, char **endptr, unsigned int base,
     1142    bool strict, uint64_t *result)
     1143{
     1144        assert(result != NULL);
     1145       
     1146        bool neg;
     1147        char *lendptr;
     1148        int ret = str_uint(nptr, &lendptr, base, &neg, result);
     1149       
     1150        if (endptr != NULL)
     1151                *endptr = (char *) lendptr;
     1152       
     1153        if (ret != EOK)
     1154                return ret;
     1155       
     1156        /* Do not allow negative values */
     1157        if (neg)
     1158                return EINVAL;
     1159       
     1160        /* Check whether we are at the end of
     1161           the string in strict mode */
     1162        if ((strict) && (*lendptr != 0))
     1163                return EINVAL;
     1164       
     1165        return EOK;
     1166}
     1167
     1168/** Convert string to size_t.
     1169 *
     1170 * @param nptr   Pointer to string.
     1171 * @param endptr If not NULL, pointer to the first invalid character
     1172 *               is stored here.
     1173 * @param base   Zero or number between 2 and 36 inclusive.
     1174 * @param strict Do not allow any trailing characters.
     1175 * @param result Result of the conversion.
     1176 *
     1177 * @return EOK if conversion was successful.
     1178 *
     1179 */
     1180int str_size_t(const char *nptr, char **endptr, unsigned int base,
     1181    bool strict, size_t *result)
     1182{
     1183        assert(result != NULL);
     1184       
     1185        bool neg;
     1186        char *lendptr;
     1187        uint64_t res;
     1188        int ret = str_uint(nptr, &lendptr, base, &neg, &res);
     1189       
     1190        if (endptr != NULL)
     1191                *endptr = (char *) lendptr;
     1192       
     1193        if (ret != EOK)
     1194                return ret;
     1195       
     1196        /* Do not allow negative values */
     1197        if (neg)
     1198                return EINVAL;
     1199       
     1200        /* Check whether we are at the end of
     1201           the string in strict mode */
     1202        if ((strict) && (*lendptr != 0))
     1203                return EINVAL;
     1204       
     1205        /* Check for overflow */
     1206        size_t _res = (size_t) res;
     1207        if (_res != res)
     1208                return EOVERFLOW;
     1209       
     1210        *result = _res;
     1211       
     1212        return EOK;
     1213}
     1214
     1215void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
     1216{
     1217        if (val > 10000000000000000000ULL) {
     1218                *rv = val / 1000000000000000000ULL;
     1219                *suffix = 'Z';
     1220        } else if (val > 1000000000000000000ULL) {
     1221                *rv = val / 1000000000000000ULL;
     1222                *suffix = 'E';
     1223        } else if (val > 1000000000000000ULL) {
     1224                *rv = val / 1000000000000ULL;
     1225                *suffix = 'T';
     1226        } else if (val > 1000000000000ULL) {
     1227                *rv = val / 1000000000ULL;
     1228                *suffix = 'G';
     1229        } else if (val > 1000000000ULL) {
     1230                *rv = val / 1000000ULL;
     1231                *suffix = 'M';
     1232        } else if (val > 1000000ULL) {
     1233                *rv = val / 1000ULL;
     1234                *suffix = 'k';
     1235        } else {
     1236                *rv = val;
     1237                *suffix = ' ';
     1238        }
     1239}
     1240
    8881241/** @}
    8891242 */
  • uspace/lib/c/generic/task.c

    rb50b5af2 r04803bf  
    3939#include <errno.h>
    4040#include <loader/loader.h>
    41 #include <string.h>
     41#include <stdarg.h>
     42#include <str.h>
    4243#include <ipc/ns.h>
    4344#include <macros.h>
     
    4647task_id_t task_get_id(void)
    4748{
     49#ifdef __32_BITS__
    4850        task_id_t task_id;
    4951        (void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id);
    5052       
    5153        return task_id;
     54#endif  /* __32_BITS__ */
     55       
     56#ifdef __64_BITS__
     57        return (task_id_t) __SYSCALL0(SYS_TASK_GET_ID);
     58#endif  /* __64_BITS__ */
    5259}
    5360
     
    5865 *
    5966 * @return Zero on success or negative error code.
    60  *
    6167 */
    6268int task_set_name(const char *name)
     
    6571}
    6672
     73/** Kill a task.
     74 *
     75 * @param task_id ID of task to kill.
     76 *
     77 * @return Zero on success or negative error code.
     78 */
     79
     80int task_kill(task_id_t task_id)
     81{
     82        return (int) __SYSCALL1(SYS_TASK_KILL, (sysarg_t) &task_id);
     83}
     84
    6785/** Create a new task by running an executable from the filesystem.
    6886 *
    6987 * This is really just a convenience wrapper over the more complicated
    70  * loader API.
    71  *
    72  * @param path pathname of the binary to execute
    73  * @param argv command-line arguments
    74  *
    75  * @return ID of the newly created task or zero on error.
    76  *
    77  */
    78 task_id_t task_spawn(const char *path, char *const args[])
    79 {
     88 * loader API. Arguments are passed as a null-terminated array of strings.
     89 *
     90 * @param id    If not NULL, the ID of the task is stored here on success.
     91 * @param path  Pathname of the binary to execute.
     92 * @param argv  Command-line arguments.
     93 *
     94 * @return      Zero on success or negative error code.
     95 */
     96int task_spawnv(task_id_t *id, const char *path, const char *const args[])
     97{
     98        loader_t *ldr;
     99        task_id_t task_id;
     100        int rc;
     101
    80102        /* Connect to a program loader. */
    81         loader_t *ldr = loader_connect();
     103        ldr = loader_connect();
    82104        if (ldr == NULL)
    83                 return 0;
     105                return EREFUSED;
    84106       
    85107        /* Get task ID. */
    86         task_id_t task_id;
    87         int rc = loader_get_task_id(ldr, &task_id);
     108        rc = loader_get_task_id(ldr, &task_id);
     109        if (rc != EOK)
     110                goto error;
     111       
     112        /* Send spawner's current working directory. */
     113        rc = loader_set_cwd(ldr);
    88114        if (rc != EOK)
    89115                goto error;
     
    98124        if (rc != EOK)
    99125                goto error;
    100        
    101126       
    102127        /* Send default files */
     
    139164        /* Success */
    140165        free(ldr);
    141         return task_id;
     166       
     167        if (id != NULL)
     168                *id = task_id;
     169       
     170        return EOK;
    142171       
    143172error:
     
    145174        loader_abort(ldr);
    146175        free(ldr);
    147        
    148         return 0;
     176        return rc;
     177}
     178
     179/** Create a new task by running an executable from the filesystem.
     180 *
     181 * This is really just a convenience wrapper over the more complicated
     182 * loader API. Arguments are passed as a null-terminated list of arguments.
     183 *
     184 * @param id    If not NULL, the ID of the task is stored here on success.
     185 * @param path  Pathname of the binary to execute.
     186 * @param ...   Command-line arguments.
     187 *
     188 * @return      Zero on success or negative error code.
     189 */
     190int task_spawnl(task_id_t *task_id, const char *path, ...)
     191{
     192        va_list ap;
     193        int rc, cnt;
     194        const char *arg;
     195        const char **arglist;
     196
     197        /* Count the number of arguments. */
     198        cnt = 0;
     199        va_start(ap, path);
     200        do {
     201                arg = va_arg(ap, const char *);
     202                cnt++;
     203        } while (arg != NULL);
     204        va_end(ap);
     205
     206        /* Allocate argument list. */
     207        arglist = malloc(cnt * sizeof(const char *));
     208        if (arglist == NULL)
     209                return ENOMEM;
     210
     211        /* Fill in arguments. */
     212        cnt = 0;
     213        va_start(ap, path);
     214        do {
     215                arg = va_arg(ap, const char *);
     216                arglist[cnt++] = arg;
     217        } while (arg != NULL);
     218        va_end(ap);
     219
     220        /* Spawn task. */
     221        rc = task_spawnv(task_id, path, arglist);
     222
     223        /* Free argument list. */
     224        free(arglist);
     225        return rc;
    149226}
    150227
    151228int task_wait(task_id_t id, task_exit_t *texit, int *retval)
    152229{
    153         ipcarg_t te, rv;
     230        sysarg_t te, rv;
    154231        int rc;
    155232
  • uspace/lib/c/generic/thread.c

    rb50b5af2 r04803bf  
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    3535#include <thread.h>
     
    3939#include <kernel/proc/uarg.h>
    4040#include <fibril.h>
    41 #include <string.h>
     41#include <str.h>
    4242#include <async.h>
     43#include "private/thread.h"
    4344
    4445#ifndef THREAD_INITIAL_STACK_PAGES_NO
     
    5051 * This function is called from __thread_entry() and is used
    5152 * to call the thread's implementing function and perform cleanup
    52  * and exit when thread returns back. Do not call this function
    53  * directly.
     53 * and exit when thread returns back.
    5454 *
    5555 * @param uarg Pointer to userspace argument structure.
     56 *
    5657 */
    5758void __thread_main(uspace_arg_t *uarg)
    5859{
    59         fibril_t *f;
    60 
    61         f = fibril_setup();
    62         __tcb_set(f->tcb);
    63 
     60        fibril_t *fibril = fibril_setup();
     61        if (fibril == NULL)
     62                thread_exit(0);
     63       
     64        __tcb_set(fibril->tcb);
     65       
    6466        uarg->uspace_thread_function(uarg->uspace_thread_arg);
    65         /* XXX: we cannot free the userspace stack while running on it */
    66 //      free(uarg->uspace_stack);
    67 //      free(uarg);
    68 
     67        /* XXX: we cannot free the userspace stack while running on it
     68                free(uarg->uspace_stack);
     69                free(uarg);
     70        */
     71       
    6972        /* If there is a manager, destroy it */
    7073        async_destroy_manager();
    71         fibril_teardown(f);
    72 
     74        fibril_teardown(fibril);
     75       
    7376        thread_exit(0);
    7477}
     
    8689 * @return Zero on success or a code from @ref errno.h on failure.
    8790 */
    88 int thread_create(void (* function)(void *), void *arg, char *name,
     91int thread_create(void (* function)(void *), void *arg, const char *name,
    8992    thread_id_t *tid)
    9093{
     
    127130 *
    128131 * @param status Exit status. Currently not used.
     132 *
    129133 */
    130134void thread_exit(int status)
    131135{
    132136        __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
    133         for (;;)
    134                 ;
     137       
     138        /* Unreachable */
     139        while (1);
    135140}
    136141
  • uspace/lib/c/generic/time.c

    rb50b5af2 r04803bf  
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    3535#include <sys/time.h>
    36 #include <unistd.h>
    37 #include <ipc/ipc.h>
    38 #include <stdio.h>
     36#include <time.h>
     37#include <bool.h>
    3938#include <arch/barrier.h>
    40 #include <unistd.h>
    41 #include <atomic.h>
    42 #include <futex.h>
    43 #include <sysinfo.h>
    44 #include <ipc/services.h>
    45 
     39#include <macros.h>
     40#include <errno.h>
    4641#include <sysinfo.h>
    4742#include <as.h>
    4843#include <ddi.h>
    49 
    50 #include <time.h>
    51 
    52 /* Pointers to public variables with time */
     44#include <libc.h>
     45
     46/** Pointer to kernel shared variables with time */
    5347struct {
    5448        volatile sysarg_t seconds1;
     
    5953/** Add microseconds to given timeval.
    6054 *
    61  * @param tv            Destination timeval.
    62  * @param usecs         Number of microseconds to add.
     55 * @param tv    Destination timeval.
     56 * @param usecs Number of microseconds to add.
     57 *
    6358 */
    6459void tv_add(struct timeval *tv, suseconds_t usecs)
     
    6661        tv->tv_sec += usecs / 1000000;
    6762        tv->tv_usec += usecs % 1000000;
     63       
    6864        if (tv->tv_usec > 1000000) {
    6965                tv->tv_sec++;
     
    7470/** Subtract two timevals.
    7571 *
    76  * @param tv1           First timeval.
    77  * @param tv2           Second timeval.
    78  *
    79  * @return              Return difference between tv1 and tv2 (tv1 - tv2) in
    80  *                      microseconds.
     72 * @param tv1 First timeval.
     73 * @param tv2 Second timeval.
     74 *
     75 * @return Difference between tv1 and tv2 (tv1 - tv2) in
     76 *         microseconds.
     77 *
    8178 */
    8279suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
    8380{
    84         suseconds_t result;
    85 
    86         result = tv1->tv_usec - tv2->tv_usec;
    87         result += (tv1->tv_sec - tv2->tv_sec) * 1000000;
    88 
    89         return result;
     81        return (tv1->tv_usec - tv2->tv_usec) +
     82            ((tv1->tv_sec - tv2->tv_sec) * 1000000);
    9083}
    9184
    9285/** Decide if one timeval is greater than the other.
    9386 *
    94  * @param t1            First timeval.
    95  * @param t2            Second timeval.
    96  *
    97  * @return              Return true tv1 is greater than tv2. Otherwise return
    98  *                      false.
     87 * @param t1 First timeval.
     88 * @param t2 Second timeval.
     89 *
     90 * @return True if tv1 is greater than tv2.
     91 * @return False otherwise.
     92 *
    9993 */
    10094int tv_gt(struct timeval *tv1, struct timeval *tv2)
    10195{
    10296        if (tv1->tv_sec > tv2->tv_sec)
    103                 return 1;
    104         if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec > tv2->tv_usec)
    105                 return 1;
    106         return 0;
     97                return true;
     98       
     99        if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec))
     100                return true;
     101       
     102        return false;
    107103}
    108104
    109105/** Decide if one timeval is greater than or equal to the other.
    110106 *
    111  * @param tv1           First timeval.
    112  * @param tv2           Second timeval.
    113  *
    114  * @return              Return true if tv1 is greater than or equal to tv2.
    115  *                      Otherwise return false.
     107 * @param tv1 First timeval.
     108 * @param tv2 Second timeval.
     109 *
     110 * @return True if tv1 is greater than or equal to tv2.
     111 * @return False otherwise.
     112 *
    116113 */
    117114int tv_gteq(struct timeval *tv1, struct timeval *tv2)
    118115{
    119116        if (tv1->tv_sec > tv2->tv_sec)
    120                 return 1;
    121         if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec >= tv2->tv_usec)
    122                 return 1;
    123         return 0;
    124 }
    125 
    126 
    127 /** POSIX gettimeofday
    128  *
    129  * The time variables are memory mapped(RO) from kernel, which updates
    130  * them periodically. As it is impossible to read 2 values atomically, we
    131  * use a trick: First read a seconds, then read microseconds, then
    132  * read seconds again. If a second elapsed in the meantime, set it to zero.
    133  * This provides assurance, that at least the
    134  * sequence of subsequent gettimeofday calls is ordered.
     117                return true;
     118       
     119        if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec))
     120                return true;
     121       
     122        return false;
     123}
     124
     125/** Get time of day
     126 *
     127 * The time variables are memory mapped (read-only) from kernel which
     128 * updates them periodically.
     129 *
     130 * As it is impossible to read 2 values atomically, we use a trick:
     131 * First we read the seconds, then we read the microseconds, then we
     132 * read the seconds again. If a second elapsed in the meantime, set
     133 * the microseconds to zero.
     134 *
     135 * This assures that the values returned by two subsequent calls
     136 * to gettimeofday() are monotonous.
     137 *
    135138 */
    136139int gettimeofday(struct timeval *tv, struct timezone *tz)
    137140{
    138         void *mapping;
    139         sysarg_t s1, s2;
    140         int rights;
    141         int res;
    142 
    143         if (!ktime) {
    144                 mapping = as_get_mappable_page(PAGE_SIZE);
    145                 /* Get the mapping of kernel clock */
    146                 res = ipc_share_in_start_1_1(PHONE_NS, mapping, PAGE_SIZE,
    147                     SERVICE_MEM_REALTIME, &rights);
    148                 if (res) {
    149                         printf("Failed to initialize timeofday memarea\n");
    150                         printf("Address was 0x%x\n", (unsigned)mapping);
    151                         _exit(1);
     141        if (ktime == NULL) {
     142                uintptr_t faddr;
     143                int rc = sysinfo_get_value("clock.faddr", &faddr);
     144                if (rc != EOK) {
     145                        errno = rc;
     146                        return -1;
    152147                }
    153                 if (!(rights & AS_AREA_READ)) {
    154                         printf("Received bad rights on time area: %X\n",
    155                             rights);
    156                         as_area_destroy(mapping);
    157                         _exit(1);
     148               
     149                void *addr = as_get_mappable_page(PAGE_SIZE);
     150                if (addr == NULL) {
     151                        errno = ENOMEM;
     152                        return -1;
    158153                }
    159                 ktime = mapping;
    160         }
     154               
     155                rc = physmem_map((void *) faddr, addr, 1,
     156                    AS_AREA_READ | AS_AREA_CACHEABLE);
     157                if (rc != EOK) {
     158                        as_area_destroy(addr);
     159                        errno = rc;
     160                        return -1;
     161                }
     162               
     163                ktime = addr;
     164        }
     165       
    161166        if (tz) {
    162167                tz->tz_minuteswest = 0;
    163168                tz->tz_dsttime = DST_NONE;
    164169        }
    165 
    166         s2 = ktime->seconds2;
     170       
     171        sysarg_t s2 = ktime->seconds2;
     172       
    167173        read_barrier();
    168174        tv->tv_usec = ktime->useconds;
     175       
    169176        read_barrier();
    170         s1 = ktime->seconds1;
     177        sysarg_t s1 = ktime->seconds1;
     178       
    171179        if (s1 != s2) {
     180                tv->tv_sec = max(s1, s2);
    172181                tv->tv_usec = 0;
    173                 tv->tv_sec = s1 > s2 ? s1 : s2;
    174182        } else
    175183                tv->tv_sec = s1;
    176 
     184       
    177185        return 0;
    178186}
     
    181189{
    182190        struct timeval tv;
    183 
    184191        if (gettimeofday(&tv, NULL))
    185192                return (time_t) -1;
     193       
    186194        if (tloc)
    187195                *tloc = tv.tv_sec;
     196       
    188197        return tv.tv_sec;
    189198}
    190199
    191 /** Wait unconditionally for specified number of microseconds */
    192 int usleep(unsigned long usec)
    193 {
    194         atomic_t futex = FUTEX_INITIALIZER;
    195 
    196         futex_initialize(&futex, 0);
    197         futex_down_timeout(&futex, usec, 0);
     200/** Wait unconditionally for specified number of microseconds
     201 *
     202 */
     203int usleep(useconds_t usec)
     204{
     205        (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
    198206        return 0;
    199207}
    200208
    201 /** Wait unconditionally for specified number of seconds */
    202 unsigned int sleep(unsigned int seconds)
    203 {
    204         atomic_t futex = FUTEX_INITIALIZER;
    205 
    206         futex_initialize(&futex, 0);
    207        
    208         /* Sleep in 1000 second steps to support
    209            full argument range */
    210         while (seconds > 0) {
    211                 unsigned int period = (seconds > 1000) ? 1000 : seconds;
    212        
    213                 futex_down_timeout(&futex, period * 1000000, 0);
    214                 seconds -= period;
    215         }
     209/** Wait unconditionally for specified number of seconds
     210 *
     211 */
     212unsigned int sleep(unsigned int sec)
     213{
     214        /*
     215         * Sleep in 1000 second steps to support
     216         * full argument range
     217         */
     218       
     219        while (sec > 0) {
     220                unsigned int period = (sec > 1000) ? 1000 : sec;
     221               
     222                usleep(period * 1000000);
     223                sec -= period;
     224        }
     225       
    216226        return 0;
    217227}
  • uspace/lib/c/generic/tls.c

    rb50b5af2 r04803bf  
    4040#include <tls.h>
    4141#include <malloc.h>
    42 #include <string.h>
     42#include <str.h>
    4343#include <align.h>
    4444
  • uspace/lib/c/generic/udebug.c

    rb50b5af2 r04803bf  
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    3535#include <udebug.h>
    3636#include <sys/types.h>
    37 #include <ipc/ipc.h>
    3837#include <async.h>
    3938
     
    5756        size_t *copied, size_t *needed)
    5857{
    59         ipcarg_t a_copied, a_needed;
     58        sysarg_t a_copied, a_needed;
    6059        int rc;
    6160
    6261        rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_THREAD_READ,
     62                (sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
     63
     64        *copied = (size_t)a_copied;
     65        *needed = (size_t)a_needed;
     66
     67        return rc;
     68}
     69
     70int udebug_name_read(int phoneid, void *buffer, size_t n,
     71        size_t *copied, size_t *needed)
     72{
     73        sysarg_t a_copied, a_needed;
     74        int rc;
     75
     76        rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_NAME_READ,
     77                (sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
     78
     79        *copied = (size_t)a_copied;
     80        *needed = (size_t)a_needed;
     81
     82        return rc;
     83}
     84
     85int udebug_areas_read(int phoneid, void *buffer, size_t n,
     86        size_t *copied, size_t *needed)
     87{
     88        sysarg_t a_copied, a_needed;
     89        int rc;
     90
     91        rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_AREAS_READ,
    6392                (sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
    6493
     
    81110}
    82111
     112int udebug_regs_read(int phoneid, thash_t tid, void *buffer)
     113{
     114        return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_REGS_READ,
     115            tid, (sysarg_t)buffer);
     116}
     117
    83118int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
    84119    sysarg_t *val0, sysarg_t *val1)
    85120{
    86         ipcarg_t a_ev_type;
     121        sysarg_t a_ev_type;
    87122        int rc;
    88123
  • uspace/lib/c/generic/vfs/canonify.c

    rb50b5af2 r04803bf  
    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/c/generic/vfs/vfs.c

    rb50b5af2 r04803bf  
    11/*
    2  * Copyright (c) 2008 Jakub Jermar 
     2 * Copyright (c) 2008 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    3535#include <vfs/vfs.h>
    3636#include <vfs/canonify.h>
     37#include <macros.h>
    3738#include <stdlib.h>
    3839#include <unistd.h>
     
    4243#include <sys/stat.h>
    4344#include <sys/types.h>
    44 #include <ipc/ipc.h>
    4545#include <ipc/services.h>
     46#include <ipc/ns.h>
    4647#include <async.h>
    47 #include <atomic.h>
    48 #include <futex.h>
     48#include <fibril_synch.h>
    4949#include <errno.h>
    50 #include <string.h>
     50#include <assert.h>
     51#include <str.h>
    5152#include <devmap.h>
    5253#include <ipc/vfs.h>
    5354#include <ipc/devmap.h>
    5455
     56static async_sess_t vfs_session;
     57
     58static FIBRIL_MUTEX_INITIALIZE(vfs_phone_mutex);
    5559static int vfs_phone = -1;
    56 static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
    57 static futex_t cwd_futex = FUTEX_INITIALIZER;
    58 
    59 DIR *cwd_dir = NULL;
    60 char *cwd_path = NULL;
    61 size_t cwd_size = 0;
     60
     61static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
     62
     63static int cwd_fd = -1;
     64static char *cwd_path = NULL;
     65static size_t cwd_size = 0;
    6266
    6367char *absolutize(const char *path, size_t *retlen)
     
    6569        char *ncwd_path;
    6670        char *ncwd_path_nc;
    67 
    68         futex_down(&cwd_futex);
     71        size_t total_size;
     72
     73        fibril_mutex_lock(&cwd_mutex);
    6974        size_t size = str_size(path);
    7075        if (*path != '/') {
    7176                if (!cwd_path) {
    72                         futex_up(&cwd_futex);
     77                        fibril_mutex_unlock(&cwd_mutex);
    7378                        return NULL;
    7479                }
    75                 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
     80                total_size = cwd_size + 1 + size + 1;
     81                ncwd_path_nc = malloc(total_size);
    7682                if (!ncwd_path_nc) {
    77                         futex_up(&cwd_futex);
     83                        fibril_mutex_unlock(&cwd_mutex);
    7884                        return NULL;
    7985                }
    80                 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
     86                str_cpy(ncwd_path_nc, total_size, cwd_path);
    8187                ncwd_path_nc[cwd_size] = '/';
    8288                ncwd_path_nc[cwd_size + 1] = '\0';
    8389        } else {
    84                 ncwd_path_nc = malloc(size + 1);
     90                total_size = size + 1;
     91                ncwd_path_nc = malloc(total_size);
    8592                if (!ncwd_path_nc) {
    86                         futex_up(&cwd_futex);
     93                        fibril_mutex_unlock(&cwd_mutex);
    8794                        return NULL;
    8895                }
    8996                ncwd_path_nc[0] = '\0';
    9097        }
    91         str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
     98        str_append(ncwd_path_nc, total_size, path);
    9299        ncwd_path = canonify(ncwd_path_nc, retlen);
    93100        if (!ncwd_path) {
    94                 futex_up(&cwd_futex);
     101                fibril_mutex_unlock(&cwd_mutex);
    95102                free(ncwd_path_nc);
    96103                return NULL;
     
    104111        free(ncwd_path_nc);
    105112        if (!ncwd_path) {
    106                 futex_up(&cwd_futex);
     113                fibril_mutex_unlock(&cwd_mutex);
    107114                return NULL;
    108115        }
    109         futex_up(&cwd_futex);
     116        fibril_mutex_unlock(&cwd_mutex);
    110117        return ncwd_path;
    111118}
    112119
     120/** Connect to VFS service and create session. */
    113121static void vfs_connect(void)
    114122{
    115123        while (vfs_phone < 0)
    116                 vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
    117 }
    118 
    119 int mount(const char *fs_name, const char *mp, const char *dev,
     124                vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
     125       
     126        async_session_create(&vfs_session, vfs_phone, 0);
     127}
     128
     129/** Start an async exchange on the VFS session.
     130 *
     131 * @return              New phone to be used during the exchange.
     132 */
     133static int vfs_exchange_begin(void)
     134{
     135        fibril_mutex_lock(&vfs_phone_mutex);
     136        if (vfs_phone < 0)
     137                vfs_connect();
     138        fibril_mutex_unlock(&vfs_phone_mutex);
     139
     140        return async_exchange_begin(&vfs_session);
     141}
     142
     143/** End an async exchange on the VFS session.
     144 *
     145 * @param phone         Phone used during the exchange.
     146 */
     147static void vfs_exchange_end(int phone)
     148{
     149        async_exchange_end(&vfs_session, phone);
     150}
     151
     152int mount(const char *fs_name, const char *mp, const char *fqdn,
    120153    const char *opts, unsigned int flags)
    121154{
    122         int res;
    123         ipcarg_t rc;
    124         ipcarg_t rc_orig;
    125         aid_t req;
    126         dev_handle_t dev_handle;
    127        
    128         res = devmap_device_get_handle(dev, &dev_handle, flags);
    129         if (res != EOK)
     155        int null_id = -1;
     156        char null[DEVMAP_NAME_MAXLEN];
     157       
     158        if (str_cmp(fqdn, "") == 0) {
     159                /* No device specified, create a fresh
     160                   null/%d device instead */
     161                null_id = devmap_null_create();
     162               
     163                if (null_id == -1)
     164                        return ENOMEM;
     165               
     166                snprintf(null, DEVMAP_NAME_MAXLEN, "null/%d", null_id);
     167                fqdn = null;
     168        }
     169       
     170        devmap_handle_t devmap_handle;
     171        int res = devmap_device_get_handle(fqdn, &devmap_handle, flags);
     172        if (res != EOK) {
     173                if (null_id != -1)
     174                        devmap_null_destroy(null_id);
     175               
    130176                return res;
     177        }
    131178       
    132179        size_t mpa_size;
    133180        char *mpa = absolutize(mp, &mpa_size);
     181        if (!mpa) {
     182                if (null_id != -1)
     183                        devmap_null_destroy(null_id);
     184               
     185                return ENOMEM;
     186        }
     187       
     188        int vfs_phone = vfs_exchange_begin();
     189
     190        sysarg_t rc_orig;
     191        aid_t req = async_send_2(vfs_phone, VFS_IN_MOUNT, devmap_handle, flags, NULL);
     192        sysarg_t rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
     193        if (rc != EOK) {
     194                vfs_exchange_end(vfs_phone);
     195                free(mpa);
     196                async_wait_for(req, &rc_orig);
     197               
     198                if (null_id != -1)
     199                        devmap_null_destroy(null_id);
     200               
     201                if (rc_orig == EOK)
     202                        return (int) rc;
     203                else
     204                        return (int) rc_orig;
     205        }
     206       
     207        rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
     208        if (rc != EOK) {
     209                vfs_exchange_end(vfs_phone);
     210                free(mpa);
     211                async_wait_for(req, &rc_orig);
     212               
     213                if (null_id != -1)
     214                        devmap_null_destroy(null_id);
     215               
     216                if (rc_orig == EOK)
     217                        return (int) rc;
     218                else
     219                        return (int) rc_orig;
     220        }
     221       
     222        rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
     223        if (rc != EOK) {
     224                vfs_exchange_end(vfs_phone);
     225                free(mpa);
     226                async_wait_for(req, &rc_orig);
     227               
     228                if (null_id != -1)
     229                        devmap_null_destroy(null_id);
     230               
     231                if (rc_orig == EOK)
     232                        return (int) rc;
     233                else
     234                        return (int) rc_orig;
     235        }
     236       
     237        /* Ask VFS whether it likes fs_name. */
     238        rc = async_req_0_0(vfs_phone, IPC_M_PING);
     239        if (rc != EOK) {
     240                vfs_exchange_end(vfs_phone);
     241                free(mpa);
     242                async_wait_for(req, &rc_orig);
     243               
     244                if (null_id != -1)
     245                        devmap_null_destroy(null_id);
     246               
     247                if (rc_orig == EOK)
     248                        return (int) rc;
     249                else
     250                        return (int) rc_orig;
     251        }
     252       
     253        vfs_exchange_end(vfs_phone);
     254        free(mpa);
     255        async_wait_for(req, &rc);
     256       
     257        if ((rc != EOK) && (null_id != -1))
     258                devmap_null_destroy(null_id);
     259       
     260        return (int) rc;
     261}
     262
     263int unmount(const char *mp)
     264{
     265        sysarg_t rc;
     266        sysarg_t rc_orig;
     267        aid_t req;
     268        size_t mpa_size;
     269        char *mpa;
     270       
     271        mpa = absolutize(mp, &mpa_size);
    134272        if (!mpa)
    135273                return ENOMEM;
    136274       
    137         futex_down(&vfs_phone_futex);
    138         async_serialize_start();
    139         vfs_connect();
    140        
    141         req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
    142         rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
    143         if (rc != EOK) {
    144                 async_wait_for(req, &rc_orig);
    145                 async_serialize_end();
    146                 futex_up(&vfs_phone_futex);
     275        int vfs_phone = vfs_exchange_begin();
     276       
     277        req = async_send_0(vfs_phone, VFS_IN_UNMOUNT, NULL);
     278        rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
     279        if (rc != EOK) {
     280                vfs_exchange_end(vfs_phone);
    147281                free(mpa);
    148                 if (rc_orig == EOK)
    149                         return (int) rc;
    150                 else
    151                         return (int) rc_orig;
    152         }
    153        
    154         rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
    155         if (rc != EOK) {
    156                 async_wait_for(req, &rc_orig);
    157                 async_serialize_end();
    158                 futex_up(&vfs_phone_futex);
    159                 free(mpa);
    160                 if (rc_orig == EOK)
    161                         return (int) rc;
    162                 else
    163                         return (int) rc_orig;
    164         }
    165 
    166         rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
    167         if (rc != EOK) {
    168                 async_wait_for(req, &rc_orig);
    169                 async_serialize_end();
    170                 futex_up(&vfs_phone_futex);
    171                 free(mpa);
    172                 if (rc_orig == EOK)
    173                         return (int) rc;
    174                 else
    175                         return (int) rc_orig;
    176         }
    177 
    178         /* Ask VFS whether it likes fs_name. */
    179         rc = async_req_0_0(vfs_phone, IPC_M_PING);
    180         if (rc != EOK) {
    181                 async_wait_for(req, &rc_orig);
    182                 async_serialize_end();
    183                 futex_up(&vfs_phone_futex);
    184                 free(mpa);
    185                 if (rc_orig == EOK)
    186                         return (int) rc;
    187                 else
    188                         return (int) rc_orig;
    189         }
    190        
    191         async_wait_for(req, &rc);
    192         async_serialize_end();
    193         futex_up(&vfs_phone_futex);
     282                async_wait_for(req, &rc_orig);
     283                if (rc_orig == EOK)
     284                        return (int) rc;
     285                else
     286                        return (int) rc_orig;
     287        }
     288       
     289
     290        vfs_exchange_end(vfs_phone);
    194291        free(mpa);
     292        async_wait_for(req, &rc);
    195293       
    196294        return (int) rc;
    197295}
    198296
    199 static int _open(const char *path, int lflag, int oflag, ...)
    200 {
    201         ipcarg_t rc;
     297static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
     298{
     299        int vfs_phone = vfs_exchange_begin();
     300       
    202301        ipc_call_t answer;
     302        aid_t req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
     303        sysarg_t rc = async_data_write_start(vfs_phone, abs, abs_size);
     304       
     305        if (rc != EOK) {
     306                vfs_exchange_end(vfs_phone);
     307
     308                sysarg_t rc_orig;
     309                async_wait_for(req, &rc_orig);
     310               
     311                if (rc_orig == EOK)
     312                        return (int) rc;
     313                else
     314                        return (int) rc_orig;
     315        }
     316       
     317        vfs_exchange_end(vfs_phone);
     318        async_wait_for(req, &rc);
     319       
     320        if (rc != EOK)
     321            return (int) rc;
     322       
     323        return (int) IPC_GET_ARG1(answer);
     324}
     325
     326int open(const char *path, int oflag, ...)
     327{
     328        size_t abs_size;
     329        char *abs = absolutize(path, &abs_size);
     330        if (!abs)
     331                return ENOMEM;
     332       
     333        int ret = open_internal(abs, abs_size, L_FILE, oflag);
     334        free(abs);
     335       
     336        return ret;
     337}
     338
     339int open_node(fdi_node_t *node, int oflag)
     340{
     341        int vfs_phone = vfs_exchange_begin();
     342       
     343        ipc_call_t answer;
     344        aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
     345            node->devmap_handle, node->index, oflag, &answer);
     346       
     347        vfs_exchange_end(vfs_phone);
     348
     349        sysarg_t rc;
     350        async_wait_for(req, &rc);
     351       
     352        if (rc != EOK)
     353                return (int) rc;
     354       
     355        return (int) IPC_GET_ARG1(answer);
     356}
     357
     358int close(int fildes)
     359{
     360        sysarg_t rc;
     361       
     362        int vfs_phone = vfs_exchange_begin();
     363       
     364        rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
     365       
     366        vfs_exchange_end(vfs_phone);
     367       
     368        return (int)rc;
     369}
     370
     371ssize_t read(int fildes, void *buf, size_t nbyte)
     372{
     373        sysarg_t rc;
     374        ipc_call_t answer;
     375        aid_t req;
     376
     377        int vfs_phone = vfs_exchange_begin();
     378       
     379        req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
     380        rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
     381        if (rc != EOK) {
     382                vfs_exchange_end(vfs_phone);
     383
     384                sysarg_t rc_orig;
     385                async_wait_for(req, &rc_orig);
     386
     387                if (rc_orig == EOK)
     388                        return (ssize_t) rc;
     389                else
     390                        return (ssize_t) rc_orig;
     391        }
     392        vfs_exchange_end(vfs_phone);
     393        async_wait_for(req, &rc);
     394        if (rc == EOK)
     395                return (ssize_t) IPC_GET_ARG1(answer);
     396        else
     397                return rc;
     398}
     399
     400ssize_t write(int fildes, const void *buf, size_t nbyte)
     401{
     402        sysarg_t rc;
     403        ipc_call_t answer;
     404        aid_t req;
     405
     406        int vfs_phone = vfs_exchange_begin();
     407       
     408        req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
     409        rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
     410        if (rc != EOK) {
     411                vfs_exchange_end(vfs_phone);
     412
     413                sysarg_t rc_orig;
     414                async_wait_for(req, &rc_orig);
     415
     416                if (rc_orig == EOK)
     417                        return (ssize_t) rc;
     418                else
     419                        return (ssize_t) rc_orig;
     420        }
     421        vfs_exchange_end(vfs_phone);
     422        async_wait_for(req, &rc);
     423        if (rc == EOK)
     424                return (ssize_t) IPC_GET_ARG1(answer);
     425        else
     426                return -1;
     427}
     428
     429int fsync(int fildes)
     430{
     431        int vfs_phone = vfs_exchange_begin();
     432       
     433        sysarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
     434       
     435        vfs_exchange_end(vfs_phone);
     436       
     437        return (int) rc;
     438}
     439
     440off64_t lseek(int fildes, off64_t offset, int whence)
     441{
     442        int vfs_phone = vfs_exchange_begin();
     443       
     444        sysarg_t newoff_lo;
     445        sysarg_t newoff_hi;
     446        sysarg_t rc = async_req_4_2(vfs_phone, VFS_IN_SEEK, fildes,
     447            LOWER32(offset), UPPER32(offset), whence,
     448            &newoff_lo, &newoff_hi);
     449       
     450        vfs_exchange_end(vfs_phone);
     451       
     452        if (rc != EOK)
     453                return (off64_t) -1;
     454       
     455        return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
     456}
     457
     458int ftruncate(int fildes, aoff64_t length)
     459{
     460        sysarg_t rc;
     461       
     462        int vfs_phone = vfs_exchange_begin();
     463       
     464        rc = async_req_3_0(vfs_phone, VFS_IN_TRUNCATE, fildes,
     465            LOWER32(length), UPPER32(length));
     466        vfs_exchange_end(vfs_phone);
     467       
     468        return (int) rc;
     469}
     470
     471int fstat(int fildes, struct stat *stat)
     472{
     473        sysarg_t rc;
     474        aid_t req;
     475
     476        int vfs_phone = vfs_exchange_begin();
     477       
     478        req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
     479        rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat));
     480        if (rc != EOK) {
     481                vfs_exchange_end(vfs_phone);
     482
     483                sysarg_t rc_orig;
     484                async_wait_for(req, &rc_orig);
     485
     486                if (rc_orig == EOK)
     487                        return (ssize_t) rc;
     488                else
     489                        return (ssize_t) rc_orig;
     490        }
     491        vfs_exchange_end(vfs_phone);
     492        async_wait_for(req, &rc);
     493
     494        return rc;
     495}
     496
     497int stat(const char *path, struct stat *stat)
     498{
     499        sysarg_t rc;
     500        sysarg_t rc_orig;
    203501        aid_t req;
    204502       
     
    208506                return ENOMEM;
    209507       
    210         futex_down(&vfs_phone_futex);
    211         async_serialize_start();
    212         vfs_connect();
    213        
    214         req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
    215         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
    216         if (rc != EOK) {
    217                 ipcarg_t rc_orig;
    218        
    219                 async_wait_for(req, &rc_orig);
    220                 async_serialize_end();
    221                 futex_up(&vfs_phone_futex);
     508        int vfs_phone = vfs_exchange_begin();
     509       
     510        req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
     511        rc = async_data_write_start(vfs_phone, pa, pa_size);
     512        if (rc != EOK) {
     513                vfs_exchange_end(vfs_phone);
    222514                free(pa);
    223                 if (rc_orig == EOK)
    224                         return (int) rc;
    225                 else
    226                         return (int) rc_orig;
    227         }
    228         async_wait_for(req, &rc);
    229         async_serialize_end();
    230         futex_up(&vfs_phone_futex);
     515                async_wait_for(req, &rc_orig);
     516                if (rc_orig == EOK)
     517                        return (int) rc;
     518                else
     519                        return (int) rc_orig;
     520        }
     521        rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
     522        if (rc != EOK) {
     523                vfs_exchange_end(vfs_phone);
     524                free(pa);
     525                async_wait_for(req, &rc_orig);
     526                if (rc_orig == EOK)
     527                        return (int) rc;
     528                else
     529                        return (int) rc_orig;
     530        }
     531        vfs_exchange_end(vfs_phone);
    231532        free(pa);
    232        
    233         if (rc != EOK)
    234             return (int) rc;
    235        
    236         return (int) IPC_GET_ARG1(answer);
    237 }
    238 
    239 int open(const char *path, int oflag, ...)
    240 {
    241         return _open(path, L_FILE, oflag);
    242 }
    243 
    244 int open_node(fdi_node_t *node, int oflag)
    245 {
    246         futex_down(&vfs_phone_futex);
    247         async_serialize_start();
    248         vfs_connect();
    249        
    250         ipc_call_t answer;
    251         aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
    252             node->dev_handle, node->index, oflag, &answer);
    253        
    254         ipcarg_t rc;
    255         async_wait_for(req, &rc);
    256         async_serialize_end();
    257         futex_up(&vfs_phone_futex);
    258        
    259         if (rc != EOK)
    260                 return (int) rc;
    261        
    262         return (int) IPC_GET_ARG1(answer);
    263 }
    264 
    265 int close(int fildes)
    266 {
    267         ipcarg_t rc;
    268        
    269         futex_down(&vfs_phone_futex);
    270         async_serialize_start();
    271         vfs_connect();
    272        
    273         rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
    274        
    275         async_serialize_end();
    276         futex_up(&vfs_phone_futex);
    277        
    278         return (int)rc;
    279 }
    280 
    281 ssize_t read(int fildes, void *buf, size_t nbyte)
    282 {
    283         ipcarg_t rc;
    284         ipc_call_t answer;
    285         aid_t req;
    286 
    287         futex_down(&vfs_phone_futex);
    288         async_serialize_start();
    289         vfs_connect();
    290        
    291         req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
    292         rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
    293         if (rc != EOK) {
    294                 ipcarg_t rc_orig;
    295        
    296                 async_wait_for(req, &rc_orig);
    297                 async_serialize_end();
    298                 futex_up(&vfs_phone_futex);
    299                 if (rc_orig == EOK)
    300                         return (ssize_t) rc;
    301                 else
    302                         return (ssize_t) rc_orig;
    303         }
    304         async_wait_for(req, &rc);
    305         async_serialize_end();
    306         futex_up(&vfs_phone_futex);
    307         if (rc == EOK)
    308                 return (ssize_t) IPC_GET_ARG1(answer);
    309         else
    310                 return rc;
    311 }
    312 
    313 ssize_t write(int fildes, const void *buf, size_t nbyte)
    314 {
    315         ipcarg_t rc;
    316         ipc_call_t answer;
    317         aid_t req;
    318 
    319         futex_down(&vfs_phone_futex);
    320         async_serialize_start();
    321         vfs_connect();
    322        
    323         req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
    324         rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
    325         if (rc != EOK) {
    326                 ipcarg_t rc_orig;
    327        
    328                 async_wait_for(req, &rc_orig);
    329                 async_serialize_end();
    330                 futex_up(&vfs_phone_futex);
    331                 if (rc_orig == EOK)
    332                         return (ssize_t) rc;
    333                 else
    334                         return (ssize_t) rc_orig;
    335         }
    336         async_wait_for(req, &rc);
    337         async_serialize_end();
    338         futex_up(&vfs_phone_futex);
    339         if (rc == EOK)
    340                 return (ssize_t) IPC_GET_ARG1(answer);
    341         else
    342                 return -1;
    343 }
    344 
    345 int fsync(int fildes)
    346 {
    347         futex_down(&vfs_phone_futex);
    348         async_serialize_start();
    349         vfs_connect();
    350        
    351         ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
    352        
    353         async_serialize_end();
    354         futex_up(&vfs_phone_futex);
    355        
    356         return (int) rc;
    357 }
    358 
    359 off_t lseek(int fildes, off_t offset, int whence)
    360 {
    361         ipcarg_t rc;
    362 
    363         futex_down(&vfs_phone_futex);
    364         async_serialize_start();
    365         vfs_connect();
    366        
    367         ipcarg_t newoffs;
    368         rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
    369             &newoffs);
    370 
    371         async_serialize_end();
    372         futex_up(&vfs_phone_futex);
    373 
    374         if (rc != EOK)
    375                 return (off_t) -1;
    376        
    377         return (off_t) newoffs;
    378 }
    379 
    380 int ftruncate(int fildes, off_t length)
    381 {
    382         ipcarg_t rc;
    383        
    384         futex_down(&vfs_phone_futex);
    385         async_serialize_start();
    386         vfs_connect();
    387        
    388         rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
    389         async_serialize_end();
    390         futex_up(&vfs_phone_futex);
    391         return (int) rc;
    392 }
    393 
    394 int fstat(int fildes, struct stat *stat)
    395 {
    396         ipcarg_t rc;
    397         aid_t req;
    398 
    399         futex_down(&vfs_phone_futex);
    400         async_serialize_start();
    401         vfs_connect();
    402        
    403         req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
    404         rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
    405         if (rc != EOK) {
    406                 ipcarg_t rc_orig;
    407                
    408                 async_wait_for(req, &rc_orig);
    409                 async_serialize_end();
    410                 futex_up(&vfs_phone_futex);
    411                 if (rc_orig == EOK)
    412                         return (ssize_t) rc;
    413                 else
    414                         return (ssize_t) rc_orig;
    415         }
    416         async_wait_for(req, &rc);
    417         async_serialize_end();
    418         futex_up(&vfs_phone_futex);
    419 
     533        async_wait_for(req, &rc);
    420534        return rc;
    421535}
    422536
    423 int stat(const char *path, struct stat *stat)
    424 {
    425         ipcarg_t rc;
    426         ipcarg_t rc_orig;
     537DIR *opendir(const char *dirname)
     538{
     539        DIR *dirp = malloc(sizeof(DIR));
     540        if (!dirp)
     541                return NULL;
     542       
     543        size_t abs_size;
     544        char *abs = absolutize(dirname, &abs_size);
     545        if (!abs) {
     546                free(dirp);
     547                return NULL;
     548        }
     549       
     550        int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
     551        free(abs);
     552       
     553        if (ret < 0) {
     554                free(dirp);
     555                return NULL;
     556        }
     557       
     558        dirp->fd = ret;
     559        return dirp;
     560}
     561
     562struct dirent *readdir(DIR *dirp)
     563{
     564        ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
     565        if (len <= 0)
     566                return NULL;
     567        return &dirp->res;
     568}
     569
     570void rewinddir(DIR *dirp)
     571{
     572        (void) lseek(dirp->fd, 0, SEEK_SET);
     573}
     574
     575int closedir(DIR *dirp)
     576{
     577        (void) close(dirp->fd);
     578        free(dirp);
     579        return 0;
     580}
     581
     582int mkdir(const char *path, mode_t mode)
     583{
     584        sysarg_t rc;
    427585        aid_t req;
    428586       
     
    432590                return ENOMEM;
    433591       
    434         futex_down(&vfs_phone_futex);
    435         async_serialize_start();
    436         vfs_connect();
    437        
    438         req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
    439         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
    440         if (rc != EOK) {
    441                 async_wait_for(req, &rc_orig);
    442                 async_serialize_end();
    443                 futex_up(&vfs_phone_futex);
     592        int vfs_phone = vfs_exchange_begin();
     593       
     594        req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
     595        rc = async_data_write_start(vfs_phone, pa, pa_size);
     596        if (rc != EOK) {
     597                vfs_exchange_end(vfs_phone);
    444598                free(pa);
    445                 if (rc_orig == EOK)
    446                         return (int) rc;
    447                 else
    448                         return (int) rc_orig;
    449         }
    450         rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
    451         if (rc != EOK) {
    452                 async_wait_for(req, &rc_orig);
    453                 async_serialize_end();
    454                 futex_up(&vfs_phone_futex);
    455                 free(pa);
    456                 if (rc_orig == EOK)
    457                         return (int) rc;
    458                 else
    459                         return (int) rc_orig;
    460         }
    461         async_wait_for(req, &rc);
    462         async_serialize_end();
    463         futex_up(&vfs_phone_futex);
     599
     600                sysarg_t rc_orig;
     601                async_wait_for(req, &rc_orig);
     602
     603                if (rc_orig == EOK)
     604                        return (int) rc;
     605                else
     606                        return (int) rc_orig;
     607        }
     608        vfs_exchange_end(vfs_phone);
    464609        free(pa);
     610        async_wait_for(req, &rc);
    465611        return rc;
    466612}
    467613
    468 DIR *opendir(const char *dirname)
    469 {
    470         DIR *dirp = malloc(sizeof(DIR));
    471         if (!dirp)
    472                 return NULL;
    473         dirp->fd = _open(dirname, L_DIRECTORY, 0);
    474         if (dirp->fd < 0) {
    475                 free(dirp);
    476                 return NULL;
    477         }
    478         return dirp;
    479 }
    480 
    481 struct dirent *readdir(DIR *dirp)
    482 {
    483         ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
    484         if (len <= 0)
    485                 return NULL;
    486         return &dirp->res;
    487 }
    488 
    489 void rewinddir(DIR *dirp)
    490 {
    491         (void) lseek(dirp->fd, 0, SEEK_SET);
    492 }
    493 
    494 int closedir(DIR *dirp)
    495 {
    496         (void) close(dirp->fd);
    497         free(dirp);
    498         return 0;
    499 }
    500 
    501 int mkdir(const char *path, mode_t mode)
    502 {
    503         ipcarg_t rc;
     614static int _unlink(const char *path, int lflag)
     615{
     616        sysarg_t rc;
    504617        aid_t req;
    505618       
     
    508621        if (!pa)
    509622                return ENOMEM;
    510        
    511         futex_down(&vfs_phone_futex);
    512         async_serialize_start();
    513         vfs_connect();
    514        
    515         req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
    516         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
    517         if (rc != EOK) {
    518                 ipcarg_t rc_orig;
    519        
    520                 async_wait_for(req, &rc_orig);
    521                 async_serialize_end();
    522                 futex_up(&vfs_phone_futex);
     623
     624        int vfs_phone = vfs_exchange_begin();
     625       
     626        req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
     627        rc = async_data_write_start(vfs_phone, pa, pa_size);
     628        if (rc != EOK) {
     629                vfs_exchange_end(vfs_phone);
    523630                free(pa);
    524                 if (rc_orig == EOK)
    525                         return (int) rc;
    526                 else
    527                         return (int) rc_orig;
    528         }
    529         async_wait_for(req, &rc);
    530         async_serialize_end();
    531         futex_up(&vfs_phone_futex);
     631
     632                sysarg_t rc_orig;
     633                async_wait_for(req, &rc_orig);
     634
     635                if (rc_orig == EOK)
     636                        return (int) rc;
     637                else
     638                        return (int) rc_orig;
     639        }
     640        vfs_exchange_end(vfs_phone);
    532641        free(pa);
     642        async_wait_for(req, &rc);
    533643        return rc;
    534644}
    535645
    536 static int _unlink(const char *path, int lflag)
    537 {
    538         ipcarg_t rc;
    539         aid_t req;
    540        
    541         size_t pa_size;
    542         char *pa = absolutize(path, &pa_size);
    543         if (!pa)
    544                 return ENOMEM;
    545 
    546         futex_down(&vfs_phone_futex);
    547         async_serialize_start();
    548         vfs_connect();
    549        
    550         req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
    551         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
    552         if (rc != EOK) {
    553                 ipcarg_t rc_orig;
    554 
    555                 async_wait_for(req, &rc_orig);
    556                 async_serialize_end();
    557                 futex_up(&vfs_phone_futex);
    558                 free(pa);
    559                 if (rc_orig == EOK)
    560                         return (int) rc;
    561                 else
    562                         return (int) rc_orig;
    563         }
    564         async_wait_for(req, &rc);
    565         async_serialize_end();
    566         futex_up(&vfs_phone_futex);
    567         free(pa);
    568         return rc;
    569 }
    570 
    571646int unlink(const char *path)
    572647{
     
    581656int rename(const char *old, const char *new)
    582657{
    583         ipcarg_t rc;
    584         ipcarg_t rc_orig;
     658        sysarg_t rc;
     659        sysarg_t rc_orig;
    585660        aid_t req;
    586661       
     
    597672        }
    598673
    599         futex_down(&vfs_phone_futex);
    600         async_serialize_start();
    601         vfs_connect();
     674        int vfs_phone = vfs_exchange_begin();
    602675       
    603676        req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
    604         rc = ipc_data_write_start(vfs_phone, olda, olda_size);
    605         if (rc != EOK) {
    606                 async_wait_for(req, &rc_orig);
    607                 async_serialize_end();
    608                 futex_up(&vfs_phone_futex);
     677        rc = async_data_write_start(vfs_phone, olda, olda_size);
     678        if (rc != EOK) {
     679                vfs_exchange_end(vfs_phone);
    609680                free(olda);
    610681                free(newa);
    611                 if (rc_orig == EOK)
    612                         return (int) rc;
    613                 else
    614                         return (int) rc_orig;
    615         }
    616         rc = ipc_data_write_start(vfs_phone, newa, newa_size);
    617         if (rc != EOK) {
    618                 async_wait_for(req, &rc_orig);
    619                 async_serialize_end();
    620                 futex_up(&vfs_phone_futex);
     682                async_wait_for(req, &rc_orig);
     683                if (rc_orig == EOK)
     684                        return (int) rc;
     685                else
     686                        return (int) rc_orig;
     687        }
     688        rc = async_data_write_start(vfs_phone, newa, newa_size);
     689        if (rc != EOK) {
     690                vfs_exchange_end(vfs_phone);
    621691                free(olda);
    622692                free(newa);
    623                 if (rc_orig == EOK)
    624                         return (int) rc;
    625                 else
    626                         return (int) rc_orig;
    627         }
    628         async_wait_for(req, &rc);
    629         async_serialize_end();
    630         futex_up(&vfs_phone_futex);
     693                async_wait_for(req, &rc_orig);
     694                if (rc_orig == EOK)
     695                        return (int) rc;
     696                else
     697                        return (int) rc_orig;
     698        }
     699        vfs_exchange_end(vfs_phone);
    631700        free(olda);
    632701        free(newa);
     702        async_wait_for(req, &rc);
    633703        return rc;
    634704}
     
    636706int chdir(const char *path)
    637707{
    638         size_t pa_size;
    639         char *pa = absolutize(path, &pa_size);
    640         if (!pa)
     708        size_t abs_size;
     709        char *abs = absolutize(path, &abs_size);
     710        if (!abs)
    641711                return ENOMEM;
    642 
    643         DIR *d = opendir(pa);
    644         if (!d) {
    645                 free(pa);
     712       
     713        int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
     714       
     715        if (fd < 0) {
     716                free(abs);
    646717                return ENOENT;
    647718        }
    648 
    649         futex_down(&cwd_futex);
    650         if (cwd_dir) {
    651                 closedir(cwd_dir);
    652                 cwd_dir = NULL;
    653                 free(cwd_path);
    654                 cwd_path = NULL;
    655                 cwd_size = 0;
    656         }
    657         cwd_dir = d;
    658         cwd_path = pa;
    659         cwd_size = pa_size;
    660         futex_up(&cwd_futex);
     719       
     720        fibril_mutex_lock(&cwd_mutex);
     721       
     722        if (cwd_fd >= 0)
     723                close(cwd_fd);
     724       
     725       
     726        if (cwd_path)
     727                free(cwd_path);
     728       
     729        cwd_fd = fd;
     730        cwd_path = abs;
     731        cwd_size = abs_size;
     732       
     733        fibril_mutex_unlock(&cwd_mutex);
    661734        return EOK;
    662735}
     
    664737char *getcwd(char *buf, size_t size)
    665738{
    666         if (!size)
     739        if (size == 0)
    667740                return NULL;
    668         futex_down(&cwd_futex);
    669         if (size < cwd_size + 1) {
    670                 futex_up(&cwd_futex);
     741       
     742        fibril_mutex_lock(&cwd_mutex);
     743       
     744        if ((cwd_size == 0) || (size < cwd_size + 1)) {
     745                fibril_mutex_unlock(&cwd_mutex);
    671746                return NULL;
    672747        }
     748       
    673749        str_cpy(buf, size, cwd_path);
    674         futex_up(&cwd_futex);
     750        fibril_mutex_unlock(&cwd_mutex);
     751       
    675752        return buf;
    676753}
     
    683760        rc = fstat(fildes, &stat);
    684761
    685         if (!stat.devfs_stat.device)
     762        if (!stat.device)
    686763                return -1;
    687764       
    688         return devmap_device_connect(stat.devfs_stat.device, 0);
     765        return devmap_device_connect(stat.device, 0);
    689766}
    690767
     
    698775        if (rc == EOK) {
    699776                node->fs_handle = stat.fs_handle;
    700                 node->dev_handle = stat.dev_handle;
     777                node->devmap_handle = stat.devmap_handle;
    701778                node->index = stat.index;
    702779        }
    703780       
    704781        return rc;
     782}
     783
     784int dup2(int oldfd, int newfd)
     785{
     786        int vfs_phone = vfs_exchange_begin();
     787       
     788        sysarg_t ret;
     789        sysarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
     790       
     791        vfs_exchange_end(vfs_phone);
     792       
     793        if (rc == EOK)
     794                return (int) ret;
     795       
     796        return (int) rc;
    705797}
    706798
Note: See TracChangeset for help on using the changeset viewer.