Changeset 1787e527 in mainline for uspace/lib


Ignore:
Timestamp:
2009-11-16T21:22:54Z (17 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
Children:
5ebdf94
Parents:
fcbd1be (diff), 9c70ed6 (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:

merged with head (unstable)

Location:
uspace/lib
Files:
11 added
1 deleted
47 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/libblock/Makefile

    rfcbd1be r1787e527  
    2828#
    2929
    30 ## Common compiler flags
    31 #
     30include Makefile.common
    3231
    33 LIBC_PREFIX = ../libc
     32.PHONY: all clean
    3433
    35 ## Setup toolchain
    36 #
    37 
    38 include $(LIBC_PREFIX)/Makefile.toolchain
    39 
    40 CFLAGS += -Iinclude
    41 
    42 ## Sources
    43 #
    44 
    45 SOURCES = \
    46         libblock.c
    47 
    48 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    49 
    50 .PHONY: all clean depend
    51 
    52 all: libblock.a
    53 
    54 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBC_PREFIX)/libc.a
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5537
    5638clean:
    57         -rm -f libblock.a Makefile.depend
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(LIBBLOCK)
    5840        find . -name '*.o' -follow -exec rm \{\} \;
    59 
    60 depend:
    61         -makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
    62 
    63 libblock.a: depend $(OBJECTS)
    64         $(AR) rc libblock.a $(OBJECTS)
    65 
    66 %.o: %.c
    67         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
  • uspace/lib/libblock/libblock.c

    rfcbd1be r1787e527  
    5050#include <adt/list.h>
    5151#include <adt/hash_table.h>
     52#include <macros.h>
    5253#include <mem.h>
    5354
     
    6263typedef struct {
    6364        fibril_mutex_t lock;
    64         size_t block_size;              /**< Block size. */
     65        size_t lblock_size;             /**< Logical block size. */
    6566        unsigned block_count;           /**< Total number of blocks. */
    6667        unsigned blocks_cached;         /**< Number of cached blocks. */
     
    7475        dev_handle_t dev_handle;
    7576        int dev_phone;
    76         fibril_mutex_t com_area_lock;
    77         void *com_area;
    78         size_t com_size;
     77        fibril_mutex_t comm_area_lock;
     78        void *comm_area;
     79        size_t comm_size;
    7980        void *bb_buf;
    80         off_t bb_off;
    81         size_t bb_size;
     81        bn_t bb_addr;
     82        size_t pblock_size;             /**< Physical block size. */
    8283        cache_t *cache;
    8384} devcon_t;
    8485
    85 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size);
    86 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size);
     86static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
     87static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
     88static int get_block_size(int dev_phone, size_t *bsize);
    8789
    8890static devcon_t *devcon_search(dev_handle_t dev_handle)
     
    102104}
    103105
    104 static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
    105    size_t com_size)
     106static int devcon_add(dev_handle_t dev_handle, int dev_phone, size_t bsize,
     107    void *comm_area, size_t comm_size)
    106108{
    107109        link_t *cur;
    108110        devcon_t *devcon;
     111
     112        if (comm_size < bsize)
     113                return EINVAL;
    109114
    110115        devcon = malloc(sizeof(devcon_t));
     
    115120        devcon->dev_handle = dev_handle;
    116121        devcon->dev_phone = dev_phone;
    117         fibril_mutex_initialize(&devcon->com_area_lock);
    118         devcon->com_area = com_area;
    119         devcon->com_size = com_size;
     122        fibril_mutex_initialize(&devcon->comm_area_lock);
     123        devcon->comm_area = comm_area;
     124        devcon->comm_size = comm_size;
    120125        devcon->bb_buf = NULL;
    121         devcon->bb_off = 0;
    122         devcon->bb_size = 0;
     126        devcon->bb_addr = 0;
     127        devcon->pblock_size = bsize;
    123128        devcon->cache = NULL;
    124129
     
    144149}
    145150
    146 int block_init(dev_handle_t dev_handle, size_t com_size)
     151int block_init(dev_handle_t dev_handle, size_t comm_size)
    147152{
    148153        int rc;
    149154        int dev_phone;
    150         void *com_area;
    151        
    152         com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
     155        void *comm_area;
     156        size_t bsize;
     157
     158        comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
    153159            MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    154         if (!com_area) {
     160        if (!comm_area) {
    155161                return ENOMEM;
    156162        }
     
    158164        dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING);
    159165        if (dev_phone < 0) {
    160                 munmap(com_area, com_size);
     166                munmap(comm_area, comm_size);
    161167                return dev_phone;
    162168        }
    163169
    164         rc = ipc_share_out_start(dev_phone, com_area,
     170        rc = async_share_out_start(dev_phone, comm_area,
    165171            AS_AREA_READ | AS_AREA_WRITE);
    166172        if (rc != EOK) {
    167                 munmap(com_area, com_size);
     173                munmap(comm_area, comm_size);
    168174                ipc_hangup(dev_phone);
    169175                return rc;
    170176        }
    171        
    172         rc = devcon_add(dev_handle, dev_phone, com_area, com_size);
     177
     178        if (get_block_size(dev_phone, &bsize) != EOK) {
     179                munmap(comm_area, comm_size);
     180                ipc_hangup(dev_phone);
     181                return rc;
     182        }
     183       
     184        rc = devcon_add(dev_handle, dev_phone, bsize, comm_area, comm_size);
    173185        if (rc != EOK) {
    174                 munmap(com_area, com_size);
     186                munmap(comm_area, comm_size);
    175187                ipc_hangup(dev_phone);
    176188                return rc;
     
    195207        }
    196208
    197         munmap(devcon->com_area, devcon->com_size);
     209        munmap(devcon->comm_area, devcon->comm_size);
    198210        ipc_hangup(devcon->dev_phone);
    199211
     
    201213}
    202214
    203 int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)
     215int block_bb_read(dev_handle_t dev_handle, bn_t ba)
    204216{
    205217        void *bb_buf;
     
    211223        if (devcon->bb_buf)
    212224                return EEXIST;
    213         bb_buf = malloc(size);
     225        bb_buf = malloc(devcon->pblock_size);
    214226        if (!bb_buf)
    215227                return ENOMEM;
    216        
    217         fibril_mutex_lock(&devcon->com_area_lock);
    218         rc = read_block(devcon, 0, size);
     228
     229        fibril_mutex_lock(&devcon->comm_area_lock);
     230        rc = read_blocks(devcon, 0, 1);
    219231        if (rc != EOK) {
    220                 fibril_mutex_unlock(&devcon->com_area_lock);
     232                fibril_mutex_unlock(&devcon->comm_area_lock);
    221233                free(bb_buf);
    222234                return rc;
    223235        }
    224         memcpy(bb_buf, devcon->com_area, size);
    225         fibril_mutex_unlock(&devcon->com_area_lock);
     236        memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);
     237        fibril_mutex_unlock(&devcon->comm_area_lock);
    226238
    227239        devcon->bb_buf = bb_buf;
    228         devcon->bb_off = off;
    229         devcon->bb_size = size;
     240        devcon->bb_addr = ba;
    230241
    231242        return EOK;
     
    275286        fibril_mutex_initialize(&cache->lock);
    276287        list_initialize(&cache->free_head);
    277         cache->block_size = size;
     288        cache->lblock_size = size;
    278289        cache->block_count = blocks;
    279290        cache->blocks_cached = 0;
    280291        cache->mode = mode;
     292
     293        /* No block size translation a.t.m. */
     294        assert(cache->lblock_size == devcon->pblock_size);
    281295
    282296        if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
     
    306320        b->refcnt = 1;
    307321        b->dirty = false;
     322        b->toxic = false;
    308323        fibril_rwlock_initialize(&b->contents_lock);
    309324        link_initialize(&b->free_link);
     
    313328/** Instantiate a block in memory and get a reference to it.
    314329 *
     330 * @param block                 Pointer to where the function will store the
     331 *                              block pointer on success.
    315332 * @param dev_handle            Device handle of the block device.
    316333 * @param boff                  Block offset.
     
    319336 *                              device.
    320337 *
    321  * @return                      Block structure.
    322  */
    323 block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags)
     338 * @return                      EOK on success or a negative error code.
     339 */
     340int block_get(block_t **block, dev_handle_t dev_handle, bn_t boff, int flags)
    324341{
    325342        devcon_t *devcon;
     
    328345        link_t *l;
    329346        unsigned long key = boff;
    330         bn_t oboff;
     347        int rc;
    331348       
    332349        devcon = devcon_search(dev_handle);
     
    336353       
    337354        cache = devcon->cache;
     355
     356retry:
     357        rc = EOK;
     358        b = NULL;
     359
    338360        fibril_mutex_lock(&cache->lock);
    339361        l = hash_table_find(&cache->block_hash, &key);
     
    346368                if (b->refcnt++ == 0)
    347369                        list_remove(&b->free_link);
     370                if (b->toxic)
     371                        rc = EIO;
    348372                fibril_mutex_unlock(&b->lock);
    349373                fibril_mutex_unlock(&cache->lock);
     
    352376                 * The block was not found in the cache.
    353377                 */
    354                 int rc;
    355                 bool sync = false;
    356 
    357378                if (cache_can_grow(cache)) {
    358379                        /*
     
    364385                        if (!b)
    365386                                goto recycle;
    366                         b->data = malloc(cache->block_size);
     387                        b->data = malloc(cache->lblock_size);
    367388                        if (!b->data) {
    368389                                free(b);
     
    376397                        unsigned long temp_key;
    377398recycle:
    378                         assert(!list_empty(&cache->free_head));
     399                        if (list_empty(&cache->free_head)) {
     400                                fibril_mutex_unlock(&cache->lock);
     401                                rc = ENOMEM;
     402                                goto out;
     403                        }
    379404                        l = cache->free_head.next;
    380                         list_remove(l);
    381405                        b = list_get_instance(l, block_t, free_link);
    382                         sync = b->dirty;
    383                         oboff = b->boff;
     406
     407                        fibril_mutex_lock(&b->lock);
     408                        if (b->dirty) {
     409                                /*
     410                                 * The block needs to be written back to the
     411                                 * device before it changes identity. Do this
     412                                 * while not holding the cache lock so that
     413                                 * concurrency is not impeded. Also move the
     414                                 * block to the end of the free list so that we
     415                                 * do not slow down other instances of
     416                                 * block_get() draining the free list.
     417                                 */
     418                                list_remove(&b->free_link);
     419                                list_append(&b->free_link, &cache->free_head);
     420                                fibril_mutex_unlock(&cache->lock);
     421                                fibril_mutex_lock(&devcon->comm_area_lock);
     422                                memcpy(devcon->comm_area, b->data, b->size);
     423                                rc = write_blocks(devcon, b->boff, 1);
     424                                fibril_mutex_unlock(&devcon->comm_area_lock);
     425                                if (rc != EOK) {
     426                                        /*
     427                                         * We did not manage to write the block
     428                                         * to the device. Keep it around for
     429                                         * another try. Hopefully, we will grab
     430                                         * another block next time.
     431                                         */
     432                                        fibril_mutex_unlock(&b->lock);
     433                                        goto retry;
     434                                }
     435                                b->dirty = false;
     436                                if (!fibril_mutex_trylock(&cache->lock)) {
     437                                        /*
     438                                         * Somebody is probably racing with us.
     439                                         * Unlock the block and retry.
     440                                         */
     441                                        fibril_mutex_unlock(&b->lock);
     442                                        goto retry;
     443                                }
     444
     445                        }
     446                        fibril_mutex_unlock(&b->lock);
     447
     448                        /*
     449                         * Unlink the block from the free list and the hash
     450                         * table.
     451                         */
     452                        list_remove(&b->free_link);
    384453                        temp_key = b->boff;
    385454                        hash_table_remove(&cache->block_hash, &temp_key, 1);
     
    388457                block_initialize(b);
    389458                b->dev_handle = dev_handle;
    390                 b->size = cache->block_size;
     459                b->size = cache->lblock_size;
    391460                b->boff = boff;
    392461                hash_table_insert(&cache->block_hash, &key, &b->hash_link);
     
    394463                /*
    395464                 * Lock the block before releasing the cache lock. Thus we don't
    396                  * kill concurent operations on the cache while doing I/O on the
    397                  * block.
     465                 * kill concurrent operations on the cache while doing I/O on
     466                 * the block.
    398467                 */
    399468                fibril_mutex_lock(&b->lock);
    400469                fibril_mutex_unlock(&cache->lock);
    401470
    402                 if (sync) {
    403                         /*
    404                          * The block is dirty and needs to be written back to
    405                          * the device before we can read in the new contents.
    406                          */
    407                         fibril_mutex_lock(&devcon->com_area_lock);
    408                         memcpy(devcon->com_area, b->data, b->size);
    409                         rc = write_block(devcon, oboff, cache->block_size);
    410                         assert(rc == EOK);
    411                         fibril_mutex_unlock(&devcon->com_area_lock);
    412                 }
    413471                if (!(flags & BLOCK_FLAGS_NOREAD)) {
    414472                        /*
     
    416474                         * the new contents from the device.
    417475                         */
    418                         fibril_mutex_lock(&devcon->com_area_lock);
    419                         rc = read_block(devcon, b->boff, cache->block_size);
    420                         assert(rc == EOK);
    421                         memcpy(b->data, devcon->com_area, cache->block_size);
    422                         fibril_mutex_unlock(&devcon->com_area_lock);
    423                 }
     476                        fibril_mutex_lock(&devcon->comm_area_lock);
     477                        rc = read_blocks(devcon, b->boff, 1);
     478                        memcpy(b->data, devcon->comm_area, cache->lblock_size);
     479                        fibril_mutex_unlock(&devcon->comm_area_lock);
     480                        if (rc != EOK)
     481                                b->toxic = true;
     482                } else
     483                        rc = EOK;
    424484
    425485                fibril_mutex_unlock(&b->lock);
    426486        }
    427         return b;
     487out:
     488        if ((rc != EOK) && b) {
     489                assert(b->toxic);
     490                (void) block_put(b);
     491                b = NULL;
     492        }
     493        *block = b;
     494        return rc;
    428495}
    429496
     
    433500 *
    434501 * @param block         Block of which a reference is to be released.
    435  */
    436 void block_put(block_t *block)
     502 *
     503 * @return              EOK on success or a negative error code.
     504 */
     505int block_put(block_t *block)
    437506{
    438507        devcon_t *devcon = devcon_search(block->dev_handle);
    439508        cache_t *cache;
    440         int rc;
     509        unsigned blocks_cached;
     510        enum cache_mode mode;
     511        int rc = EOK;
    441512
    442513        assert(devcon);
     
    444515
    445516        cache = devcon->cache;
     517
     518retry:
     519        fibril_mutex_lock(&cache->lock);
     520        blocks_cached = cache->blocks_cached;
     521        mode = cache->mode;
     522        fibril_mutex_unlock(&cache->lock);
     523
     524        /*
     525         * Determine whether to sync the block. Syncing the block is best done
     526         * when not holding the cache lock as it does not impede concurrency.
     527         * Since the situation may have changed when we unlocked the cache, the
     528         * blocks_cached and mode variables are mere hints. We will recheck the
     529         * conditions later when the cache lock is held again.
     530         */
     531        fibril_mutex_lock(&block->lock);
     532        if (block->toxic)
     533                block->dirty = false;   /* will not write back toxic block */
     534        if (block->dirty && (block->refcnt == 1) &&
     535            (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) {
     536                fibril_mutex_lock(&devcon->comm_area_lock);
     537                memcpy(devcon->comm_area, block->data, block->size);
     538                rc = write_blocks(devcon, block->boff, 1);
     539                fibril_mutex_unlock(&devcon->comm_area_lock);
     540                block->dirty = false;
     541        }
     542        fibril_mutex_unlock(&block->lock);
     543
    446544        fibril_mutex_lock(&cache->lock);
    447545        fibril_mutex_lock(&block->lock);
     
    449547                /*
    450548                 * Last reference to the block was dropped. Either free the
    451                  * block or put it on the free list.
     549                 * block or put it on the free list. In case of an I/O error,
     550                 * free the block.
    452551                 */
    453                 if (cache->blocks_cached > CACHE_HI_WATERMARK) {
     552                if ((cache->blocks_cached > CACHE_HI_WATERMARK) ||
     553                    (rc != EOK)) {
    454554                        /*
    455                          * Currently there are too many cached blocks.
     555                         * Currently there are too many cached blocks or there
     556                         * was an I/O error when writing the block back to the
     557                         * device.
    456558                         */
    457559                        if (block->dirty) {
    458                                 fibril_mutex_lock(&devcon->com_area_lock);
    459                                 memcpy(devcon->com_area, block->data,
    460                                     block->size);
    461                                 rc = write_block(devcon, block->boff,
    462                                     block->size);
    463                                 assert(rc == EOK);
    464                                 fibril_mutex_unlock(&devcon->com_area_lock);
     560                                /*
     561                                 * We cannot sync the block while holding the
     562                                 * cache lock. Release everything and retry.
     563                                 */
     564                                block->refcnt++;
     565                                fibril_mutex_unlock(&block->lock);
     566                                fibril_mutex_unlock(&cache->lock);
     567                                goto retry;
    465568                        }
    466569                        /*
     
    473576                        cache->blocks_cached--;
    474577                        fibril_mutex_unlock(&cache->lock);
    475                         return;
     578                        return rc;
    476579                }
    477580                /*
    478581                 * Put the block on the free list.
    479582                 */
     583                if (cache->mode != CACHE_MODE_WB && block->dirty) {
     584                        /*
     585                         * We cannot sync the block while holding the cache
     586                         * lock. Release everything and retry.
     587                         */
     588                        block->refcnt++;
     589                        fibril_mutex_unlock(&block->lock);
     590                        fibril_mutex_unlock(&cache->lock);
     591                        goto retry;
     592                }
    480593                list_append(&block->free_link, &cache->free_head);
    481                 if (cache->mode != CACHE_MODE_WB && block->dirty) {
    482                         fibril_mutex_lock(&devcon->com_area_lock);
    483                         memcpy(devcon->com_area, block->data, block->size);
    484                         rc = write_block(devcon, block->boff, block->size);
    485                         assert(rc == EOK);
    486                         fibril_mutex_unlock(&devcon->com_area_lock);
    487 
    488                         block->dirty = false;
    489                 }
    490594        }
    491595        fibril_mutex_unlock(&block->lock);
    492596        fibril_mutex_unlock(&cache->lock);
     597
     598        return rc;
    493599}
    494600
     
    508614 */
    509615int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen,
    510     off_t *pos, void *dst, size_t size, size_t block_size)
     616    off_t *pos, void *dst, size_t size)
    511617{
    512618        off_t offset = 0;
    513619        size_t left = size;
    514         devcon_t *devcon = devcon_search(dev_handle);
    515         assert(devcon);
    516        
    517         fibril_mutex_lock(&devcon->com_area_lock);
     620        size_t block_size;
     621        devcon_t *devcon;
     622
     623        devcon = devcon_search(dev_handle);
     624        assert(devcon);
     625        block_size = devcon->pblock_size;
     626       
     627        fibril_mutex_lock(&devcon->comm_area_lock);
    518628        while (left > 0) {
    519629                size_t rd;
     
    529639                         * destination buffer.
    530640                         */
    531                         memcpy(dst + offset, devcon->com_area + *bufpos, rd);
     641                        memcpy(dst + offset, devcon->comm_area + *bufpos, rd);
    532642                        offset += rd;
    533643                        *bufpos += rd;
     
    540650                        int rc;
    541651
    542                         rc = read_block(devcon, *pos / block_size, block_size);
     652                        rc = read_blocks(devcon, *pos / block_size, 1);
    543653                        if (rc != EOK) {
    544                                 fibril_mutex_unlock(&devcon->com_area_lock);
     654                                fibril_mutex_unlock(&devcon->comm_area_lock);
    545655                                return rc;
    546656                        }
     
    550660                }
    551661        }
    552         fibril_mutex_unlock(&devcon->com_area_lock);
     662        fibril_mutex_unlock(&devcon->comm_area_lock);
    553663       
    554664        return EOK;
    555665}
    556666
    557 /** Read block from block device.
     667/** Read blocks directly from device (bypass cache).
     668 *
     669 * @param dev_handle    Device handle of the block device.
     670 * @param ba            Address of first block.
     671 * @param cnt           Number of blocks.
     672 * @param src           Buffer for storing the data.
     673 *
     674 * @return              EOK on success or negative error code on failure.
     675 */
     676int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf)
     677{
     678        devcon_t *devcon;
     679        int rc;
     680
     681        devcon = devcon_search(dev_handle);
     682        assert(devcon);
     683       
     684        fibril_mutex_lock(&devcon->comm_area_lock);
     685
     686        rc = read_blocks(devcon, ba, cnt);
     687        if (rc == EOK)
     688                memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt);
     689
     690        fibril_mutex_unlock(&devcon->comm_area_lock);
     691
     692        return rc;
     693}
     694
     695/** Write blocks directly to device (bypass cache).
     696 *
     697 * @param dev_handle    Device handle of the block device.
     698 * @param ba            Address of first block.
     699 * @param cnt           Number of blocks.
     700 * @param src           The data to be written.
     701 *
     702 * @return              EOK on success or negative error code on failure.
     703 */
     704int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt,
     705    const void *data)
     706{
     707        devcon_t *devcon;
     708        int rc;
     709
     710        devcon = devcon_search(dev_handle);
     711        assert(devcon);
     712       
     713        fibril_mutex_lock(&devcon->comm_area_lock);
     714
     715        memcpy(devcon->comm_area, data, devcon->pblock_size * cnt);
     716        rc = read_blocks(devcon, ba, cnt);
     717
     718        fibril_mutex_unlock(&devcon->comm_area_lock);
     719
     720        return rc;
     721}
     722
     723/** Get device block size.
     724 *
     725 * @param dev_handle    Device handle of the block device.
     726 * @param bsize         Output block size.
     727 *
     728 * @return              EOK on success or negative error code on failure.
     729 */
     730int block_get_bsize(dev_handle_t dev_handle, size_t *bsize)
     731{
     732        devcon_t *devcon;
     733
     734        devcon = devcon_search(dev_handle);
     735        assert(devcon);
     736       
     737        return get_block_size(devcon->dev_phone, bsize);
     738}
     739
     740/** Read blocks from block device.
    558741 *
    559742 * @param devcon        Device connection.
    560  * @param boff          Block index.
    561  * @param block_size    Block size.
     743 * @param ba            Address of first block.
     744 * @param cnt           Number of blocks.
    562745 * @param src           Buffer for storing the data.
    563746 *
    564747 * @return              EOK on success or negative error code on failure.
    565748 */
    566 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size)
    567 {
    568         ipcarg_t retval;
     749static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     750{
    569751        int rc;
    570752
    571753        assert(devcon);
    572         rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size,
    573             &retval);
    574         if ((rc != EOK) || (retval != EOK))
    575                 return (rc != EOK ? rc : (int) retval);
    576 
    577         return EOK;
     754        rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
     755            UPPER32(ba), cnt);
     756        return rc;
    578757}
    579758
     
    581760 *
    582761 * @param devcon        Device connection.
    583  * @param boff          Block index.
    584  * @param block_size    Block size.
     762 * @param ba            Address of first block.
     763 * @param cnt           Number of blocks.
    585764 * @param src           Buffer containing the data to write.
    586765 *
    587766 * @return              EOK on success or negative error code on failure.
    588767 */
    589 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size)
    590 {
    591         ipcarg_t retval;
     768static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
     769{
    592770        int rc;
    593771
    594772        assert(devcon);
    595         rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size,
    596             &retval);
    597         if ((rc != EOK) || (retval != EOK))
    598                 return (rc != EOK ? rc : (int) retval);
    599 
    600         return EOK;
     773        rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
     774            UPPER32(ba), cnt);
     775        return rc;
     776}
     777
     778/** Get block size used by the device. */
     779static int get_block_size(int dev_phone, size_t *bsize)
     780{
     781        ipcarg_t bs;
     782        int rc;
     783
     784        rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
     785        if (rc == EOK)
     786                *bsize = (size_t) bs;
     787
     788        return rc;
    601789}
    602790
  • uspace/lib/libblock/libblock.h

    rfcbd1be r1787e527  
    6060#define BLOCK_FLAGS_NOREAD      1
    6161
    62 typedef unsigned bn_t;  /**< Block number type. */
     62typedef uint64_t bn_t;  /**< Block number type. */
    6363
    6464typedef struct block {
     
    6969        /** If true, the block needs to be written back to the block device. */
    7070        bool dirty;
     71        /** If true, the blcok does not contain valid data. */
     72        bool toxic;
    7173        /** Readers / Writer lock protecting the contents of the block. */
    7274        fibril_rwlock_t contents_lock;
     
    9698extern void block_fini(dev_handle_t);
    9799
    98 extern int block_bb_read(dev_handle_t, off_t, size_t);
     100extern int block_bb_read(dev_handle_t, bn_t);
    99101extern void *block_bb_get(dev_handle_t);
    100102
    101103extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode);
    102104
    103 extern block_t *block_get(dev_handle_t, bn_t, int);
    104 extern void block_put(block_t *);
     105extern int block_get(block_t **, dev_handle_t, bn_t, int);
     106extern int block_put(block_t *);
    105107
    106108extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *,
    107     size_t, size_t);
     109    size_t);
     110
     111extern int block_get_bsize(dev_handle_t, size_t *);
     112extern int block_read_direct(dev_handle_t, bn_t, size_t, void *);
     113extern int block_write_direct(dev_handle_t, bn_t, size_t, const void *);
    108114
    109115#endif
  • uspace/lib/libc/Makefile

    rfcbd1be r1787e527  
    2727#
    2828
    29 ## Common compiler flags
    30 #
     29include Makefile.common
    3130
    32 LIBC_PREFIX = $(shell pwd)
    33 SOFTINT_PREFIX = ../softint
     31.PHONY: all clean
    3432
    35 
    36 ## Setup toolchain
    37 #
    38 
    39 include $(LIBC_PREFIX)/Makefile.toolchain
    40 
    41 
    42 ## Sources
    43 #
    44 
    45 GENERIC_SOURCES = \
    46         generic/libc.c \
    47         generic/ddi.c \
    48         generic/as.c \
    49         generic/cap.c \
    50         generic/devmap.c \
    51         generic/event.c \
    52         generic/errno.c \
    53         generic/mem.c \
    54         generic/string.c \
    55         generic/fibril.c \
    56         generic/fibril_sync.c \
    57         generic/pcb.c \
    58         generic/smc.c \
    59         generic/thread.c \
    60         generic/tls.c \
    61         generic/task.c \
    62         generic/futex.c \
    63         generic/io/asprintf.c \
    64         generic/io/io.c \
    65         generic/io/printf.c \
    66         generic/io/klog.c \
    67         generic/io/snprintf.c \
    68         generic/io/vprintf.c \
    69         generic/io/vsnprintf.c \
    70         generic/io/printf_core.c \
    71         generic/io/console.c \
    72         generic/malloc.c \
    73         generic/sysinfo.c \
    74         generic/ipc.c \
    75         generic/async.c \
    76         generic/loader.c \
    77         generic/getopt.c \
    78         generic/adt/list.o \
    79         generic/adt/hash_table.o \
    80         generic/time.c \
    81         generic/err.c \
    82         generic/stdlib.c \
    83         generic/mman.c \
    84         generic/udebug.c \
    85         generic/vfs/vfs.c \
    86         generic/vfs/canonify.c
    87 
    88 ARCH_SOURCES += \
    89         arch/$(UARCH)/src/entry.s \
    90         arch/$(UARCH)/src/thread_entry.s
    91 
    92 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
    93 ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
    94 OBJECTS := $(GENERIC_OBJECTS) $(ARCH_OBJECTS)
    95 
    96 .PHONY: all clean depend kerninc
    97 
    98 all: kerninc libc.a arch/$(UARCH)/_link.ld
    99 
    100 kerninc:
    101         ln -sfn ../../../../kernel/generic/include include/kernel
    102         ln -sfn kernel/arch include/arch
    103         ln -sfn ../arch/$(UARCH)/include include/libarch
    104 
    105 -include Makefile.depend
     33all: ../../../Makefile.config ../../../config.h ../../../config.defs
     34        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     35        $(MAKE) -f Makefile.build
    10636
    10737clean:
    108         -rm -f include/kernel include/arch include/libarch libc.a arch/$(UARCH)/_link.ld Makefile.depend
    109         find generic/ arch/$(UARCH)/ -name '*.o' -follow -exec rm \{\} \;
    110 
    111 depend: kerninc
    112         -makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
    113 
    114 libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
    115         $(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
    116 
    117 arch/$(UARCH)/_link.ld: arch/$(UARCH)/_link.ld.in
    118         $(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
    119 
    120 %.o: %.S
    121         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    122 
    123 %.o: %.s
    124         $(AS) $(AFLAGS) $< -o $@
    125 
    126 %.o: %.c
    127         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     38        rm -f $(DEPEND) $(DEPEND_PREV) $(INCLUDE_KERNEL) $(INCLUDE_ARCH) $(INCLUDE_LIBARCH) $(LIBC) arch/*/_link.ld
     39        find generic/ arch/*/ -name '*.o' -follow -exec rm \{\} \;
  • uspace/lib/libc/Makefile.toolchain

    rfcbd1be r1787e527  
    2727#
    2828
    29 CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
     29GCC_CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
    3030        -fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
    31         -finput-charset=UTF-8 -fno-builtin -Wall -Wextra -Wno-unused-parameter \
    32         -Wmissing-prototypes -Werror-implicit-function-declaration -nostdlib \
    33         -nostdinc -pipe -g -D__$(ENDIANESS)__
     31        -finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
     32        -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
     33        -Werror-implicit-function-declaration -pipe -g -D__$(ENDIANESS)__
     34
     35ICC_CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
     36        -fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
     37        -finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
     38        -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
     39        -Werror-implicit-function-declaration -pipe -g -D__$(ENDIANESS)__
     40
     41CLANG_CFLAGS = -I$(LIBC_PREFIX)/include -O3 -imacros $(LIBC_PREFIX)/../../../config.h \
     42        -fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
     43        -finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
     44        -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
     45        -Werror-implicit-function-declaration -pipe -g -arch $(CLANG_ARCH) \
     46        -D__$(ENDIANESS)__
     47
    3448LFLAGS = -M -N $(SOFTINT_PREFIX)/libsoftint.a
    3549AFLAGS =
     
    4559#
    4660
    47 -include $(LIBC_PREFIX)/../../../Makefile.config
    48 -include $(LIBC_PREFIX)/../../../config.defs
    49 -include $(LIBC_PREFIX)/arch/$(UARCH)/Makefile.inc
     61include $(LIBC_PREFIX)/../../../Makefile.config
     62include $(LIBC_PREFIX)/../../../config.defs
     63include $(LIBC_PREFIX)/arch/$(UARCH)/Makefile.inc
    5064
    5165## Simple detection of the host system
     
    6478#
    6579
     80ifeq ($(COMPILER),gcc_cross)
     81        CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc
     82        GCC = $(CC)
     83        AS = $(TOOLCHAIN_DIR)/$(TARGET)-as
     84        LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld
     85        AR = $(TOOLCHAIN_DIR)/$(TARGET)-ar
     86        OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy
     87        OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
     88        CFLAGS = $(GCC_CFLAGS)
     89        DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
     90endif
     91
    6692ifeq ($(COMPILER),gcc_native)
    6793        CC = gcc
     94        GCC = $(CC)
    6895        AS = $(BINUTILS_PREFIX)as
    6996        LD = $(BINUTILS_PREFIX)ld
     
    7198        OBJCOPY = $(BINUTILS_PREFIX)objcopy
    7299        OBJDUMP = $(BINUTILS_PREFIX)objdump
     100        CFLAGS = $(GCC_CFLAGS)
    73101        DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
    74102endif
    75103
    76 ifeq ($(COMPILER),icc_native)
     104ifeq ($(COMPILER),icc)
    77105        CC = icc
     106        GCC = gcc
    78107        AS = as
    79108        LD = ld
     
    81110        OBJCOPY = objcopy
    82111        OBJDUMP = objdump
     112        CFLAGS = $(ICC_CFLAGS)
    83113        DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
    84114endif
    85115
    86 ifeq ($(COMPILER),gcc_cross)
    87         CC = $(TOOLCHAIN_DIR)/$(TARGET)-gcc
    88         AS = $(TOOLCHAIN_DIR)/$(TARGET)-as
    89         LD = $(TOOLCHAIN_DIR)/$(TARGET)-ld
    90         AR = $(TOOLCHAIN_DIR)/$(TARGET)-ar
    91         OBJCOPY = $(TOOLCHAIN_DIR)/$(TARGET)-objcopy
    92         OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
     116ifeq ($(COMPILER),clang)
     117        CC = clang
     118        GCC = gcc
     119        AS = $(BINUTILS_PREFIX)as
     120        LD = $(BINUTILS_PREFIX)ld
     121        AR = $(BINUTILS_PREFIX)ar
     122        OBJCOPY = $(BINUTILS_PREFIX)objcopy
     123        OBJDUMP = $(BINUTILS_PREFIX)objdump
     124        CFLAGS = $(CLANG_CFLAGS)
    93125        DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
    94126endif
  • uspace/lib/libc/arch/amd64/Makefile.inc

    rfcbd1be r1787e527  
    3131
    3232TARGET = amd64-linux-gnu
     33CLANG_ARCH = x86_64
    3334TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin
    3435
  • uspace/lib/libc/arch/arm32/Makefile.inc

    rfcbd1be r1787e527  
    3232
    3333TARGET = arm-linux-gnu
    34 TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
     34TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm32/bin
    3535
    3636ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
     
    3939        arch/$(UARCH)/src/eabi.S
    4040
    41 CFLAGS += -ffixed-r9 -mtp=soft
     41GCC_CFLAGS += -ffixed-r9 -mtp=soft
    4242LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
    4343
  • uspace/lib/libc/arch/ia32/Makefile.inc

    rfcbd1be r1787e527  
    3131
    3232TARGET = i686-pc-linux-gnu
    33 TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin
     33CLANG_ARCH = i386
     34TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia32/bin
    3435
    3536ARCH_SOURCES += arch/$(UARCH)/src/syscall.S \
  • uspace/lib/libc/arch/ia32/_link.ld.in

    rfcbd1be r1787e527  
    33
    44PHDRS {
    5         text PT_LOAD FLAGS(5);
     5        text PT_LOAD FLAGS(5);
    66        data PT_LOAD FLAGS(6);
    77}
     
    99SECTIONS {
    1010        . = 0x1000 + SIZEOF_HEADERS;
    11 
     11       
    1212        .init : {
    1313                *(.init);
    1414        } :text
     15       
    1516        .text : {
    1617                *(.text);
    17                 *(.rodata*);
     18                *(.rodata*);
    1819        } :text
    19 
     20       
    2021        . = . + 0x1000;
    21 
     22       
    2223        .data : {
    2324                *(.data);
    2425        } :data
     26       
    2527        .tdata : {
    2628                _tdata_start = .;
    2729                *(.tdata);
     30                *(.gnu.linkonce.tb.*);
    2831                _tdata_end = .;
    2932                _tbss_start = .;
     
    3134                _tbss_end = .;
    3235        } :data
     36       
    3337        _tls_alignment = ALIGNOF(.tdata);
     38       
    3439        .bss : {
    35                 *(COMMON);
    36                 *(.bss);
     40                *(COMMON);
     41                *(.bss);
    3742        } :data
    3843       
    3944        . = ALIGN(0x1000);
     45       
    4046        _heap = .;
    4147       
     
    4349                *(*);
    4450        }
    45 
    4651}
  • uspace/lib/libc/arch/ia32/include/syscall.h

    rfcbd1be r1787e527  
    4040#include <kernel/syscall/syscall.h>
    4141
    42 #define __syscall0      __syscall_sysenter
    43 #define __syscall1      __syscall_sysenter
    44 #define __syscall2      __syscall_sysenter
    45 #define __syscall3      __syscall_sysenter
    46 #define __syscall4      __syscall_sysenter
    47 #define __syscall5      __syscall_int
    48 #define __syscall6      __syscall_int
     42#define __syscall0      __syscall_fast_func
     43#define __syscall1      __syscall_fast_func
     44#define __syscall2      __syscall_fast_func
     45#define __syscall3      __syscall_fast_func
     46#define __syscall4      __syscall_fast_func
     47#define __syscall5      __syscall_slow
     48#define __syscall6      __syscall_slow
    4949
    5050extern sysarg_t
    51 __syscall_sysenter(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
    52     const sysarg_t, const sysarg_t, const syscall_t);
     51(* __syscall_fast_func)(const sysarg_t, const sysarg_t, const sysarg_t,
     52    const sysarg_t, const sysarg_t, const sysarg_t, const syscall_t);
    5353
    5454extern sysarg_t
    55 __syscall_int(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
    56      const sysarg_t, const sysarg_t, const syscall_t);
     55__syscall_slow(const sysarg_t, const sysarg_t, const sysarg_t, const sysarg_t,
     56    const sysarg_t, const sysarg_t, const syscall_t);
    5757
    5858#endif
  • uspace/lib/libc/arch/ia32/src/entry.s

    rfcbd1be r1787e527  
    2727#
    2828
     29INTEL_CPUID_STANDARD = 1
     30INTEL_SEP = 11
     31
    2932.section .init, "ax"
    3033
     
    3538## User-space task entry point
    3639#
    37 # %ebx contains the PCB pointer
     40# %edi contains the PCB pointer
    3841#
    3942__entry:
     
    4447        # Do not set %gs, it contains descriptor that can see TLS
    4548
     49        # Detect the mechanism used for making syscalls
     50        movl $(INTEL_CPUID_STANDARD), %eax
     51        cpuid
     52        bt $(INTEL_SEP), %edx
     53        jnc 0f
     54        leal __syscall_fast_func, %eax
     55        movl $__syscall_fast, (%eax)
     560:
     57
    4658        # Pass the PCB pointer to __main as the first argument
    47         pushl %ebx
     59        pushl %edi
    4860        call __main
    4961
  • uspace/lib/libc/arch/ia32/src/syscall.S

    rfcbd1be r1787e527  
    2727#
    2828
     29.data
     30
     31.global __syscall_fast_func
     32__syscall_fast_func:
     33        .long __syscall_slow
     34
    2935.text
    3036
     
    3541 * could benefit from this and not save unused registers on the stack.
    3642 */
    37 .global __syscall_int
    38 __syscall_int:
     43.global __syscall_slow
     44__syscall_slow:
    3945        pushl %ebx
    4046        pushl %esi
     
    6470 * segment, otherwise the SYSENTER wouldn't work in the first place).
    6571 */
    66 .global __syscall_sysenter
    67 __syscall_sysenter:
     72.global __syscall_fast
     73__syscall_fast:
    6874        pushl %ebx
    6975        pushl %esi
  • uspace/lib/libc/arch/ia64/Makefile.inc

    rfcbd1be r1787e527  
    3838        arch/$(UARCH)/src/ddi.c
    3939
    40 CFLAGS += -fno-unwind-tables
     40GCC_CFLAGS += -fno-unwind-tables
    4141LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
    4242
  • uspace/lib/libc/arch/ia64/include/atomic.h

    rfcbd1be r1787e527  
    2727 */
    2828
    29 /** @addtogroup libcia64       
     29/** @addtogroup libcia64
    3030 * @{
    3131 */
     
    3636#define LIBC_ia64_ATOMIC_H_
    3737
    38 /** Atomic addition.
    39  *
    40  * @param val Atomic value.
    41  * @param imm Value to add.
    42  *
    43  * @return Value before addition.
    44  */
    45 static inline long atomic_add(atomic_t *val, int imm)
     38static inline void atomic_inc(atomic_t *val)
    4639{
    4740        long v;
     41       
     42        asm volatile (
     43                "fetchadd8.rel %[v] = %[count], 1\n"
     44                : [v] "=r" (v),
     45                  [count] "+m" (val->count)
     46        );
     47}
    4848
    49         asm volatile ("fetchadd8.rel %0 = %1, %2\n" : "=r" (v), "+m" (val->count) : "i" (imm));
    50  
     49static inline void atomic_dec(atomic_t *val)
     50{
     51        long v;
     52       
     53        asm volatile (
     54                "fetchadd8.rel %[v] = %[count], -1\n"
     55                : [v] "=r" (v),
     56                  [count] "+m" (val->count)
     57        );
     58}
     59
     60static inline long atomic_preinc(atomic_t *val)
     61{
     62        long v;
     63       
     64        asm volatile (
     65                "fetchadd8.rel %[v] = %[count], 1\n"
     66                : [v] "=r" (v),
     67                  [count] "+m" (val->count)
     68        );
     69       
     70        return (v + 1);
     71}
     72
     73static inline long atomic_predec(atomic_t *val)
     74{
     75        long v;
     76       
     77        asm volatile (
     78                "fetchadd8.rel %[v] = %[count], -1\n"
     79                : [v] "=r" (v),
     80                  [count] "+m" (val->count)
     81        );
     82       
     83        return (v - 1);
     84}
     85
     86static inline long atomic_postinc(atomic_t *val)
     87{
     88        long v;
     89       
     90        asm volatile (
     91                "fetchadd8.rel %[v] = %[count], 1\n"
     92                : [v] "=r" (v),
     93                  [count] "+m" (val->count)
     94        );
     95       
    5196        return v;
    5297}
    5398
    54 static inline void atomic_inc(atomic_t *val) { atomic_add(val, 1); }
    55 static inline void atomic_dec(atomic_t *val) { atomic_add(val, -1); }
    56 
    57 static inline long atomic_preinc(atomic_t *val) { return atomic_add(val, 1) + 1; }
    58 static inline long atomic_predec(atomic_t *val) { return atomic_add(val, -1) - 1; }
    59 
    60 static inline long atomic_postinc(atomic_t *val) { return atomic_add(val, 1); }
    61 static inline long atomic_postdec(atomic_t *val) { return atomic_add(val, -1); }
     99static inline long atomic_postdec(atomic_t *val)
     100{
     101        long v;
     102       
     103        asm volatile (
     104                "fetchadd8.rel %[v] = %[count], -1\n"
     105                : [v] "=r" (v),
     106                  [count] "+m" (val->count)
     107        );
     108       
     109        return v;
     110}
    62111
    63112#endif
  • uspace/lib/libc/arch/mips32/Makefile.inc

    rfcbd1be r1787e527  
    3131
    3232TARGET = mipsel-linux-gnu
    33 TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
     33TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips32/bin
    3434
    3535ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
     
    3737        arch/$(UARCH)/src/tls.c
    3838
    39 CFLAGS += -mips3
     39GCC_CFLAGS += -mips3
    4040
    4141ENDIANESS = LE
  • uspace/lib/libc/arch/mips32eb/Makefile.inc

    rfcbd1be r1787e527  
    3131
    3232TARGET = mips-linux-gnu
    33 TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
     33TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips32eb/bin
    3434
    3535ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
    36                 arch/$(UARCH)/src/fibril.S \
    37                 arch/$(UARCH)/src/tls.c
     36        arch/$(UARCH)/src/fibril.S \
     37        arch/$(UARCH)/src/tls.c
    3838
    39 CFLAGS += -mips3
     39GCC_CFLAGS += -mips3
    4040LFLAGS += -N
    4141
  • uspace/lib/libc/arch/ppc32/Makefile.inc

    rfcbd1be r1787e527  
    3131
    3232TARGET = ppc-linux-gnu
    33 TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin
     33TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc32/bin
    3434
    3535ARCH_SOURCES += arch/$(UARCH)/src/syscall.c \
     
    3737        arch/$(UARCH)/src/tls.c
    3838
    39 CFLAGS += -mcpu=powerpc -msoft-float -m32
     39GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32
    4040AFLAGS += -a32
    4141LFLAGS += -N
  • uspace/lib/libc/arch/sparc64/Makefile.inc

    rfcbd1be r1787e527  
    3636        arch/$(UARCH)/src/tls.c
    3737
    38 CFLAGS += -mcpu=ultrasparc -m64
     38GCC_CFLAGS += -mcpu=ultrasparc -m64
    3939LFLAGS += -no-check-sections -N
    4040
  • uspace/lib/libc/generic/async.c

    rfcbd1be r1787e527  
    8383 *
    8484 *     callid = async_get_call(&call);
    85  *     handle_call(callid, call);
     85 *     somehow_handle_the_call(callid, call);
    8686 *     ipc_answer_2(callid, 1, 2, 3);
    8787 *
     
    9494#include <futex.h>
    9595#include <async.h>
     96#include <async_priv.h>
    9697#include <fibril.h>
    9798#include <stdio.h>
     
    107108atomic_t async_futex = FUTEX_INITIALIZER;
    108109
    109 /** Structures of this type represent a waiting fibril. */
    110 typedef struct {
    111         /** Expiration time. */
    112         struct timeval expires;
    113        
    114         /** If true, this struct is in the timeout list. */
    115         bool inlist;
    116        
    117         /** Timeout list link. */
    118         link_t link;
    119        
    120         /** Identification of and link to the waiting fibril. */
    121         fid_t fid;
    122        
    123         /** If true, this fibril is currently active. */
    124         bool active;
    125        
    126         /** If true, we have timed out. */
    127         bool timedout;
    128 } awaiter_t;
     110/** Number of threads waiting for IPC in the kernel. */
     111atomic_t threads_in_ipc_wait = { 0 };
    129112
    130113typedef struct {
     
    250233 *
    251234 */
    252 static void insert_timeout(awaiter_t *wd)
    253 {
    254         wd->timedout = false;
    255         wd->inlist = true;
     235void async_insert_timeout(awaiter_t *wd)
     236{
     237        wd->to_event.occurred = false;
     238        wd->to_event.inlist = true;
    256239       
    257240        link_t *tmp = timeout_list.next;
    258241        while (tmp != &timeout_list) {
    259                 awaiter_t *cur = list_get_instance(tmp, awaiter_t, link);
    260                
    261                 if (tv_gteq(&cur->expires, &wd->expires))
     242                awaiter_t *cur;
     243               
     244                cur = list_get_instance(tmp, awaiter_t, to_event.link);
     245                if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires))
    262246                        break;
    263                
    264247                tmp = tmp->next;
    265248        }
    266249       
    267         list_append(&wd->link, tmp);
     250        list_append(&wd->to_event.link, tmp);
    268251}
    269252
     
    312295               
    313296                /* If in timeout list, remove it */
    314                 if (conn->wdata.inlist) {
    315                         conn->wdata.inlist = false;
    316                         list_remove(&conn->wdata.link);
     297                if (conn->wdata.to_event.inlist) {
     298                        conn->wdata.to_event.inlist = false;
     299                        list_remove(&conn->wdata.to_event.link);
    317300                }
    318301               
     
    402385       
    403386        if (usecs) {
    404                 gettimeofday(&conn->wdata.expires, NULL);
    405                 tv_add(&conn->wdata.expires, usecs);
     387                gettimeofday(&conn->wdata.to_event.expires, NULL);
     388                tv_add(&conn->wdata.to_event.expires, usecs);
    406389        } else
    407                 conn->wdata.inlist = false;
     390                conn->wdata.to_event.inlist = false;
    408391       
    409392        /* If nothing in queue, wait until something arrives */
    410393        while (list_empty(&conn->msg_queue)) {
    411394                if (usecs)
    412                         insert_timeout(&conn->wdata);
     395                        async_insert_timeout(&conn->wdata);
    413396               
    414397                conn->wdata.active = false;
     
    427410                 */
    428411                futex_down(&async_futex);
    429                 if ((usecs) && (conn->wdata.timedout)
     412                if ((usecs) && (conn->wdata.to_event.occurred)
    430413                    && (list_empty(&conn->msg_queue))) {
    431414                        /* If we timed out -> exit */
     
    622605        link_t *cur = timeout_list.next;
    623606        while (cur != &timeout_list) {
    624                 awaiter_t *waiter = list_get_instance(cur, awaiter_t, link);
    625                
    626                 if (tv_gt(&waiter->expires, &tv))
     607                awaiter_t *waiter;
     608               
     609                waiter = list_get_instance(cur, awaiter_t, to_event.link);
     610                if (tv_gt(&waiter->to_event.expires, &tv))
    627611                        break;
    628                
     612
    629613                cur = cur->next;
    630                
    631                 list_remove(&waiter->link);
    632                 waiter->inlist = false;
    633                 waiter->timedout = true;
     614
     615                list_remove(&waiter->to_event.link);
     616                waiter->to_event.inlist = false;
     617                waiter->to_event.occurred = true;
    634618               
    635619                /*
     
    668652                if (!list_empty(&timeout_list)) {
    669653                        awaiter_t *waiter = list_get_instance(timeout_list.next,
    670                             awaiter_t, link);
     654                            awaiter_t, to_event.link);
    671655                       
    672656                        struct timeval tv;
    673657                        gettimeofday(&tv, NULL);
    674658                       
    675                         if (tv_gteq(&tv, &waiter->expires)) {
     659                        if (tv_gteq(&tv, &waiter->to_event.expires)) {
    676660                                futex_up(&async_futex);
    677661                                handle_expired_timeouts();
    678662                                continue;
    679663                        } else
    680                                 timeout = tv_sub(&waiter->expires, &tv);
     664                                timeout = tv_sub(&waiter->to_event.expires,
     665                                    &tv);
    681666                } else
    682667                        timeout = SYNCH_NO_TIMEOUT;
    683668               
    684669                futex_up(&async_futex);
     670
     671                atomic_inc(&threads_in_ipc_wait);
    685672               
    686673                ipc_call_t call;
     
    688675                    SYNCH_FLAGS_NONE);
    689676               
     677                atomic_dec(&threads_in_ipc_wait);
     678
    690679                if (!callid) {
    691680                        handle_expired_timeouts();
     
    775764       
    776765        /* Remove message from timeout list */
    777         if (msg->wdata.inlist)
    778                 list_remove(&msg->wdata.link);
     766        if (msg->wdata.to_event.inlist)
     767                list_remove(&msg->wdata.to_event.link);
    779768       
    780769        msg->done = true;
     
    815804        msg->dataptr = dataptr;
    816805       
    817         msg->wdata.inlist = false;
     806        msg->wdata.to_event.inlist = false;
    818807        /* We may sleep in the next method, but it will use its own mechanism */
    819808        msg->wdata.active = true;
     
    855844        msg->dataptr = dataptr;
    856845       
    857         msg->wdata.inlist = false;
     846        msg->wdata.to_event.inlist = false;
    858847        /* We may sleep in next method, but it will use its own mechanism */
    859848        msg->wdata.active = true;
     
    884873        msg->wdata.fid = fibril_get_id();
    885874        msg->wdata.active = false;
    886         msg->wdata.inlist = false;
     875        msg->wdata.to_event.inlist = false;
    887876       
    888877        /* Leave the async_futex locked when entering this function */
     
    922911        }
    923912       
    924         gettimeofday(&msg->wdata.expires, NULL);
    925         tv_add(&msg->wdata.expires, timeout);
     913        gettimeofday(&msg->wdata.to_event.expires, NULL);
     914        tv_add(&msg->wdata.to_event.expires, timeout);
    926915       
    927916        msg->wdata.fid = fibril_get_id();
    928917        msg->wdata.active = false;
    929         insert_timeout(&msg->wdata);
     918        async_insert_timeout(&msg->wdata);
    930919       
    931920        /* Leave the async_futex locked when entering this function */
     
    963952        msg->wdata.active = false;
    964953       
    965         gettimeofday(&msg->wdata.expires, NULL);
    966         tv_add(&msg->wdata.expires, timeout);
     954        gettimeofday(&msg->wdata.to_event.expires, NULL);
     955        tv_add(&msg->wdata.to_event.expires, timeout);
    967956       
    968957        futex_down(&async_futex);
    969958       
    970         insert_timeout(&msg->wdata);
     959        async_insert_timeout(&msg->wdata);
    971960       
    972961        /* Leave the async_futex locked when entering this function */
     
    10981087}
    10991088
     1089/** Wrapper for making IPC_M_SHARE_IN calls using the async framework.
     1090 *
     1091 * @param phoneid       Phone that will be used to contact the receiving side.
     1092 * @param dst           Destination address space area base.
     1093 * @param size          Size of the destination address space area.
     1094 * @param arg           User defined argument.
     1095 * @param flags         Storage where the received flags will be stored. Can be
     1096 *                      NULL.
     1097 *
     1098 * @return              Zero on success or a negative error code from errno.h.
     1099 */
     1100int async_share_in_start(int phoneid, void *dst, size_t size, ipcarg_t arg,
     1101    int *flags)
     1102{
     1103        int res;
     1104        sysarg_t tmp_flags;
     1105        res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
     1106            (ipcarg_t) size, arg, NULL, &tmp_flags);
     1107        if (flags)
     1108                *flags = tmp_flags;
     1109        return res;
     1110}
     1111
     1112/** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework.
     1113 *
     1114 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
     1115 * so that the user doesn't have to remember the meaning of each IPC argument.
     1116 *
     1117 * So far, this wrapper is to be used from within a connection fibril.
     1118 *
     1119 * @param callid        Storage where the hash of the IPC_M_SHARE_IN call will
     1120 *                      be stored.
     1121 * @param size          Destination address space area size.   
     1122 *
     1123 * @return              Non-zero on success, zero on failure.
     1124 */
     1125int async_share_in_receive(ipc_callid_t *callid, size_t *size)
     1126{
     1127        ipc_call_t data;
     1128       
     1129        assert(callid);
     1130        assert(size);
     1131
     1132        *callid = async_get_call(&data);
     1133        if (IPC_GET_METHOD(data) != IPC_M_SHARE_IN)
     1134                return 0;
     1135        *size = (size_t) IPC_GET_ARG2(data);
     1136        return 1;
     1137}
     1138
     1139/** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
     1140 *
     1141 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     1142 * so that the user doesn't have to remember the meaning of each IPC argument.
     1143 *
     1144 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     1145 * @param src           Source address space base.
     1146 * @param flags         Flags to be used for sharing. Bits can be only cleared.
     1147 *
     1148 * @return              Zero on success or a value from @ref errno.h on failure.
     1149 */
     1150int async_share_in_finalize(ipc_callid_t callid, void *src, int flags)
     1151{
     1152        return ipc_share_in_finalize(callid, src, flags);
     1153}
     1154
     1155/** Wrapper for making IPC_M_SHARE_OUT calls using the async framework.
     1156 *
     1157 * @param phoneid       Phone that will be used to contact the receiving side.
     1158 * @param src           Source address space area base address.
     1159 * @param flags         Flags to be used for sharing. Bits can be only cleared.
     1160 *
     1161 * @return              Zero on success or a negative error code from errno.h.
     1162 */
     1163int async_share_out_start(int phoneid, void *src, int flags)
     1164{
     1165        return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
     1166            (ipcarg_t) flags);
     1167}
     1168
     1169/** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework.
     1170 *
     1171 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
     1172 * so that the user doesn't have to remember the meaning of each IPC argument.
     1173 *
     1174 * So far, this wrapper is to be used from within a connection fibril.
     1175 *
     1176 * @param callid        Storage where the hash of the IPC_M_SHARE_OUT call will
     1177 *                      be stored.
     1178 * @param size          Storage where the source address space area size will be
     1179 *                      stored.
     1180 * @param flags         Storage where the sharing flags will be stored.
     1181 *
     1182 * @return              Non-zero on success, zero on failure.
     1183 */
     1184int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
     1185{
     1186        ipc_call_t data;
     1187       
     1188        assert(callid);
     1189        assert(size);
     1190        assert(flags);
     1191
     1192        *callid = async_get_call(&data);
     1193        if (IPC_GET_METHOD(data) != IPC_M_SHARE_OUT)
     1194                return 0;
     1195        *size = (size_t) IPC_GET_ARG2(data);
     1196        *flags = (int) IPC_GET_ARG3(data);
     1197        return 1;
     1198}
     1199
     1200/** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework.
     1201 *
     1202 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
     1203 * so that the user doesn't have to remember the meaning of each IPC argument.
     1204 *
     1205 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
     1206 * @param dst           Destination address space area base address.   
     1207 *
     1208 * @return              Zero on success or a value from @ref errno.h on failure.
     1209 */
     1210int async_share_out_finalize(ipc_callid_t callid, void *dst)
     1211{
     1212        return ipc_share_out_finalize(callid, dst);
     1213}
     1214
     1215
     1216/** Wrapper for making IPC_M_DATA_READ calls using the async framework.
     1217 *
     1218 * @param phoneid       Phone that will be used to contact the receiving side.
     1219 * @param dst           Address of the beginning of the destination buffer.
     1220 * @param size          Size of the destination buffer.
     1221 *
     1222 * @return              Zero on success or a negative error code from errno.h.
     1223 */
     1224int async_data_read_start(int phoneid, void *dst, size_t size)
     1225{
     1226        return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
     1227            (ipcarg_t) size);
     1228}
     1229
     1230/** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework.
     1231 *
     1232 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
     1233 * so that the user doesn't have to remember the meaning of each IPC argument.
     1234 *
     1235 * So far, this wrapper is to be used from within a connection fibril.
     1236 *
     1237 * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
     1238 *                      be stored.
     1239 * @param size          Storage where the maximum size will be stored. Can be
     1240 *                      NULL.
     1241 *
     1242 * @return              Non-zero on success, zero on failure.
     1243 */
     1244int async_data_read_receive(ipc_callid_t *callid, size_t *size)
     1245{
     1246        ipc_call_t data;
     1247       
     1248        assert(callid);
     1249
     1250        *callid = async_get_call(&data);
     1251        if (IPC_GET_METHOD(data) != IPC_M_DATA_READ)
     1252                return 0;
     1253        if (size)
     1254                *size = (size_t) IPC_GET_ARG2(data);
     1255        return 1;
     1256}
     1257
     1258/** Wrapper for answering the IPC_M_DATA_READ calls using the async framework.
     1259 *
     1260 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     1261 * so that the user doesn't have to remember the meaning of each IPC argument.
     1262 *
     1263 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     1264 * @param src           Source address for the IPC_M_DATA_READ call.
     1265 * @param size          Size for the IPC_M_DATA_READ call. Can be smaller than
     1266 *                      the maximum size announced by the sender.
     1267 *
     1268 * @return              Zero on success or a value from @ref errno.h on failure.
     1269 */
     1270int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
     1271{
     1272        return ipc_data_read_finalize(callid, src, size);
     1273}
     1274
     1275/** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
     1276 *
     1277 * @param phoneid       Phone that will be used to contact the receiving side.
     1278 * @param src           Address of the beginning of the source buffer.
     1279 * @param size          Size of the source buffer.
     1280 *
     1281 * @return              Zero on success or a negative error code from errno.h.
     1282 */
     1283int async_data_write_start(int phoneid, const void *src, size_t size)
     1284{
     1285        return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
     1286            (ipcarg_t) size);
     1287}
     1288
     1289/** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework.
     1290 *
     1291 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
     1292 * so that the user doesn't have to remember the meaning of each IPC argument.
     1293 *
     1294 * So far, this wrapper is to be used from within a connection fibril.
     1295 *
     1296 * @param callid        Storage where the hash of the IPC_M_DATA_WRITE call will
     1297 *                      be stored.
     1298 * @param size          Storage where the suggested size will be stored. May be
     1299 *                      NULL
     1300 *
     1301 * @return              Non-zero on success, zero on failure.
     1302 */
     1303int async_data_write_receive(ipc_callid_t *callid, size_t *size)
     1304{
     1305        ipc_call_t data;
     1306       
     1307        assert(callid);
     1308
     1309        *callid = async_get_call(&data);
     1310        if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE)
     1311                return 0;
     1312        if (size)
     1313                *size = (size_t) IPC_GET_ARG2(data);
     1314        return 1;
     1315}
     1316
     1317/** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework.
     1318 *
     1319 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
     1320 * so that the user doesn't have to remember the meaning of each IPC argument.
     1321 *
     1322 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
     1323 * @param dst           Final destination address for the IPC_M_DATA_WRITE call.
     1324 * @param size          Final size for the IPC_M_DATA_WRITE call.
     1325 *
     1326 * @return              Zero on success or a value from @ref errno.h on failure.
     1327 */
     1328int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
     1329{
     1330        return ipc_data_write_finalize(callid, dst, size);
     1331}
     1332
    11001333/** @}
    11011334 */
  • uspace/lib/libc/generic/devmap.c

    rfcbd1be r1787e527  
    105105        aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
    106106       
    107         ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
     107        ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
    108108       
    109109        if (retval != EOK) {
     
    143143            &answer);
    144144       
    145         ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
     145        ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
    146146       
    147147        if (retval != EOK) {
     
    180180            &answer);
    181181       
    182         ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
     182        ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
    183183       
    184184        if (retval != EOK) {
     
    271271        aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer);
    272272       
    273         ipcarg_t retval = ipc_data_read_start(phone, data, count * sizeof(dev_desc_t));
     273        ipcarg_t retval = async_data_read_start(phone, data, count * sizeof(dev_desc_t));
    274274       
    275275        if (retval != EOK) {
  • uspace/lib/libc/generic/fibril_sync.c

    rfcbd1be r1787e527  
    3636#include <fibril.h>
    3737#include <async.h>
     38#include <async_priv.h>
    3839#include <adt/list.h>
    3940#include <futex.h>
     41#include <sys/time.h>
     42#include <errno.h>
    4043#include <assert.h>
     44
     45static void optimize_execution_power(void)
     46{
     47        /*
     48         * When waking up a worker fibril previously blocked in fibril
     49         * synchronization, chances are that there is an idle manager fibril
     50         * waiting for IPC, that could start executing the awakened worker
     51         * fibril right away. We try to detect this and bring the manager
     52         * fibril back to fruitful work.
     53         */
     54        if (atomic_get(&threads_in_ipc_wait) > 0)
     55                ipc_poke();
     56}
    4157
    4258void fibril_mutex_initialize(fibril_mutex_t *fm)
     
    5066        futex_down(&async_futex);
    5167        if (fm->counter-- <= 0) {
    52                 fibril_t *f = (fibril_t *) fibril_get_id();
    53                 list_append(&f->link, &fm->waiters);
     68                awaiter_t wdata;
     69
     70                wdata.fid = fibril_get_id();
     71                wdata.active = false;
     72                wdata.wu_event.inlist = true;
     73                link_initialize(&wdata.wu_event.link);
     74                list_append(&wdata.wu_event.link, &fm->waiters);
    5475                fibril_switch(FIBRIL_TO_MANAGER);
    5576        } else {
     
    7798        if (fm->counter++ < 0) {
    7899                link_t *tmp;
    79                 fibril_t *f;
     100                awaiter_t *wdp;
    80101       
    81102                assert(!list_empty(&fm->waiters));
    82103                tmp = fm->waiters.next;
    83                 f = list_get_instance(tmp, fibril_t, link);
    84                 list_remove(&f->link);
    85                 fibril_add_ready((fid_t) f);
     104                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     105                wdp->active = true;
     106                wdp->wu_event.inlist = false;
     107                list_remove(&wdp->wu_event.link);
     108                fibril_add_ready(wdp->fid);
     109                optimize_execution_power();
    86110        }
    87111}
     
    106130        if (frw->writers) {
    107131                fibril_t *f = (fibril_t *) fibril_get_id();
     132                awaiter_t wdata;
     133
     134                wdata.fid = (fid_t) f;
     135                wdata.active = false;
     136                wdata.wu_event.inlist = true;
     137                link_initialize(&wdata.wu_event.link);
    108138                f->flags &= ~FIBRIL_WRITER;
    109                 list_append(&f->link, &frw->waiters);
     139                list_append(&wdata.wu_event.link, &frw->waiters);
    110140                fibril_switch(FIBRIL_TO_MANAGER);
    111141        } else {
     
    120150        if (frw->writers || frw->readers) {
    121151                fibril_t *f = (fibril_t *) fibril_get_id();
     152                awaiter_t wdata;
     153
     154                wdata.fid = (fid_t) f;
     155                wdata.active = false;
     156                wdata.wu_event.inlist = true;
     157                link_initialize(&wdata.wu_event.link);
    122158                f->flags |= FIBRIL_WRITER;
    123                 list_append(&f->link, &frw->waiters);
     159                list_append(&wdata.wu_event.link, &frw->waiters);
    124160                fibril_switch(FIBRIL_TO_MANAGER);
    125161        } else {
     
    144180        while (!list_empty(&frw->waiters)) {
    145181                link_t *tmp = frw->waiters.next;
    146                 fibril_t *f = list_get_instance(tmp, fibril_t, link);
     182                awaiter_t *wdp;
     183                fibril_t *f;
     184               
     185                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     186                f = (fibril_t *) wdp->fid;
    147187               
    148188                if (f->flags & FIBRIL_WRITER) {
    149189                        if (frw->readers)
    150190                                break;
    151                         list_remove(&f->link);
    152                         fibril_add_ready((fid_t) f);
     191                        wdp->active = true;
     192                        wdp->wu_event.inlist = false;
     193                        list_remove(&wdp->wu_event.link);
     194                        fibril_add_ready(wdp->fid);
    153195                        frw->writers++;
     196                        optimize_execution_power();
    154197                        break;
    155198                } else {
    156                         list_remove(&f->link);
    157                         fibril_add_ready((fid_t) f);
     199                        wdp->active = true;
     200                        wdp->wu_event.inlist = false;
     201                        list_remove(&wdp->wu_event.link);
     202                        fibril_add_ready(wdp->fid);
    158203                        frw->readers++;
     204                        optimize_execution_power();
    159205                }
    160206        }
     
    178224}
    179225
    180 void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
    181 {
    182         fibril_t *f = (fibril_t *) fibril_get_id();
    183 
    184         futex_down(&async_futex);
    185         list_append(&f->link, &fcv->waiters);
     226int
     227fibril_condvar_wait_timeout(fibril_condvar_t *fcv, fibril_mutex_t *fm,
     228    suseconds_t timeout)
     229{
     230        awaiter_t wdata;
     231
     232        if (timeout < 0)
     233                return ETIMEOUT;
     234
     235        wdata.fid = fibril_get_id();
     236        wdata.active = false;
     237       
     238        wdata.to_event.inlist = timeout > 0;
     239        wdata.to_event.occurred = false;
     240        link_initialize(&wdata.to_event.link);
     241
     242        wdata.wu_event.inlist = true;
     243        link_initialize(&wdata.wu_event.link);
     244
     245        futex_down(&async_futex);
     246        if (timeout) {
     247                gettimeofday(&wdata.to_event.expires, NULL);
     248                tv_add(&wdata.to_event.expires, timeout);
     249                async_insert_timeout(&wdata);
     250        }
     251        list_append(&wdata.wu_event.link, &fcv->waiters);
    186252        _fibril_mutex_unlock_unsafe(fm);
    187253        fibril_switch(FIBRIL_TO_MANAGER);
    188254        fibril_mutex_lock(fm);
     255
     256        /* async_futex not held after fibril_switch() */
     257        futex_down(&async_futex);
     258        if (wdata.to_event.inlist)
     259                list_remove(&wdata.to_event.link);
     260        if (wdata.wu_event.inlist)
     261                list_remove(&wdata.wu_event.link);
     262        futex_up(&async_futex);
     263       
     264        return wdata.to_event.occurred ? ETIMEOUT : EOK;
     265}
     266
     267void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
     268{
     269        int rc;
     270
     271        rc = fibril_condvar_wait_timeout(fcv, fm, 0);
     272        assert(rc == EOK);
    189273}
    190274
     
    192276{
    193277        link_t *tmp;
    194         fibril_t *f;
     278        awaiter_t *wdp;
    195279
    196280        futex_down(&async_futex);
    197281        while (!list_empty(&fcv->waiters)) {
    198282                tmp = fcv->waiters.next;
    199                 f = list_get_instance(tmp, fibril_t, link);
    200                 list_remove(&f->link);
    201                 fibril_add_ready((fid_t) f);
    202                 if (once)
    203                         break;
     283                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     284                list_remove(&wdp->wu_event.link);
     285                wdp->wu_event.inlist = false;
     286                if (!wdp->active) {
     287                        wdp->active = true;
     288                        fibril_add_ready(wdp->fid);
     289                        optimize_execution_power();
     290                        if (once)
     291                                break;
     292                }
    204293        }
    205294        futex_up(&async_futex);
  • uspace/lib/libc/generic/io/console.c

    rfcbd1be r1787e527  
    4545}
    4646
    47 int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols)
     47int console_get_size(int phone, int *cols, int *rows)
    4848{
    49         return async_req_0_2(phone, CONSOLE_GET_SIZE, rows, cols);
     49        ipcarg_t cols_v;
     50        ipcarg_t rows_v;
     51        int rc;
     52
     53        rc = async_req_0_2(phone, CONSOLE_GET_SIZE, &cols_v, &rows_v);
     54
     55        *cols = (int) cols_v;
     56        *rows = (int) rows_v;
     57        return rc;
    5058}
    5159
     
    8694}
    8795
    88 void console_goto(int phone, ipcarg_t row, ipcarg_t col)
     96void console_goto(int phone, int col, int row)
    8997{
    90         async_msg_2(phone, CONSOLE_GOTO, row, col);
     98        async_msg_2(phone, CONSOLE_GOTO, col, row);
    9199}
    92100
  • uspace/lib/libc/generic/io/klog.c

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

    rfcbd1be r1787e527  
    565565}
    566566
     567/** Interrupt one thread of this task from waiting for IPC. */
     568void ipc_poke(void)
     569{
     570        __SYSCALL0(SYS_IPC_POKE);
     571}
     572
    567573/** Ask destination to do a callback connection.
    568574 *
     
    724730        int res;
    725731        sysarg_t tmp_flags;
    726         res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
     732        res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
    727733            (ipcarg_t) size, arg, NULL, &tmp_flags);
    728734        if (flags)
     
    731737}
    732738
    733 /** Wrapper for receiving the IPC_M_SHARE_IN calls.
    734  *
    735  * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
    736  * so that the user doesn't have to remember the meaning of each IPC argument.
    737  *
    738  * So far, this wrapper is to be used from within a connection fibril.
    739  *
    740  * @param callid        Storage where the hash of the IPC_M_SHARE_IN call will
    741  *                      be stored.
    742  * @param size          Destination address space area size.   
    743  *
    744  * @return              Non-zero on success, zero on failure.
    745  */
    746 int ipc_share_in_receive(ipc_callid_t *callid, size_t *size)
    747 {
    748         ipc_call_t data;
    749        
    750         assert(callid);
    751         assert(size);
    752 
    753         *callid = async_get_call(&data);
    754         if (IPC_GET_METHOD(data) != IPC_M_SHARE_IN)
    755                 return 0;
    756         *size = (size_t) IPC_GET_ARG2(data);
    757         return 1;
    758 }
    759 
    760739/** Wrapper for answering the IPC_M_SHARE_IN calls.
    761740 *
     
    784763int ipc_share_out_start(int phoneid, void *src, int flags)
    785764{
    786         return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
     765        return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
    787766            (ipcarg_t) flags);
    788 }
    789 
    790 /** Wrapper for receiving the IPC_M_SHARE_OUT calls.
    791  *
    792  * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
    793  * so that the user doesn't have to remember the meaning of each IPC argument.
    794  *
    795  * So far, this wrapper is to be used from within a connection fibril.
    796  *
    797  * @param callid        Storage where the hash of the IPC_M_SHARE_OUT call will
    798  *                      be stored.
    799  * @param size          Storage where the source address space area size will be
    800  *                      stored.
    801  * @param flags         Storage where the sharing flags will be stored.
    802  *
    803  * @return              Non-zero on success, zero on failure.
    804  */
    805 int ipc_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
    806 {
    807         ipc_call_t data;
    808        
    809         assert(callid);
    810         assert(size);
    811         assert(flags);
    812 
    813         *callid = async_get_call(&data);
    814         if (IPC_GET_METHOD(data) != IPC_M_SHARE_OUT)
    815                 return 0;
    816         *size = (size_t) IPC_GET_ARG2(data);
    817         *flags = (int) IPC_GET_ARG3(data);
    818         return 1;
    819767}
    820768
     
    845793int ipc_data_read_start(int phoneid, void *dst, size_t size)
    846794{
    847         return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
     795        return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
    848796            (ipcarg_t) size);
    849 }
    850 
    851 /** Wrapper for receiving the IPC_M_DATA_READ calls.
    852  *
    853  * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
    854  * so that the user doesn't have to remember the meaning of each IPC argument.
    855  *
    856  * So far, this wrapper is to be used from within a connection fibril.
    857  *
    858  * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
    859  *                      be stored.
    860  * @param size          Storage where the maximum size will be stored. Can be
    861  *                      NULL.
    862  *
    863  * @return              Non-zero on success, zero on failure.
    864  */
    865 int ipc_data_read_receive(ipc_callid_t *callid, size_t *size)
    866 {
    867         ipc_call_t data;
    868        
    869         assert(callid);
    870 
    871         *callid = async_get_call(&data);
    872         if (IPC_GET_METHOD(data) != IPC_M_DATA_READ)
    873                 return 0;
    874         if (size)
    875                 *size = (size_t) IPC_GET_ARG2(data);
    876         return 1;
    877797}
    878798
     
    904824int ipc_data_write_start(int phoneid, const void *src, size_t size)
    905825{
    906         return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
     826        return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
    907827            (ipcarg_t) size);
    908 }
    909 
    910 /** Wrapper for receiving the IPC_M_DATA_WRITE calls.
    911  *
    912  * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
    913  * so that the user doesn't have to remember the meaning of each IPC argument.
    914  *
    915  * So far, this wrapper is to be used from within a connection fibril.
    916  *
    917  * @param callid        Storage where the hash of the IPC_M_DATA_WRITE call will
    918  *                      be stored.
    919  * @param size          Storage where the suggested size will be stored. May be
    920  *                      NULL
    921  *
    922  * @return              Non-zero on success, zero on failure.
    923  */
    924 int ipc_data_write_receive(ipc_callid_t *callid, size_t *size)
    925 {
    926         ipc_call_t data;
    927        
    928         assert(callid);
    929 
    930         *callid = async_get_call(&data);
    931         if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE)
    932                 return 0;
    933         if (size)
    934                 *size = (size_t) IPC_GET_ARG2(data);
    935         return 1;
    936828}
    937829
  • uspace/lib/libc/generic/libc.c

    rfcbd1be r1787e527  
    8383                argv = __pcb->argv;
    8484                __stdio_init(__pcb->filc, __pcb->filv);
     85                (void) chdir(__pcb->cwd);
    8586        }
    8687       
  • uspace/lib/libc/generic/loader.c

    rfcbd1be r1787e527  
    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));
     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        ipcarg_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);
    93128        if (rc != EOK) {
    94129                async_wait_for(req, NULL);
     
    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);
     160        int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
    126161        if (rc != EOK) {
    127162                async_wait_for(req, NULL);
     
    178213        ipc_call_t answer;
    179214        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);
     215        ipcarg_t rc = async_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
    181216        if (rc != EOK) {
    182217                async_wait_for(req, NULL);
     
    232267        ipc_call_t answer;
    233268        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,
     269        ipcarg_t rc = async_data_write_start(ldr->phone_id, (void *) files_buf,
    235270            count * sizeof(fdi_node_t));
    236271        if (rc != EOK) {
  • uspace/lib/libc/generic/malloc.c

    rfcbd1be r1787e527  
    353353}
    354354
     355void *calloc(const size_t nmemb, const size_t size)
     356{
     357        void *block = malloc(nmemb * size);
     358        if (block == NULL)
     359                return NULL;
     360
     361        memset(block, 0, nmemb * size);
     362        return block;
     363}
     364
    355365void *malloc(const size_t size)
    356366{
  • uspace/lib/libc/generic/task.c

    rfcbd1be r1787e527  
    8989                goto error;
    9090       
     91        /* Send spawner's current working directory. */
     92        rc = loader_set_cwd(ldr);
     93        if (rc != EOK)
     94                goto error;
     95       
    9196        /* Send program pathname. */
    9297        rc = loader_set_pathname(ldr, path);
     
    98103        if (rc != EOK)
    99104                goto error;
    100        
    101105       
    102106        /* Send default files */
  • uspace/lib/libc/generic/vfs/vfs.c

    rfcbd1be r1787e527  
    5757static futex_t cwd_futex = FUTEX_INITIALIZER;
    5858
    59 DIR *cwd_dir = NULL;
    60 char *cwd_path = NULL;
    61 size_t cwd_size = 0;
     59static int cwd_fd = -1;
     60static char *cwd_path = NULL;
     61static size_t cwd_size = 0;
    6262
    6363char *absolutize(const char *path, size_t *retlen)
     
    140140       
    141141        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);
     142        rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
    143143        if (rc != EOK) {
    144144                async_wait_for(req, &rc_orig);
     
    152152        }
    153153       
    154         rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
     154        rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
    155155        if (rc != EOK) {
    156156                async_wait_for(req, &rc_orig);
     
    164164        }
    165165
    166         rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
     166        rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
    167167        if (rc != EOK) {
    168168                async_wait_for(req, &rc_orig);
     
    197197}
    198198
    199 static int _open(const char *path, int lflag, int oflag, ...)
    200 {
    201         ipcarg_t rc;
     199static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
     200{
     201        futex_down(&vfs_phone_futex);
     202        async_serialize_start();
     203        vfs_connect();
     204       
    202205        ipc_call_t answer;
    203         aid_t req;
    204        
    205         size_t pa_size;
    206         char *pa = absolutize(path, &pa_size);
    207         if (!pa)
    208                 return ENOMEM;
    209        
    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);
     206        aid_t req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
     207        ipcarg_t rc = async_data_write_start(vfs_phone, abs, abs_size);
     208       
    216209        if (rc != EOK) {
    217210                ipcarg_t rc_orig;
    218        
    219                 async_wait_for(req, &rc_orig);
    220                 async_serialize_end();
    221                 futex_up(&vfs_phone_futex);
    222                 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);
    231         free(pa);
     211                async_wait_for(req, &rc_orig);
     212               
     213                async_serialize_end();
     214                futex_up(&vfs_phone_futex);
     215               
     216                if (rc_orig == EOK)
     217                        return (int) rc;
     218                else
     219                        return (int) rc_orig;
     220        }
     221       
     222        async_wait_for(req, &rc);
     223        async_serialize_end();
     224        futex_up(&vfs_phone_futex);
    232225       
    233226        if (rc != EOK)
     
    239232int open(const char *path, int oflag, ...)
    240233{
    241         return _open(path, L_FILE, oflag);
     234        size_t abs_size;
     235        char *abs = absolutize(path, &abs_size);
     236        if (!abs)
     237                return ENOMEM;
     238       
     239        int ret = open_internal(abs, abs_size, L_FILE, oflag);
     240        free(abs);
     241       
     242        return ret;
    242243}
    243244
     
    290291       
    291292        req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
    292         rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
     293        rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
    293294        if (rc != EOK) {
    294295                ipcarg_t rc_orig;
     
    322323       
    323324        req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
    324         rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
     325        rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
    325326        if (rc != EOK) {
    326327                ipcarg_t rc_orig;
     
    402403       
    403404        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        rc = async_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
    405406        if (rc != EOK) {
    406407                ipcarg_t rc_orig;
     
    437438       
    438439        req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
    439         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     440        rc = async_data_write_start(vfs_phone, pa, pa_size);
    440441        if (rc != EOK) {
    441442                async_wait_for(req, &rc_orig);
     
    448449                        return (int) rc_orig;
    449450        }
    450         rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
     451        rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
    451452        if (rc != EOK) {
    452453                async_wait_for(req, &rc_orig);
     
    471472        if (!dirp)
    472473                return NULL;
    473         dirp->fd = _open(dirname, L_DIRECTORY, 0);
    474         if (dirp->fd < 0) {
     474       
     475        size_t abs_size;
     476        char *abs = absolutize(dirname, &abs_size);
     477        if (!abs) {
     478                free(dirp);
     479                return ENOMEM;
     480        }
     481       
     482        int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
     483        free(abs);
     484       
     485        if (ret < 0) {
    475486                free(dirp);
    476487                return NULL;
    477488        }
     489       
     490        dirp->fd = ret;
    478491        return dirp;
    479492}
     
    514527       
    515528        req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
    516         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     529        rc = async_data_write_start(vfs_phone, pa, pa_size);
    517530        if (rc != EOK) {
    518531                ipcarg_t rc_orig;
     
    549562       
    550563        req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
    551         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     564        rc = async_data_write_start(vfs_phone, pa, pa_size);
    552565        if (rc != EOK) {
    553566                ipcarg_t rc_orig;
     
    602615       
    603616        req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
    604         rc = ipc_data_write_start(vfs_phone, olda, olda_size);
     617        rc = async_data_write_start(vfs_phone, olda, olda_size);
    605618        if (rc != EOK) {
    606619                async_wait_for(req, &rc_orig);
     
    614627                        return (int) rc_orig;
    615628        }
    616         rc = ipc_data_write_start(vfs_phone, newa, newa_size);
     629        rc = async_data_write_start(vfs_phone, newa, newa_size);
    617630        if (rc != EOK) {
    618631                async_wait_for(req, &rc_orig);
     
    636649int chdir(const char *path)
    637650{
    638         size_t pa_size;
    639         char *pa = absolutize(path, &pa_size);
    640         if (!pa)
    641                 return ENOMEM;
    642 
    643         DIR *d = opendir(pa);
    644         if (!d) {
    645                 free(pa);
     651        size_t abs_size;
     652        char *abs = absolutize(path, &abs_size);
     653        if (!abs)
     654                return ENOMEM;
     655       
     656        int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
     657       
     658        if (fd < 0) {
     659                free(abs);
    646660                return ENOENT;
    647661        }
    648 
     662       
    649663        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;
     664       
     665        if (cwd_fd >= 0)
     666                close(cwd_fd);
     667       
     668       
     669        if (cwd_path)
     670                free(cwd_path);
     671       
     672        cwd_fd = fd;
     673        cwd_path = abs;
     674        cwd_size = abs_size;
     675       
    660676        futex_up(&cwd_futex);
    661677        return EOK;
     
    664680char *getcwd(char *buf, size_t size)
    665681{
    666         if (!size)
     682        if (size == 0)
    667683                return NULL;
     684       
    668685        futex_down(&cwd_futex);
    669         if (size < cwd_size + 1) {
     686       
     687        if ((cwd_size == 0) || (size < cwd_size + 1)) {
    670688                futex_up(&cwd_futex);
    671689                return NULL;
    672690        }
     691       
    673692        str_cpy(buf, size, cwd_path);
    674693        futex_up(&cwd_futex);
     694       
    675695        return buf;
    676696}
     
    705725}
    706726
     727int dup2(int oldfd, int newfd)
     728{
     729        futex_down(&vfs_phone_futex);
     730        async_serialize_start();
     731        vfs_connect();
     732       
     733        ipcarg_t ret;
     734        ipcarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
     735       
     736        async_serialize_end();
     737        futex_up(&vfs_phone_futex);
     738       
     739        if (rc == EOK)
     740                return (int) ret;
     741       
     742        return (int) rc;
     743}
     744
    707745/** @}
    708746 */
  • uspace/lib/libc/include/async.h

    rfcbd1be r1787e527  
    4747extern atomic_t async_futex;
    4848
     49extern atomic_t threads_in_ipc_wait;
     50
    4951extern int __async_init(void);
    5052extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
     
    257259}
    258260
     261/*
     262 * User-friendly wrappers for async_share_in_start().
     263 */
     264#define async_share_in_start_0_0(phoneid, dst, size) \
     265        async_share_in_start((phoneid), (dst), (size), 0, NULL)
     266#define async_share_in_start_0_1(phoneid, dst, size, flags) \
     267        async_share_in_start((phoneid), (dst), (size), 0, (flags))
     268#define async_share_in_start_1_0(phoneid, dst, size, arg) \
     269        async_share_in_start((phoneid), (dst), (size), (arg), NULL)
     270#define async_share_in_start_1_1(phoneid, dst, size, arg, flags) \
     271        async_share_in_start((phoneid), (dst), (size), (arg), (flags))
     272
     273extern int async_share_in_start(int, void *, size_t, ipcarg_t, int *);
     274extern int async_share_in_receive(ipc_callid_t *, size_t *);
     275extern int async_share_in_finalize(ipc_callid_t, void *, int );
     276extern int async_share_out_start(int, void *, int);
     277extern int async_share_out_receive(ipc_callid_t *, size_t *, int *);
     278extern int async_share_out_finalize(ipc_callid_t, void *);
     279extern int async_data_read_start(int, void *, size_t);
     280extern int async_data_read_receive(ipc_callid_t *, size_t *);
     281extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
     282extern int async_data_write_start(int, const void *, size_t);
     283extern int async_data_write_receive(ipc_callid_t *, size_t *);
     284extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
     285
    259286#endif
    260287
  • uspace/lib/libc/include/async_priv.h

    rfcbd1be r1787e527  
    11/*
    2  * Copyright (c) 2005 Jakub Jermar
     2 * Copyright (c) 2006 Ondrej Palkovsky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup libcia32
     29/** @addtogroup libc
    3030 * @{
    3131 */
     
    3333 */
    3434
    35 /*
    36  * Variable argument list manipulation macros
    37  * for architectures using stack to pass arguments.
    38  */
    39  
    40 #ifndef LIBC_ia32_STACKARG_H_
    41 #define LIBC_ia32_STACKARG_H_
     35#ifndef LIBC_ASYNC_PRIV_H_
     36#define LIBC_ASYNC_PRIV_H_
    4237
    43 #include <sys/types.h>
     38#include <adt/list.h>
     39#include <fibril.h>
     40#include <sys/time.h>
     41#include <bool.h>
    4442
    45 /* dont allow to define it second time in stdarg.h */
    46 #define __VARARGS_DEFINED
     43/** Structures of this type are used to track the timeout events. */
     44typedef struct {
     45        /** If true, this struct is in the timeout list. */
     46        bool inlist;
     47       
     48        /** Timeout list link. */
     49        link_t link;
     50       
     51        /** If true, we have timed out. */
     52        bool occurred;
    4753
    48 typedef struct va_list {
    49         int pos;
    50         uint8_t *last;
    51 } va_list;
     54        /** Expiration time. */
     55        struct timeval expires;
     56} to_event_t;
    5257
    53 #define va_start(ap, lst) \
    54         (ap).pos = sizeof(lst);                         \
    55         (ap).last = (uint8_t *) &(lst)
     58/** Structures of this type are used to track the wakeup events. */
     59typedef struct {
     60        /** If true, this struct is in a synchronization object wait queue. */
     61        bool inlist;
     62       
     63        /** Wait queue linkage. */
     64        link_t link;
     65} wu_event_t;
    5666
    57 #define va_arg(ap, type)                \
    58         (*((type *)((ap).last + ((ap).pos  += sizeof(type) ) - sizeof(type))))
    5967
    60 #define va_end(ap)
     68/** Structures of this type represent a waiting fibril. */
     69typedef struct {
     70        /** Identification of and link to the waiting fibril. */
     71        fid_t fid;
     72       
     73        /** If true, this fibril is currently active. */
     74        bool active;
    6175
     76        /** Timeout wait data. */
     77        to_event_t to_event;
     78        /** Wakeup wait data. */
     79        wu_event_t wu_event;
     80} awaiter_t;
     81
     82extern void async_insert_timeout(awaiter_t *wd);
    6283
    6384#endif
  • uspace/lib/libc/include/fcntl.h

    rfcbd1be r1787e527  
    4343#define O_RDWR    32
    4444#define O_WRONLY  64
     45#define O_DESC    128
    4546
    4647extern int open(const char *, int, ...);
  • uspace/lib/libc/include/fibril_sync.h

    rfcbd1be r1787e527  
    4040#include <adt/list.h>
    4141#include <libarch/tls.h>
     42#include <sys/time.h>
    4243
    4344typedef struct {
     
    9596
    9697extern void fibril_condvar_initialize(fibril_condvar_t *);
     98extern int fibril_condvar_wait_timeout(fibril_condvar_t *, fibril_mutex_t *,
     99    suseconds_t);
    97100extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
    98101extern void fibril_condvar_signal(fibril_condvar_t *);
  • uspace/lib/libc/include/io/console.h

    rfcbd1be r1787e527  
    6868extern void console_clear(int phone);
    6969
    70 extern int console_get_size(int phone, ipcarg_t *rows, ipcarg_t *cols);
    71 extern void console_goto(int phone, ipcarg_t row, ipcarg_t col);
     70extern int console_get_size(int phone, int *cols, int *rows);
     71extern void console_goto(int phone, int col, int row);
    7272
    7373extern void console_set_style(int phone, int style);
  • uspace/lib/libc/include/ipc/bd.h

    rfcbd1be r1787e527  
    3939
    4040typedef enum {
    41         BD_READ_BLOCK = IPC_FIRST_USER_METHOD,
    42         BD_WRITE_BLOCK
     41        BD_GET_BLOCK_SIZE = IPC_FIRST_USER_METHOD,
     42        BD_READ_BLOCKS,
     43        BD_WRITE_BLOCKS
    4344} bd_request_t;
    4445
  • uspace/lib/libc/include/ipc/ipc.h

    rfcbd1be r1787e527  
    192192extern ipc_callid_t ipc_wait_cycle(ipc_call_t *, uint32_t, int);
    193193extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *, uint32_t);
     194extern void ipc_poke(void);
    194195
    195196static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data)
     
    282283
    283284extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *);
    284 extern int ipc_share_in_receive(ipc_callid_t *, size_t *);
    285285extern int ipc_share_in_finalize(ipc_callid_t, void *, int );
    286286extern int ipc_share_out_start(int, void *, int);
    287 extern int ipc_share_out_receive(ipc_callid_t *, size_t *, int *);
    288287extern int ipc_share_out_finalize(ipc_callid_t, void *);
    289288extern int ipc_data_read_start(int, void *, size_t);
    290 extern int ipc_data_read_receive(ipc_callid_t *, size_t *);
    291289extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t);
    292290extern int ipc_data_write_start(int, const void *, size_t);
    293 extern int ipc_data_write_receive(ipc_callid_t *, size_t *);
    294291extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t);
    295292
  • uspace/lib/libc/include/ipc/loader.h

    rfcbd1be r1787e527  
    4141        LOADER_HELLO = IPC_FIRST_USER_METHOD,
    4242        LOADER_GET_TASKID,
     43        LOADER_SET_CWD,
    4344        LOADER_SET_PATHNAME,
    4445        LOADER_SET_ARGS,
  • uspace/lib/libc/include/ipc/vfs.h

    rfcbd1be r1787e527  
    7373        VFS_IN_UNLINK,
    7474        VFS_IN_RENAME,
    75         VFS_IN_STAT
     75        VFS_IN_STAT,
     76        VFS_IN_DUP
    7677} vfs_in_request_t;
    7778
  • uspace/lib/libc/include/loader/loader.h

    rfcbd1be r1787e527  
    4949extern loader_t *loader_connect(void);
    5050extern int loader_get_task_id(loader_t *, task_id_t *);
     51extern int loader_set_cwd(loader_t *);
    5152extern int loader_set_pathname(loader_t *, const char *);
    5253extern int loader_set_args(loader_t *, char *const[]);
  • uspace/lib/libc/include/loader/pcb.h

    rfcbd1be r1787e527  
    5252        /** Program entry point. */
    5353        entry_point_t entry;
     54
     55        /** Current working directory. */
     56        char *cwd;
    5457       
    5558        /** Number of command-line arguments. */
  • uspace/lib/libc/include/malloc.h

    rfcbd1be r1787e527  
    4242
    4343extern void *malloc(const size_t size);
     44extern void *calloc(const size_t nmemb, const size_t size);
    4445extern void *memalign(const size_t align, const size_t size);
    4546extern void *realloc(const void *addr, const size_t size);
  • uspace/lib/libc/include/stdarg.h

    rfcbd1be r1787e527  
    3737
    3838#include <sys/types.h>
    39 #include <libarch/stackarg.h>
    40 
    41 #ifndef __VARARGS_DEFINED
    42 # define __VARARGS_DEFINED
    4339
    4440typedef __builtin_va_list va_list;
    4541
    46 # define va_start(ap, last)             __builtin_va_start(ap, last)
    47 # define va_arg(ap, type)               __builtin_va_arg(ap, type)
    48 # define va_end(ap)                     __builtin_va_end(ap)
    49 
    50 # endif
     42#define va_start(ap, last)  __builtin_va_start(ap, last)
     43#define va_arg(ap, type)    __builtin_va_arg(ap, type)
     44#define va_end(ap)          __builtin_va_end(ap)
    5145
    5246#endif
  • uspace/lib/libc/include/unistd.h

    rfcbd1be r1787e527  
    5151#endif
    5252
     53extern int dup2(int oldfd, int newfd);
     54
    5355extern ssize_t write(int, const void *, size_t);
    5456extern ssize_t read(int, void *, size_t);
  • uspace/lib/libfs/Makefile

    rfcbd1be r1787e527  
    2828#
    2929
    30 ## Common compiler flags
    31 #
     30include Makefile.common
    3231
    33 LIBC_PREFIX = ../libc
     32.PHONY: all clean
    3433
    35 ## Setup toolchain
    36 #
    37 
    38 include $(LIBC_PREFIX)/Makefile.toolchain
    39 
    40 CFLAGS += -Iinclude
    41 
    42 ## Sources
    43 #
    44 
    45 SOURCES = \
    46         libfs.c
    47 
    48 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
    49 
    50 .PHONY: all clean depend
    51 
    52 all: libfs.a
    53 
    54 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBC_PREFIX)/libc.a
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5537
    5638clean:
    57         -rm -f libfs.a Makefile.depend
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(LIBFS)
    5840        find . -name '*.o' -follow -exec rm \{\} \;
    59 
    60 depend:
    61         -makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > Makefile.depend 2> /dev/null
    62 
    63 libfs.a: depend $(OBJECTS)
    64         $(AR) rc libfs.a $(OBJECTS)
    65 
    66 %.o: %.c
    67         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
  • uspace/lib/libfs/libfs.c

    rfcbd1be r1787e527  
    4646#include <sys/stat.h>
    4747
     48#define on_error(rc, action) \
     49        do { \
     50                if ((rc) != EOK) \
     51                        action; \
     52        } while (0)
     53
     54#define combine_rc(rc1, rc2) \
     55        ((rc1) == EOK ? (rc2) : (rc1))
     56
     57#define answer_and_return(rid, rc) \
     58        do { \
     59                ipc_answer_0((rid), (rc)); \
     60                return; \
     61        } while (0)
     62
    4863/** Register file system server.
    4964 *
     
    7691         * Send our VFS info structure to VFS.
    7792         */
    78         int rc = ipc_data_write_start(vfs_phone, info, sizeof(*info));
     93        int rc = async_data_write_start(vfs_phone, info, sizeof(*info));
    7994        if (rc != EOK) {
    8095                async_wait_for(req, NULL);
     
    99114         * Request sharing the Path Lookup Buffer with VFS.
    100115         */
    101         rc = ipc_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);
     116        rc = async_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);
    102117        if (rc) {
    103118                async_wait_for(req, NULL);
     
    154169        ipc_answer_0(callid, EOK);      /* acknowledge the mountee_phone */
    155170       
    156         res = ipc_data_write_receive(&callid, NULL);
     171        res = async_data_write_receive(&callid, NULL);
    157172        if (!res) {
    158173                ipc_hangup(mountee_phone);
     
    162177        }
    163178
    164         fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index);
    165         if (!fn) {
     179        fs_node_t *fn;
     180        res = ops->node_get(&fn, mp_dev_handle, mp_fs_index);
     181        if (res != EOK || !fn) {
    166182                ipc_hangup(mountee_phone);
    167                 ipc_answer_0(callid, ENOENT);
    168                 ipc_answer_0(rid, ENOENT);
     183                ipc_answer_0(callid, combine_rc(res, ENOENT));
     184                ipc_answer_0(rid, combine_rc(res, ENOENT));
    169185                return;
    170186        }
     
    172188        if (fn->mp_data.mp_active) {
    173189                ipc_hangup(mountee_phone);
    174                 ops->node_put(fn);
     190                (void) ops->node_put(fn);
    175191                ipc_answer_0(callid, EBUSY);
    176192                ipc_answer_0(rid, EBUSY);
     
    179195
    180196        rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
    181         if (rc != 0) {
     197        if (rc != EOK) {
    182198                ipc_hangup(mountee_phone);
    183                 ops->node_put(fn);
     199                (void) ops->node_put(fn);
    184200                ipc_answer_0(callid, rc);
    185201                ipc_answer_0(rid, rc);
     
    230246        char component[NAME_MAX + 1];
    231247        int len;
     248        int rc;
    232249
    233250        if (last < next)
     
    235252
    236253        fs_node_t *par = NULL;
    237         fs_node_t *cur = ops->root_get(dev_handle);
     254        fs_node_t *cur = NULL;
    238255        fs_node_t *tmp = NULL;
     256
     257        rc = ops->root_get(&cur, dev_handle);
     258        on_error(rc, goto out_with_answer);
    239259
    240260        if (cur->mp_data.mp_active) {
     
    242262                    next, last, cur->mp_data.dev_handle, lflag, index,
    243263                    IPC_FF_ROUTE_FROM_ME);
    244                 ops->node_put(cur);
     264                (void) ops->node_put(cur);
    245265                return;
    246266        }
     
    249269                next++;         /* eat slash */
    250270       
    251         while (next <= last && ops->has_children(cur)) {
     271        while (next <= last) {
     272                bool has_children;
     273
     274                rc = ops->has_children(&has_children, cur);
     275                on_error(rc, goto out_with_answer);
     276                if (!has_children)
     277                        break;
     278
    252279                /* collect the component */
    253280                len = 0;
     
    267294
    268295                /* match the component */
    269                 tmp = ops->match(cur, component);
     296                rc = ops->match(&tmp, cur, component);
     297                on_error(rc, goto out_with_answer);
     298
    270299                if (tmp && tmp->mp_data.mp_active) {
    271300                        if (next > last)
     
    277306                            VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle,
    278307                            lflag, index, IPC_FF_ROUTE_FROM_ME);
    279                         ops->node_put(cur);
    280                         ops->node_put(tmp);
     308                        (void) ops->node_put(cur);
     309                        (void) ops->node_put(tmp);
    281310                        if (par)
    282                                 ops->node_put(par);
     311                                (void) ops->node_put(par);
    283312                        return;
    284313                }
     
    300329                                fs_node_t *fn;
    301330                                if (lflag & L_CREATE)
    302                                         fn = ops->create(dev_handle, lflag);
     331                                        rc = ops->create(&fn, dev_handle,
     332                                            lflag);
    303333                                else
    304                                         fn = ops->node_get(dev_handle,
     334                                        rc = ops->node_get(&fn, dev_handle,
    305335                                            index);
     336                                on_error(rc, goto out_with_answer);
    306337                                if (fn) {
    307                                         int rc;
    308 
    309338                                        rc = ops->link(cur, fn, component);
    310339                                        if (rc != EOK) {
    311                                                 if (lflag & L_CREATE) {
    312                                                         (void)ops->destroy(fn);
    313                                                 }
     340                                                if (lflag & L_CREATE)
     341                                                        (void) ops->destroy(fn);
    314342                                                ipc_answer_0(rid, rc);
    315343                                        } else {
     
    319347                                                    ops->size_get(fn),
    320348                                                    ops->lnkcnt_get(fn));
    321                                                 ops->node_put(fn);
     349                                                (void) ops->node_put(fn);
    322350                                        }
    323351                                } else {
     
    330358                }
    331359
    332                 if (par)
    333                         ops->node_put(par);
     360                if (par) {
     361                        rc = ops->node_put(par);
     362                        on_error(rc, goto out_with_answer);
     363                }
    334364
    335365                /* descend one level */
     
    340370
    341371        /* handle miss: excessive components */
    342         if (next <= last && !ops->has_children(cur)) {
     372        if (next <= last) {
     373                bool has_children;
     374
     375                rc = ops->has_children(&has_children, cur);
     376                on_error(rc, goto out_with_answer);
     377                if (has_children)
     378                        goto skip_miss;
     379
    343380                if (lflag & (L_CREATE | L_LINK)) {
    344381                        if (!ops->is_directory(cur)) {
     
    368405                        fs_node_t *fn;
    369406                        if (lflag & L_CREATE)
    370                                 fn = ops->create(dev_handle, lflag);
     407                                rc = ops->create(&fn, dev_handle, lflag);
    371408                        else
    372                                 fn = ops->node_get(dev_handle, index);
     409                                rc = ops->node_get(&fn, dev_handle, index);
     410                        on_error(rc, goto out_with_answer);
    373411                        if (fn) {
    374                                 int rc;
    375 
    376412                                rc = ops->link(cur, fn, component);
    377413                                if (rc != EOK) {
    378414                                        if (lflag & L_CREATE)
    379                                                 (void)ops->destroy(fn);
     415                                                (void) ops->destroy(fn);
    380416                                        ipc_answer_0(rid, rc);
    381417                                } else {
     
    385421                                            ops->size_get(fn),
    386422                                            ops->lnkcnt_get(fn));
    387                                         ops->node_put(fn);
     423                                        (void) ops->node_put(fn);
    388424                                }
    389425                        } else {
     
    395431                goto out;
    396432        }
     433skip_miss:
    397434
    398435        /* handle hit */
    399436        if (lflag & L_UNLINK) {
    400437                unsigned old_lnkcnt = ops->lnkcnt_get(cur);
    401                 int res = ops->unlink(par, cur, component);
    402                 ipc_answer_5(rid, (ipcarg_t)res, fs_handle, dev_handle,
     438                rc = ops->unlink(par, cur, component);
     439                ipc_answer_5(rid, (ipcarg_t)rc, fs_handle, dev_handle,
    403440                    ops->index_get(cur), ops->size_get(cur), old_lnkcnt);
    404441                goto out;
     
    418455        }
    419456
    420         ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur),
    421             ops->size_get(cur), ops->lnkcnt_get(cur));
     457out_with_answer:
     458        if (rc == EOK) {
     459                ipc_answer_5(rid, EOK, fs_handle, dev_handle,
     460                    ops->index_get(cur), ops->size_get(cur),
     461                    ops->lnkcnt_get(cur));
     462        } else {
     463                ipc_answer_0(rid, rc);
     464        }
    422465
    423466out:
    424467        if (par)
    425                 ops->node_put(par);
     468                (void) ops->node_put(par);
    426469        if (cur)
    427                 ops->node_put(cur);
     470                (void) ops->node_put(cur);
    428471        if (tmp)
    429                 ops->node_put(tmp);
     472                (void) ops->node_put(tmp);
    430473}
    431474
     
    435478        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
    436479        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    437         fs_node_t *fn = ops->node_get(dev_handle, index);
     480        fs_node_t *fn;
     481        int rc;
     482
     483        rc = ops->node_get(&fn, dev_handle, index);
     484        on_error(rc, answer_and_return(rid, rc));
    438485
    439486        ipc_callid_t callid;
    440487        size_t size;
    441         if (!ipc_data_read_receive(&callid, &size) ||
     488        if (!async_data_read_receive(&callid, &size) ||
    442489            size != sizeof(struct stat)) {
    443490                ipc_answer_0(callid, EINVAL);
     
    456503        stat.size = ops->size_get(fn);
    457504
    458         ipc_data_read_finalize(callid, &stat, sizeof(struct stat));
     505        async_data_read_finalize(callid, &stat, sizeof(struct stat));
    459506        ipc_answer_0(rid, EOK);
    460507}
     
    473520        dev_handle_t dev_handle = IPC_GET_ARG1(*request);
    474521        fs_index_t index = IPC_GET_ARG2(*request);
    475        
    476         fs_node_t *node = ops->node_get(dev_handle, index);
    477        
    478         if (node == NULL) {
     522        fs_node_t *fn;
     523        int rc;
     524       
     525        rc = ops->node_get(&fn, dev_handle, index);
     526        on_error(rc, answer_and_return(rid, rc));
     527       
     528        if (fn == NULL) {
    479529                ipc_answer_0(rid, ENOENT);
    480530                return;
    481531        }
    482532       
    483         ipc_answer_5(rid, EOK, fs_handle, dev_handle, index,
    484             ops->size_get(node), ops->lnkcnt_get(node));
    485        
    486         ops->node_put(node);
     533        ipc_answer_3(rid, EOK, ops->size_get(fn), ops->lnkcnt_get(fn),
     534            (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
     535       
     536        (void) ops->node_put(fn);
    487537}
    488538
  • uspace/lib/libfs/libfs.h

    rfcbd1be r1787e527  
    5656
    5757typedef struct {
    58         fs_node_t * (* match)(fs_node_t *, const char *);
    59         fs_node_t * (* node_get)(dev_handle_t, fs_index_t);
    60         void (* node_put)(fs_node_t *);
    61         fs_node_t * (* create)(dev_handle_t, int);
     58        /*
     59         * The first set of methods are functions that return an integer error
     60         * code. If some additional return value is to be returned, the first
     61         * argument holds the output argument.
     62         */
     63        int (* root_get)(fs_node_t **, dev_handle_t);
     64        int (* match)(fs_node_t **, fs_node_t *, const char *);
     65        int (* node_get)(fs_node_t **, dev_handle_t, fs_index_t);
     66        int (* node_put)(fs_node_t *);
     67        int (* create)(fs_node_t **, dev_handle_t, int);
    6268        int (* destroy)(fs_node_t *);
    6369        int (* link)(fs_node_t *, fs_node_t *, const char *);
    6470        int (* unlink)(fs_node_t *, fs_node_t *, const char *);
     71        int (* has_children)(bool *, fs_node_t *);
     72        /*
     73         * The second set of methods are usually mere getters that do not return
     74         * an integer error code.
     75         */
    6576        fs_index_t (* index_get)(fs_node_t *);
    6677        size_t (* size_get)(fs_node_t *);
    6778        unsigned (* lnkcnt_get)(fs_node_t *);
    68         bool (* has_children)(fs_node_t *);
    69         fs_node_t *(* root_get)(dev_handle_t);
    7079        char (* plb_get_char)(unsigned pos);
    7180        bool (* is_directory)(fs_node_t *);
  • uspace/lib/softfloat/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Common compiler flags
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../libc
     32.PHONY: all clean
    3333
    34 ## Setup toolchain
    35 #
    36 
    37 include $(LIBC_PREFIX)/Makefile.toolchain
    38 
    39 CFLAGS += -Iinclude -Iarch/$(UARCH)/include/
    40 
    41 ## Sources
    42 #
    43 
    44 GENERIC_SOURCES = \
    45         generic/add.c \
    46         generic/common.c \
    47         generic/comparison.c \
    48         generic/conversion.c \
    49         generic/div.c \
    50         generic/mul.c \
    51         generic/other.c \
    52         generic/softfloat.c \
    53         generic/sub.c
    54 
    55 ARCH_SOURCES =
    56 
    57 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
    58 
    59 .PHONY: all clean depend
    60 
    61 all: libsoftfloat.a
    62 
    63 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBC_PREFIX)/libc.a
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    6437
    6538clean:
    66         -rm -f libsoftfloat.a Makefile.depend
    67         find generic/ -name '*.o' -follow -exec rm \{\} \;
    68 
    69 depend:
    70         -makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
    71 
    72 libsoftfloat.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
    73         $(AR) rc libsoftfloat.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
    74 
    75 %.o: %.S
    76         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    77 
    78 %.o: %.s
    79         $(AS) $(AFLAGS) $< -o $@
    80 
    81 %.o: %.c
    82         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(LIBSOFTFLOAT)
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/lib/softint/Makefile

    rfcbd1be r1787e527  
    11#
    22# Copyright (c) 2005 Martin Decky
     3# Copyright (c) 2007 Jakub Jermar
    34# All rights reserved.
    45#
     
    2728#
    2829
    29 ## Common compiler flags
    30 #
     30include Makefile.common
    3131
    32 LIBC_PREFIX = ../libc
     32.PHONY: all clean
    3333
    34 ## Setup toolchain
    35 #
    36 
    37 include $(LIBC_PREFIX)/Makefile.toolchain
    38 
    39 CFLAGS += -Iinclude
    40 
    41 ## Sources
    42 #
    43 
    44 ARCH_SOURCES =
    45 
    46 GENERIC_SOURCES = \
    47         generic/division.c
    48 
    49 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
    50 
    51 .PHONY: all clean depend
    52 
    53 all: libsoftint.a
    54 
    55 -include Makefile.depend
     34all: $(LIBC_PREFIX)/../../../Makefile.config $(LIBC_PREFIX)/../../../config.h $(LIBC_PREFIX)/../../../config.defs $(LIBC_PREFIX)/libc.a
     35        -[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
     36        $(MAKE) -f Makefile.build
    5637
    5738clean:
    58         -rm -f libsoftint.a Makefile.depend
    59         find generic/ -name '*.o' -follow -exec rm \{\} \;
    60 
    61 depend:
    62         -makedepend -f - -- $(DEPEMD_DEFS) $(CFLAGS) -- $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
    63 
    64 libsoftint.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
    65         $(AR) rc libsoftint.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
    66 
    67 %.o: %.S
    68         $(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
    69 
    70 %.o: %.s
    71         $(AS) $(AFLAGS) $< -o $@
    72 
    73 %.o: %.c
    74         $(CC) $(DEFS) $(CFLAGS) -c $< -o $@
     39        rm -f $(DEPEND) $(DEPEND_PREV) $(LIBSOFTINT)
     40        find . -name '*.o' -follow -exec rm \{\} \;
  • uspace/lib/softint/include/multiplication.h

    rfcbd1be r1787e527  
    11/*
    2  * Copyright (c) 2005 Jakub Jermar
     2 * Copyright (c) 2009 Josef Cejka
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 /** @addtogroup ia32   
     29/** @addtogroup softint
    3030 * @{
    31  */
    32 /** @file
     31 */
     32/**
     33 * @file
    3334 */
    3435
    35 #ifndef KERN_ia32_ARG_H_
    36 #define KERN_ia32_ARG_H_
     36#ifndef __SOFTINT_MULTIPLICATION_H__
     37#define __SOFTINT_MULTIPLICATION_H__
    3738
    38 #include <stackarg.h>
     39/* 64 bit multiplication */
     40long long __muldi3(long long a, long long b);
    3941
    4042#endif
     
    4244/** @}
    4345 */
     46
     47
Note: See TracChangeset for help on using the changeset viewer.