Changeset b800b0e in mainline for uspace/lib


Ignore:
Timestamp:
2012-10-23T13:16:49Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6ecf5b8
Parents:
32b3a12 (diff), b2ac3998 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

Location:
uspace/lib
Files:
43 added
1 deleted
48 edited
20 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/block/block.c

    r32b3a12 rb800b0e  
    6262static LIST_INITIALIZE(dcl);
    6363
    64 #define CACHE_BUCKETS_LOG2  10
    65 #define CACHE_BUCKETS       (1 << CACHE_BUCKETS_LOG2)
    6664
    6765typedef struct {
     
    233231}
    234232
    235 static hash_index_t cache_hash(unsigned long *key)
    236 {
    237         return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
    238 }
    239 
    240 static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item)
    241 {
    242         block_t *b = hash_table_get_instance(item, block_t, hash_link);
    243         return b->lba == MERGE_LOUP32(key[0], key[1]);
    244 }
    245 
    246 static void cache_remove_callback(link_t *item)
    247 {
    248 }
    249 
    250 static hash_table_operations_t cache_ops = {
     233static size_t cache_key_hash(void *key)
     234{
     235        aoff64_t *lba = (aoff64_t*)key;
     236        return *lba;
     237}
     238
     239static size_t cache_hash(const ht_link_t *item)
     240{
     241        block_t *b = hash_table_get_inst(item, block_t, hash_link);
     242        return b->lba;
     243}
     244
     245static bool cache_key_equal(void *key, const ht_link_t *item)
     246{
     247        aoff64_t *lba = (aoff64_t*)key;
     248        block_t *b = hash_table_get_inst(item, block_t, hash_link);
     249        return b->lba == *lba;
     250}
     251
     252
     253static hash_table_ops_t cache_ops = {
    251254        .hash = cache_hash,
    252         .compare = cache_compare,
    253         .remove_callback = cache_remove_callback
     255        .key_hash = cache_key_hash,
     256        .key_equal = cache_key_equal,
     257        .equal = NULL,
     258        .remove_callback = NULL
    254259};
    255260
     
    282287        cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
    283288
    284         if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
    285             &cache_ops)) {
     289        if (!hash_table_create(&cache->block_hash, 0, 0, &cache_ops)) {
    286290                free(cache);
    287291                return ENOMEM;
     
    321325                }
    322326
    323                 unsigned long key[2] = {
    324                         LOWER32(b->lba),
    325                         UPPER32(b->lba)
    326                 };
    327                 hash_table_remove(&cache->block_hash, key, 2);
     327                hash_table_remove_item(&cache->block_hash, &b->hash_link);
    328328               
    329329                free(b->data);
     
    357357        fibril_rwlock_initialize(&b->contents_lock);
    358358        link_initialize(&b->free_link);
    359         link_initialize(&b->hash_link);
    360359}
    361360
     
    377376        cache_t *cache;
    378377        block_t *b;
    379         link_t *l;
    380         unsigned long key[2] = {
    381                 LOWER32(ba),
    382                 UPPER32(ba)
    383         };
     378        link_t *link;
    384379
    385380        int rc;
     
    397392
    398393        fibril_mutex_lock(&cache->lock);
    399         l = hash_table_find(&cache->block_hash, key);
    400         if (l) {
     394        ht_link_t *hlink = hash_table_find(&cache->block_hash, &ba);
     395        if (hlink) {
    401396found:
    402397                /*
    403398                 * We found the block in the cache.
    404399                 */
    405                 b = hash_table_get_instance(l, block_t, hash_link);
     400                b = hash_table_get_inst(hlink, block_t, hash_link);
    406401                fibril_mutex_lock(&b->lock);
    407402                if (b->refcnt++ == 0)
     
    441436                                goto out;
    442437                        }
    443                         l = list_first(&cache->free_list);
    444                         b = list_get_instance(l, block_t, free_link);
     438                        link = list_first(&cache->free_list);
     439                        b = list_get_instance(link, block_t, free_link);
    445440
    446441                        fibril_mutex_lock(&b->lock);
     
    479474                                        goto retry;
    480475                                }
    481                                 l = hash_table_find(&cache->block_hash, key);
    482                                 if (l) {
     476                                hlink = hash_table_find(&cache->block_hash, &ba);
     477                                if (hlink) {
    483478                                        /*
    484479                                         * Someone else must have already
     
    502497                         */
    503498                        list_remove(&b->free_link);
    504                         unsigned long temp_key[2] = {
    505                                 LOWER32(b->lba),
    506                                 UPPER32(b->lba)
    507                         };
    508                         hash_table_remove(&cache->block_hash, temp_key, 2);
     499                        hash_table_remove_item(&cache->block_hash, &b->hash_link);
    509500                }
    510501
     
    514505                b->lba = ba;
    515506                b->pba = ba_ltop(devcon, b->lba);
    516                 hash_table_insert(&cache->block_hash, key, &b->hash_link);
     507                hash_table_insert(&cache->block_hash, &b->hash_link);
    517508
    518509                /*
     
    622613                         * Take the block out of the cache and free it.
    623614                         */
    624                         unsigned long key[2] = {
    625                                 LOWER32(block->lba),
    626                                 UPPER32(block->lba)
    627                         };
    628                         hash_table_remove(&cache->block_hash, key, 2);
     615                        hash_table_remove_item(&cache->block_hash, &block->hash_link);
    629616                        fibril_mutex_unlock(&block->lock);
    630617                        free(block->data);
  • uspace/lib/block/block.h

    r32b3a12 rb800b0e  
    8484        link_t free_link;
    8585        /** Link for placing the block into the block hash table. */
    86         link_t hash_link;
     86        ht_link_t hash_link;
    8787        /** Buffer with the block data. */
    8888        void *data;
  • uspace/lib/c/Makefile

    r32b3a12 rb800b0e  
    7171        generic/device/hw_res_parsed.c \
    7272        generic/device/char_dev.c \
     73        generic/device/clock_dev.c \
     74        generic/device/battery_dev.c \
    7375        generic/device/graph_dev.c \
    7476        generic/device/nic.c \
    7577        generic/device/pci.c \
    7678        generic/device/ahci.c \
     79        generic/dlfcn.c \
    7780        generic/elf/elf_load.c \
    7881        generic/event.c \
     
    101104        generic/io/printf.c \
    102105        generic/io/log.c \
     106        generic/io/logctl.c \
    103107        generic/io/klog.c \
    104108        generic/io/snprintf.c \
     
    121125        generic/adt/list.c \
    122126        generic/adt/hash_table.c \
    123         generic/adt/hash_set.c \
    124127        generic/adt/dynamic_fifo.c \
    125128        generic/adt/char_map.c \
     
    142145ifeq ($(CONFIG_RTLD),y)
    143146        GENERIC_SOURCES += \
    144                 generic/dlfcn.c \
    145147                generic/rtld/rtld.c \
    146148                generic/rtld/dynamic.c \
  • uspace/lib/c/arch/abs32le/_link.ld.in

    r32b3a12 rb800b0e  
    1515#ifdef LOADER
    1616        . = 0x70001000 + SIZEOF_HEADERS;
    17        
    18         .interp : {
    19                 *(.interp);
    20         } :interp :text
    2117#else
    2218        . = 0x1000 + SIZEOF_HEADERS;
    2319#endif
    24        
    25         /* Make sure the code is aligned reasonably */
    26         . = ALIGN(., 16);
    2720       
    2821        .text : {
     
    3023                *(.rodata .rodata.*);
    3124        } :text
     25       
     26#ifdef LOADER
     27        .interp : {
     28                *(.interp);
     29        } :interp :text
     30#endif
    3231       
    3332        . = . + 0x1000;
  • uspace/lib/c/arch/amd64/_link.ld.in

    r32b3a12 rb800b0e  
    1616#ifdef LOADER
    1717        . = 0x70001000 + SIZEOF_HEADERS;
    18        
    19         .interp : {
    20                 *(.interp);
    21         } :interp :text
    2218#else
    2319        . = 0x1000 + SIZEOF_HEADERS;
    2420#endif
    25        
    26         /* Make sure the code is aligned reasonably */
    27         . = ALIGN(., 16);
    2821       
    2922        .init : {
     
    3528                *(.rodata .rodata.*);
    3629        } :text
     30       
     31#ifdef LOADER
     32        .interp : {
     33                *(.interp);
     34        } :interp :text
     35#endif
    3736       
    3837        . = . + 0x1000;
  • uspace/lib/c/arch/arm32/Makefile.common

    r32b3a12 rb800b0e  
    2828#
    2929
    30 GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -march=armv4
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
     31GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -march=armv4 -mapcs-frame
    3132
    3233ENDIANESS = LE
  • uspace/lib/c/arch/arm32/_link.ld.in

    r32b3a12 rb800b0e  
    1515#ifdef LOADER
    1616        . = 0x70001000 + SIZEOF_HEADERS;
    17        
    18         .interp : {
    19                 *(.interp);
    20         } :interp :text
    2117#else
    2218        . = 0x1000 + SIZEOF_HEADERS;
    2319#endif
    24        
    25         /* Make sure the code is aligned reasonably */
    26         . = ALIGN(., 8);
    2720       
    2821        .init : {
     
    3427                *(.rodata .rodata.*);
    3528        } :text
     29       
     30#ifdef LOADER
     31        .interp : {
     32                *(.interp);
     33        } :interp :text
     34#endif
    3635       
    3736        . = . + 0x1000;
  • uspace/lib/c/arch/ia32/_link.ld.in

    r32b3a12 rb800b0e  
    2424        . = 0x1000 + SIZEOF_HEADERS;
    2525#endif
    26        
    27 #if defined(LOADER) || defined(DLEXE)
    28         .interp : {
    29                 *(.interp);
    30         } :interp :text
    31 #endif
    32        
    33         /* Make sure the code is aligned reasonably */
    34         . = ALIGN(., 16);
    3526       
    3627        .init : {
     
    7162        } :text
    7263#endif
     64       
     65#if defined(LOADER) || defined(DLEXE)
     66        .interp : {
     67                *(.interp);
     68        } :interp :text
     69#endif
     70       
    7371        . = . + 0x1000;
    7472       
  • uspace/lib/c/arch/ia64/_link.ld.in

    r32b3a12 rb800b0e  
    1515#ifdef LOADER
    1616        . = 0x800000000 + SIZEOF_HEADERS;
    17        
    18         .interp : {
    19                 *(.interp);
    20         } :interp :text
    2117#else
    2218        . = 0x4000 + SIZEOF_HEADERS;
    2319#endif
    2420       
    25         /* Make sure the code is aligned reasonably */
     21        /* Workaround proper alignment of the .init section */
    2622        . = ALIGN(., 16);
    2723       
     
    3430                *(.rodata .rodata.*);
    3531        } :text
     32       
     33#ifdef LOADER
     34        .interp : {
     35                *(.interp);
     36        } :interp :text
     37#endif
    3638       
    3739        . = . + 0x4000;
  • uspace/lib/c/arch/mips32/Makefile.common

    r32b3a12 rb800b0e  
    2828
    2929GCC_CFLAGS += -msoft-float -mips3 -mabi=32
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031
    3132ENDIANESS = LE
  • uspace/lib/c/arch/mips32/_link.ld.in

    r32b3a12 rb800b0e  
    1515#ifdef LOADER
    1616        . = 0x70004000 + SIZEOF_HEADERS;
    17        
    18         .interp : {
    19                 *(.interp);
    20         } :interp :text
    2117#else
    2218        . = 0x4000 + SIZEOF_HEADERS;
    2319#endif
    24        
    25         /* Make sure the code is aligned reasonably */
    26         . = ALIGN(., 16);
    2720       
    2821        .init : {
     
    3427                *(.rodata .rodata.*);
    3528        } :text
     29       
     30#ifdef LOADER
     31        .interp : {
     32                *(.interp);
     33        } :interp :text
     34#endif
    3635       
    3736        . = . + 0x4000;
  • uspace/lib/c/arch/mips32eb/Makefile.common

    r32b3a12 rb800b0e  
    2828
    2929GCC_CFLAGS += -msoft-float -mips3 -mabi=32
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031
    3132ENDIANESS = BE
  • uspace/lib/c/arch/mips64/Makefile.common

    r32b3a12 rb800b0e  
    2828
    2929GCC_CFLAGS += -msoft-float -mips3 -mabi=64
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031AFLAGS = -64
    3132
  • uspace/lib/c/arch/mips64/_link.ld.in

    r32b3a12 rb800b0e  
    1616#ifdef LOADER
    1717        . = 0x70004000 + SIZEOF_HEADERS;
    18        
    19         .interp : {
    20                 *(.interp);
    21         } :interp :text
    2218#else
    2319        . = 0x4000 + SIZEOF_HEADERS;
    2420#endif
    25        
    26         /* Make sure the code is aligned reasonably */
    27         . = ALIGN(., 16);
    2821       
    2922        .init : {
     
    3528                *(.rodata .rodata.*);
    3629        } :text
     30       
     31#ifdef LOADER
     32        .interp : {
     33                *(.interp);
     34        } :interp :text
     35#endif
    3736       
    3837        . = . + 0x4000;
  • uspace/lib/c/arch/ppc32/Makefile.common

    r32b3a12 rb800b0e  
    2828
    2929GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031AFLAGS = -a32
    3132
  • uspace/lib/c/arch/ppc32/_link.ld.in

    r32b3a12 rb800b0e  
    1616#ifdef LOADER
    1717        . = 0x70001000 + SIZEOF_HEADERS;
    18        
    19         .interp : {
    20                 *(.interp);
    21         } :interp :text
    2218#else
    2319        . = 0x1000 + SIZEOF_HEADERS;
    2420#endif
    25        
    26         /* Make sure the code is aligned reasonably */
    27         . = ALIGN(., 4);
    2821       
    2922        .init : {
     
    3528                *(.rodata .rodata.*);
    3629        } :text
     30       
     31#ifdef LOADER
     32        .interp : {
     33                *(.interp);
     34        } :interp :text
     35#endif
    3736       
    3837        . = . + 0x1000;
  • uspace/lib/c/arch/sparc64/_link.ld.in

    r32b3a12 rb800b0e  
    1515#ifdef LOADER
    1616        . = 0x70004000 + SIZEOF_HEADERS;
    17        
    18         .interp : {
    19                 *(.interp);
    20         } :interp :text
    2117#else
    2218        . = 0x4000 + SIZEOF_HEADERS;
    2319#endif
    24        
    25         /* Make sure the code is aligned reasonably */
    26         . = ALIGN(., 16);
    2720       
    2821        .init : {
     
    3427                *(.rodata .rodata.*);
    3528        } :text
     29       
     30#ifdef LOADER
     31        .interp : {
     32                *(.interp);
     33        } :interp :text
     34#endif
    3635       
    3736        . = . + 0x4000;
  • uspace/lib/c/generic/adt/hash_table.c

    r32b3a12 rb800b0e  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2012 Adam Hraska
     4 *
    35 * All rights reserved.
    46 *
     
    3436
    3537/*
    36  * This is an implementation of generic chained hash table.
     38 * This is an implementation of a generic resizable chained hash table.
     39 *
     40 * The table grows to 2*n+1 buckets each time, starting at n == 89,
     41 * per Thomas Wang's recommendation:
     42 * http://www.concentric.net/~Ttwang/tech/hashsize.htm
     43 *
     44 * This policy produces prime table sizes for the first five resizes
     45 * and generally produces table sizes which are either prime or
     46 * have fairly large (prime/odd) divisors. Having a prime table size
     47 * mitigates the use of suboptimal hash functions and distributes
     48 * items over the whole table.
    3749 */
    3850
     
    4456#include <str.h>
    4557
     58/* Optimal initial bucket count. See comment above. */
     59#define HT_MIN_BUCKETS  89
     60/* The table is resized when the average load per bucket exceeds this number. */
     61#define HT_MAX_LOAD     2
     62
     63
     64static size_t round_up_size(size_t);
     65static bool alloc_table(size_t, list_t **);
     66static void clear_items(hash_table_t *);
     67static void resize(hash_table_t *, size_t);
     68static void grow_if_needed(hash_table_t *);
     69static void shrink_if_needed(hash_table_t *);
     70
     71/* Dummy do nothing callback to invoke in place of remove_callback == NULL. */
     72static void nop_remove_callback(ht_link_t *item)
     73{
     74        /* no-op */
     75}
     76
     77
    4678/** Create chained hash table.
    4779 *
    4880 * @param h        Hash table structure. Will be initialized by this call.
    49  * @param m        Number of hash table buckets.
     81 * @param init_size Initial desired number of hash table buckets. Pass zero
     82 *                 if you want the default initial size.
    5083 * @param max_keys Maximal number of keys needed to identify an item.
    51  * @param op       Hash table operations structure.
     84 * @param op       Hash table operations structure. remove_callback()
     85 *                 is optional and can be NULL if no action is to be taken
     86 *                 upon removal. equal() is optional if and only if
     87 *                 hash_table_insert_unique() will never be invoked.
     88 *                 All other operations are mandatory.
    5289 *
    5390 * @return True on success
    5491 *
    5592 */
    56 bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
    57     hash_table_operations_t *op)
     93bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_load,
     94    hash_table_ops_t *op)
    5895{
    5996        assert(h);
    60         assert(op && op->hash && op->compare);
    61         assert(max_keys > 0);
    62        
    63         h->entry = malloc(m * sizeof(list_t));
    64         if (!h->entry)
     97        assert(op && op->hash && op->key_hash && op->key_equal);
     98       
     99        /* Check for compulsory ops. */
     100        if (!op || !op->hash || !op->key_hash || !op->key_equal)
    65101                return false;
    66102       
    67         memset((void *) h->entry, 0,  m * sizeof(list_t));
    68        
    69         hash_count_t i;
    70         for (i = 0; i < m; i++)
    71                 list_initialize(&h->entry[i]);
    72        
    73         h->entries = m;
    74         h->max_keys = max_keys;
     103        h->bucket_cnt = round_up_size(init_size);
     104       
     105        if (!alloc_table(h->bucket_cnt, &h->bucket))
     106                return false;
     107       
     108        h->max_load = (max_load == 0) ? HT_MAX_LOAD : max_load;
     109        h->item_cnt = 0;
    75110        h->op = op;
     111        h->full_item_cnt = h->max_load * h->bucket_cnt;
     112        h->apply_ongoing = false;
     113
     114        if (h->op->remove_callback == NULL) {
     115                h->op->remove_callback = nop_remove_callback;
     116        }
    76117       
    77118        return true;
    78119}
    79120
     121/** Destroy a hash table instance.
     122 *
     123 * @param h Hash table to be destroyed.
     124 *
     125 */
     126void hash_table_destroy(hash_table_t *h)
     127{
     128        assert(h && h->bucket);
     129        assert(!h->apply_ongoing);
     130       
     131        clear_items(h);
     132       
     133        free(h->bucket);
     134
     135        h->bucket = 0;
     136        h->bucket_cnt = 0;
     137}
     138
     139/** Returns true if there are no items in the table. */
     140bool hash_table_empty(hash_table_t *h)
     141{
     142        assert(h && h->bucket);
     143        return h->item_cnt == 0;
     144}
     145
     146/** Returns the number of items in the table. */
     147size_t hash_table_size(hash_table_t *h)
     148{
     149        assert(h && h->bucket);
     150        return h->item_cnt;
     151}
     152
    80153/** Remove all elements from the hash table
    81154 *
     
    84157void hash_table_clear(hash_table_t *h)
    85158{
    86         for (hash_count_t chain = 0; chain < h->entries; ++chain) {
    87                 link_t *cur;
    88                 link_t *next;
    89                
    90                 for (cur = h->entry[chain].head.next;
    91                     cur != &h->entry[chain].head;
    92                     cur = next) {
    93                         next = cur->next;
     159        assert(h && h->bucket);
     160        assert(!h->apply_ongoing);
     161       
     162        clear_items(h);
     163       
     164        /* Shrink the table to its minimum size if possible. */
     165        if (HT_MIN_BUCKETS < h->bucket_cnt) {
     166                resize(h, HT_MIN_BUCKETS);
     167        }
     168}
     169
     170/** Unlinks and removes all items but does not resize. */
     171static void clear_items(hash_table_t *h)
     172{
     173        if (h->item_cnt == 0)
     174                return;
     175       
     176        for (size_t idx = 0; idx < h->bucket_cnt; ++idx) {
     177                list_foreach_safe(h->bucket[idx], cur, next) {
     178                        assert(cur);
     179                        ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     180                       
    94181                        list_remove(cur);
    95                         h->op->remove_callback(cur);
    96                 }
    97         }
    98 }
    99 
    100 /** Destroy a hash table instance.
    101  *
    102  * @param h Hash table to be destroyed.
    103  *
    104  */
    105 void hash_table_destroy(hash_table_t *h)
    106 {
    107         assert(h);
    108         assert(h->entry);
    109        
    110         free(h->entry);
     182                        h->op->remove_callback(cur_link);
     183                }
     184        }
     185       
     186        h->item_cnt = 0;
    111187}
    112188
     
    117193 * @param item Item to be inserted into the hash table.
    118194 */
    119 void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
     195void hash_table_insert(hash_table_t *h, ht_link_t *item)
    120196{
    121197        assert(item);
    122         assert(h && h->op && h->op->hash && h->op->compare);
    123        
    124         hash_index_t chain = h->op->hash(key);
    125         assert(chain < h->entries);
    126        
    127         list_append(item, &h->entry[chain]);
     198        assert(h && h->bucket);
     199        assert(!h->apply_ongoing);
     200       
     201        size_t idx = h->op->hash(item) % h->bucket_cnt;
     202       
     203        list_append(&item->link, &h->bucket[idx]);
     204        ++h->item_cnt;
     205        grow_if_needed(h);
     206}
     207
     208
     209/** Insert item into a hash table if not already present.
     210 *
     211 * @param h    Hash table.
     212 * @param key  Array of all keys necessary to compute hash index.
     213 * @param item Item to be inserted into the hash table.
     214 *
     215 * @return False if such an item had already been inserted.
     216 * @return True if the inserted item was the only item with such a lookup key.
     217 */
     218bool hash_table_insert_unique(hash_table_t *h, ht_link_t *item)
     219{
     220        assert(item);
     221        assert(h && h->bucket && h->bucket_cnt);
     222        assert(h->op && h->op->hash && h->op->equal);
     223        assert(!h->apply_ongoing);
     224       
     225        size_t idx = h->op->hash(item) % h->bucket_cnt;
     226       
     227        /* Check for duplicates. */
     228        list_foreach(h->bucket[idx], cur) {
     229                /*
     230                 * We could filter out items using their hashes first, but
     231                 * calling equal() might very well be just as fast.
     232                 */
     233                ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     234                if (h->op->equal(cur_link, item))
     235                        return false;
     236        }
     237       
     238        list_append(&item->link, &h->bucket[idx]);
     239        ++h->item_cnt;
     240        grow_if_needed(h);
     241       
     242        return true;
    128243}
    129244
     
    136251 *
    137252 */
    138 link_t *hash_table_find(hash_table_t *h, unsigned long key[])
    139 {
    140         assert(h && h->op && h->op->hash && h->op->compare);
    141        
    142         hash_index_t chain = h->op->hash(key);
    143         assert(chain < h->entries);
    144        
    145         list_foreach(h->entry[chain], cur) {
    146                 if (h->op->compare(key, h->max_keys, cur)) {
    147                         /*
    148                          * The entry is there.
    149                          */
    150                         return cur;
    151                 }
    152         }
    153        
     253ht_link_t *hash_table_find(const hash_table_t *h, void *key)
     254{
     255        assert(h && h->bucket);
     256       
     257        size_t idx = h->op->key_hash(key) % h->bucket_cnt;
     258
     259        list_foreach(h->bucket[idx], cur) {
     260                ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     261                /*
     262                 * Is this is the item we are looking for? We could have first
     263                 * checked if the hashes match but op->key_equal() may very well be
     264                 * just as fast as op->hash().
     265                 */
     266                if (h->op->key_equal(key, cur_link)) {
     267                        return cur_link;
     268                }
     269        }
     270       
     271        return NULL;
     272}
     273
     274/** Find the next item equal to item. */
     275ht_link_t *hash_table_find_next(const hash_table_t *h, ht_link_t *item)
     276{
     277        assert(item);
     278        assert(h && h->bucket);
     279
     280        /* Traverse the circular list until we reach the starting item again. */
     281        for (link_t *cur = item->link.next; cur != &item->link; cur = cur->next) {
     282                assert(cur);
     283                ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     284                /*
     285                 * Is this is the item we are looking for? We could have first
     286                 * checked if the hashes match but op->equal() may very well be
     287                 * just as fast as op->hash().
     288                 */
     289                if (h->op->equal(cur_link, item)) {
     290                        return cur_link;
     291                }
     292        }
     293
    154294        return NULL;
    155295}
     
    163303 *             the hash table.
    164304 * @param keys Number of keys in the 'key' array.
    165  *
    166  */
    167 void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
    168 {
    169         assert(h && h->op && h->op->hash && h->op->compare &&
    170             h->op->remove_callback);
    171         assert(keys <= h->max_keys);
    172        
    173         if (keys == h->max_keys) {
    174                 /*
    175                  * All keys are known, hash_table_find() can be used to find the
    176                  * entry.
     305 *
     306 * @return Returns the number of removed items.
     307 */
     308size_t hash_table_remove(hash_table_t *h, void *key)
     309{
     310        assert(h && h->bucket);
     311        assert(!h->apply_ongoing);
     312       
     313        size_t idx = h->op->key_hash(key) % h->bucket_cnt;
     314
     315        size_t removed = 0;
     316       
     317        list_foreach_safe(h->bucket[idx], cur, next) {
     318                ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     319               
     320                if (h->op->key_equal(key, cur_link)) {
     321                        ++removed;
     322                        list_remove(cur);
     323                        h->op->remove_callback(cur_link);
     324                }
     325        }
     326
     327        h->item_cnt -= removed;
     328        shrink_if_needed(h);
     329       
     330        return removed;
     331}
     332
     333/** Removes an item already present in the table. The item must be in the table.*/
     334void hash_table_remove_item(hash_table_t *h, ht_link_t *item)
     335{
     336        assert(item);
     337        assert(h && h->bucket);
     338        assert(link_in_use(&item->link));
     339
     340        list_remove(&item->link);
     341        --h->item_cnt;
     342        h->op->remove_callback(item);
     343        shrink_if_needed(h);
     344}
     345
     346/** Apply function to all items in hash table.
     347 *
     348 * @param h   Hash table.
     349 * @param f   Function to be applied. Return false if no more items
     350 *            should be visited. The functor may only delete the supplied
     351 *            item. It must not delete the successor of the item passed
     352 *            in the first argument.
     353 * @param arg Argument to be passed to the function.
     354 */
     355void hash_table_apply(hash_table_t *h, bool (*f)(ht_link_t *, void *), void *arg)
     356{       
     357        assert(f);
     358        assert(h && h->bucket);
     359       
     360        if (h->item_cnt == 0)
     361                return;
     362       
     363        h->apply_ongoing = true;
     364       
     365        for (size_t idx = 0; idx < h->bucket_cnt; ++idx) {
     366                list_foreach_safe(h->bucket[idx], cur, next) {
     367                        ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     368                        /*
     369                         * The next pointer had already been saved. f() may safely
     370                         * delete cur (but not next!).
     371                         */
     372                        if (!f(cur_link, arg))
     373                                return;
     374                }
     375        }
     376       
     377        h->apply_ongoing = false;
     378       
     379        shrink_if_needed(h);
     380        grow_if_needed(h);
     381}
     382
     383/** Rounds up size to the nearest suitable table size. */
     384static size_t round_up_size(size_t size)
     385{
     386        size_t rounded_size = HT_MIN_BUCKETS;
     387       
     388        while (rounded_size < size) {
     389                rounded_size = 2 * rounded_size + 1;
     390        }
     391       
     392        return rounded_size;
     393}
     394
     395/** Allocates and initializes the desired number of buckets. True if successful.*/
     396static bool alloc_table(size_t bucket_cnt, list_t **pbuckets)
     397{
     398        assert(pbuckets && HT_MIN_BUCKETS <= bucket_cnt);
     399               
     400        list_t *buckets = malloc(bucket_cnt * sizeof(list_t));
     401        if (!buckets)
     402                return false;
     403       
     404        for (size_t i = 0; i < bucket_cnt; i++)
     405                list_initialize(&buckets[i]);
     406
     407        *pbuckets = buckets;
     408        return true;
     409}
     410
     411
     412/** Shrinks the table if the table is only sparely populated. */
     413static inline void shrink_if_needed(hash_table_t *h)
     414{
     415        if (h->item_cnt <= h->full_item_cnt / 4 && HT_MIN_BUCKETS < h->bucket_cnt) {
     416                /*
     417                 * Keep the bucket_cnt odd (possibly also prime).
     418                 * Shrink from 2n + 1 to n. Integer division discards the +1.
    177419                 */
    178                
    179                 link_t *cur = hash_table_find(h, key);
    180                 if (cur) {
    181                         list_remove(cur);
    182                         h->op->remove_callback(cur);
    183                 }
    184                
     420                size_t new_bucket_cnt = h->bucket_cnt / 2;
     421                resize(h, new_bucket_cnt);
     422        }
     423}
     424
     425/** Grows the table if table load exceeds the maximum allowed. */
     426static inline void grow_if_needed(hash_table_t *h)
     427{
     428        /* Grow the table if the average bucket load exceeds the maximum. */
     429        if (h->full_item_cnt < h->item_cnt) {
     430                /* Keep the bucket_cnt odd (possibly also prime). */
     431                size_t new_bucket_cnt = 2 * h->bucket_cnt + 1;
     432                resize(h, new_bucket_cnt);
     433        }
     434}
     435
     436/** Allocates and rehashes items to a new table. Frees the old table. */
     437static void resize(hash_table_t *h, size_t new_bucket_cnt)
     438{
     439        assert(h && h->bucket);
     440        assert(HT_MIN_BUCKETS <= new_bucket_cnt);
     441       
     442        /* We are traversing the table and resizing would mess up the buckets. */
     443        if (h->apply_ongoing)
    185444                return;
    186         }
    187        
    188         /*
    189          * Fewer keys were passed.
    190          * Any partially matching entries are to be removed.
    191          */
    192         hash_index_t chain;
    193         for (chain = 0; chain < h->entries; chain++) {
    194                 for (link_t *cur = h->entry[chain].head.next;
    195                     cur != &h->entry[chain].head;
    196                     cur = cur->next) {
    197                         if (h->op->compare(key, keys, cur)) {
    198                                 link_t *hlp;
    199                                
    200                                 hlp = cur;
    201                                 cur = cur->prev;
    202                                
    203                                 list_remove(hlp);
    204                                 h->op->remove_callback(hlp);
    205                                
    206                                 continue;
     445       
     446        list_t *new_buckets;
     447
     448        /* Leave the table as is if we cannot resize. */
     449        if (!alloc_table(new_bucket_cnt, &new_buckets))
     450                return;
     451       
     452        if (0 < h->item_cnt) {
     453                /* Rehash all the items to the new table. */
     454                for (size_t old_idx = 0; old_idx < h->bucket_cnt; ++old_idx) {
     455                        list_foreach_safe(h->bucket[old_idx], cur, next) {
     456                                ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link);
     457
     458                                size_t new_idx = h->op->hash(cur_link) % new_bucket_cnt;
     459                                list_remove(cur);
     460                                list_append(cur, &new_buckets[new_idx]);
    207461                        }
    208462                }
    209463        }
    210 }
    211 
    212 /** Apply function to all items in hash table.
    213  *
    214  * @param h   Hash table.
    215  * @param f   Function to be applied.
    216  * @param arg Argument to be passed to the function.
    217  *
    218  */
    219 void hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg)
    220 {       
    221         for (hash_index_t bucket = 0; bucket < h->entries; bucket++) {
    222                 link_t *cur;
    223                 link_t *next;
    224 
    225                 for (cur = h->entry[bucket].head.next; cur != &h->entry[bucket].head;
    226                     cur = next) {
    227                         /*
    228                          * The next pointer must be stored prior to the functor
    229                          * call to allow using destructor as the functor (the
    230                          * free function could overwrite the cur->next pointer).
    231                          */
    232                         next = cur->next;
    233                         f(cur, arg);
    234                 }
    235         }
    236 }
     464       
     465        free(h->bucket);
     466        h->bucket = new_buckets;
     467        h->bucket_cnt = new_bucket_cnt;
     468        h->full_item_cnt = h->max_load * h->bucket_cnt;
     469}
     470
    237471
    238472/** @}
  • uspace/lib/c/generic/async.c

    r32b3a12 rb800b0e  
    116116#include "private/libc.h"
    117117
    118 #define CLIENT_HASH_TABLE_BUCKETS  32
    119 #define CONN_HASH_TABLE_BUCKETS    32
    120118
    121119/** Session data */
     
    205203/* Client connection data */
    206204typedef struct {
    207         link_t link;
     205        ht_link_t link;
    208206       
    209207        task_id_t in_task_id;
     
    217215       
    218216        /** Hash table link. */
    219         link_t link;
     217        ht_link_t link;
    220218       
    221219        /** Incoming client task ID. */
     
    393391static LIST_INITIALIZE(timeout_list);
    394392
    395 static hash_index_t client_hash(unsigned long key[])
    396 {
    397         assert(key);
    398        
    399         return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
    400 }
    401 
    402 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
    403 {
    404         assert(key);
    405         assert(keys == 2);
    406         assert(item);
    407        
    408         client_t *client = hash_table_get_instance(item, client_t, link);
    409         return (key[0] == LOWER32(client->in_task_id) &&
    410             (key[1] == UPPER32(client->in_task_id)));
    411 }
    412 
    413 static void client_remove(link_t *item)
    414 {
    415 }
     393static size_t client_key_hash(void *k)
     394{
     395        task_id_t key = *(task_id_t*)k;
     396        return key;
     397}
     398
     399static size_t client_hash(const ht_link_t *item)
     400{
     401        client_t *client = hash_table_get_inst(item, client_t, link);
     402        return client_key_hash(&client->in_task_id);
     403}
     404
     405static bool client_key_equal(void *k, const ht_link_t *item)
     406{
     407        task_id_t key = *(task_id_t*)k;
     408        client_t *client = hash_table_get_inst(item, client_t, link);
     409        return key == client->in_task_id;
     410}
     411
    416412
    417413/** Operations for the client hash table. */
    418 static hash_table_operations_t client_hash_table_ops = {
     414static hash_table_ops_t client_hash_table_ops = {
    419415        .hash = client_hash,
    420         .compare = client_compare,
    421         .remove_callback = client_remove
     416        .key_hash = client_key_hash,
     417        .key_equal = client_key_equal,
     418        .equal = NULL,
     419        .remove_callback = NULL
    422420};
    423421
     
    429427 *
    430428 */
    431 static hash_index_t conn_hash(unsigned long key[])
    432 {
    433         assert(key);
    434        
    435         return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
    436 }
    437 
    438 /** Compare hash table item with a key.
    439  *
    440  * @param key  Array containing the source phone hash as the only item.
    441  * @param keys Expected 1 but ignored.
    442  * @param item Connection hash table item.
    443  *
    444  * @return True on match, false otherwise.
    445  *
    446  */
    447 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
    448 {
    449         assert(key);
    450         assert(item);
    451        
    452         connection_t *conn = hash_table_get_instance(item, connection_t, link);
    453         return (key[0] == conn->in_phone_hash);
    454 }
    455 
    456 static void conn_remove(link_t *item)
    457 {
    458 }
     429static size_t conn_key_hash(void *key)
     430{
     431        sysarg_t in_phone_hash  = *(sysarg_t*)key;
     432        return in_phone_hash ;
     433}
     434
     435static size_t conn_hash(const ht_link_t *item)
     436{
     437        connection_t *conn = hash_table_get_inst(item, connection_t, link);
     438        return conn_key_hash(&conn->in_phone_hash);
     439}
     440
     441static bool conn_key_equal(void *key, const ht_link_t *item)
     442{
     443        sysarg_t in_phone_hash = *(sysarg_t*)key;
     444        connection_t *conn = hash_table_get_inst(item, connection_t, link);
     445        return (in_phone_hash == conn->in_phone_hash);
     446}
     447
    459448
    460449/** Operations for the connection hash table. */
    461 static hash_table_operations_t conn_hash_table_ops = {
     450static hash_table_ops_t conn_hash_table_ops = {
    462451        .hash = conn_hash,
    463         .compare = conn_compare,
    464         .remove_callback = conn_remove
     452        .key_hash = conn_key_hash,
     453        .key_equal = conn_key_equal,
     454        .equal = NULL,
     455        .remove_callback = NULL
    465456};
    466457
     
    510501        futex_down(&async_futex);
    511502       
    512         unsigned long key = call->in_phone_hash;
    513         link_t *hlp = hash_table_find(&conn_hash_table, &key);
     503        ht_link_t *hlp = hash_table_find(&conn_hash_table, &call->in_phone_hash);
    514504       
    515505        if (!hlp) {
     
    518508        }
    519509       
    520         connection_t *conn = hash_table_get_instance(hlp, connection_t, link);
     510        connection_t *conn = hash_table_get_inst(hlp, connection_t, link);
    521511       
    522512        msg_t *msg = malloc(sizeof(*msg));
     
    638628       
    639629        if (usecs) {
    640                 gettimeofday(&conn->wdata.to_event.expires, NULL);
     630                getuptime(&conn->wdata.to_event.expires);
    641631                tv_add(&conn->wdata.to_event.expires, usecs);
    642632        } else
     
    698688static client_t *async_client_get(task_id_t client_id, bool create)
    699689{
    700         unsigned long key[2] = {
    701                 LOWER32(client_id),
    702                 UPPER32(client_id),
    703         };
    704690        client_t *client = NULL;
    705691
    706692        futex_down(&async_futex);
    707         link_t *lnk = hash_table_find(&client_hash_table, key);
     693        ht_link_t *lnk = hash_table_find(&client_hash_table, &client_id);
    708694        if (lnk) {
    709                 client = hash_table_get_instance(lnk, client_t, link);
     695                client = hash_table_get_inst(lnk, client_t, link);
    710696                atomic_inc(&client->refcnt);
    711697        } else if (create) {
     
    716702               
    717703                        atomic_set(&client->refcnt, 1);
    718                         hash_table_insert(&client_hash_table, key, &client->link);
     704                        hash_table_insert(&client_hash_table, &client->link);
    719705                }
    720706        }
     
    727713{
    728714        bool destroy;
    729         unsigned long key[2] = {
    730                 LOWER32(client->in_task_id),
    731                 UPPER32(client->in_task_id)
    732         };
    733        
     715
    734716        futex_down(&async_futex);
    735717       
    736718        if (atomic_predec(&client->refcnt) == 0) {
    737                 hash_table_remove(&client_hash_table, key, 2);
     719                hash_table_remove(&client_hash_table, &client->in_task_id);
    738720                destroy = true;
    739721        } else
     
    831813         */
    832814        futex_down(&async_futex);
    833         unsigned long key = fibril_connection->in_phone_hash;
    834         hash_table_remove(&conn_hash_table, &key, 1);
     815        hash_table_remove(&conn_hash_table, &fibril_connection->in_phone_hash);
    835816        futex_up(&async_futex);
    836817       
     
    916897       
    917898        /* Add connection to the connection hash table */
    918         unsigned long key = conn->in_phone_hash;
    919899       
    920900        futex_down(&async_futex);
    921         hash_table_insert(&conn_hash_table, &key, &conn->link);
     901        hash_table_insert(&conn_hash_table, &conn->link);
    922902        futex_up(&async_futex);
    923903       
     
    967947{
    968948        struct timeval tv;
    969         gettimeofday(&tv, NULL);
     949        getuptime(&tv);
    970950       
    971951        futex_down(&async_futex);
     
    10241004                       
    10251005                        struct timeval tv;
    1026                         gettimeofday(&tv, NULL);
     1006                        getuptime(&tv);
    10271007                       
    10281008                        if (tv_gteq(&tv, &waiter->to_event.expires)) {
     
    11111091void __async_init(void)
    11121092{
    1113         if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
    1114             2, &client_hash_table_ops))
     1093        if (!hash_table_create(&client_hash_table, 0, 0, &client_hash_table_ops))
    11151094                abort();
    11161095       
    1117         if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
    1118             1, &conn_hash_table_ops))
     1096        if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops))
    11191097                abort();
    11201098       
     
    13311309                timeout = 0;
    13321310
    1333         gettimeofday(&msg->wdata.to_event.expires, NULL);
     1311        getuptime(&msg->wdata.to_event.expires);
    13341312        tv_add(&msg->wdata.to_event.expires, timeout);
    13351313       
     
    14131391        msg->wdata.fid = fibril_get_id();
    14141392       
    1415         gettimeofday(&msg->wdata.to_event.expires, NULL);
     1393        getuptime(&msg->wdata.to_event.expires);
    14161394        tv_add(&msg->wdata.to_event.expires, timeout);
    14171395       
  • uspace/lib/c/generic/dlfcn.c

    r32b3a12 rb800b0e  
    3838#include <stdlib.h>
    3939#include <dlfcn.h>
     40
     41#ifdef CONFIG_RTLD
    4042
    4143#include <rtld/module.h>
     
    8789}
    8890
     91#else /* CONFIG_RTLD not defined */
     92
     93void *dlopen(const char *path, int flag)
     94{
     95        return NULL;
     96}
     97
     98void *dlsym(void *mod, const char *sym_name)
     99{
     100        return NULL;
     101}
     102
     103#endif
     104
    89105/** @}
    90106 */
  • uspace/lib/c/generic/fibril_synch.c

    r32b3a12 rb800b0e  
    379379        futex_down(&async_futex);
    380380        if (timeout) {
    381                 gettimeofday(&wdata.to_event.expires, NULL);
     381                getuptime(&wdata.to_event.expires);
    382382                tv_add(&wdata.to_event.expires, timeout);
    383383                async_insert_timeout(&wdata);
  • uspace/lib/c/generic/io/log.c

    r32b3a12 rb800b0e  
    3838#include <stdlib.h>
    3939#include <stdio.h>
    40 
     40#include <async.h>
    4141#include <io/log.h>
    42 
    43 /** Serialization mutex for logging functions. */
    44 static FIBRIL_MUTEX_INITIALIZE(log_serializer);
    45 
    46 /** Current log level. */
    47 static log_level_t log_level;
    48 
    49 static FILE *log_stream;
    50 
     42#include <ipc/logger.h>
     43#include <ns.h>
     44
     45/** Id of the first log we create at logger. */
     46static sysarg_t default_log_id;
     47
     48/** Log messages are printed under this name. */
    5149static const char *log_prog_name;
    5250
    53 /** Prefixes for individual logging levels. */
     51/** Names of individual log levels. */
    5452static const char *log_level_names[] = {
    55         [LVL_FATAL] = "Fatal error",
    56         [LVL_ERROR] = "Error",
    57         [LVL_WARN] = "Warning",
    58         [LVL_NOTE] = "Note",
    59         [LVL_DEBUG] = "Debug",
    60         [LVL_DEBUG2] = "Debug2"
     53        "fatal",
     54        "error",
     55        "warn",
     56        "note",
     57        "debug",
     58        "debug2",
     59        NULL
    6160};
    6261
     62/** IPC session with the logger service. */
     63static async_sess_t *logger_session;
     64
     65/** Maximum length of a single log message (in bytes). */
     66#define MESSAGE_BUFFER_SIZE 4096
     67
     68/** Send formatted message to the logger service.
     69 *
     70 * @param session Initialized IPC session with the logger.
     71 * @param log Log to use.
     72 * @param level Verbosity level of the message.
     73 * @param message The actual message.
     74 * @return Error code of the conversion or EOK on success.
     75 */
     76static int logger_message(async_sess_t *session, log_t log, log_level_t level, char *message)
     77{
     78        async_exch_t *exchange = async_exchange_begin(session);
     79        if (exchange == NULL) {
     80                return ENOMEM;
     81        }
     82        if (log == LOG_DEFAULT)
     83                log = default_log_id;
     84
     85        // FIXME: remove when all USB drivers use libc logging explicitly
     86        str_rtrim(message, '\n');
     87
     88        aid_t reg_msg = async_send_2(exchange, LOGGER_WRITER_MESSAGE,
     89            log, level, NULL);
     90        int rc = async_data_write_start(exchange, message, str_size(message));
     91        sysarg_t reg_msg_rc;
     92        async_wait_for(reg_msg, &reg_msg_rc);
     93
     94        async_exchange_end(exchange);
     95
     96        /*
     97         * Getting ENAK means no-one wants our message. That is not an
     98         * error at all.
     99         */
     100        if (rc == ENAK)
     101                rc = EOK;
     102
     103        if (rc != EOK) {
     104                return rc;
     105        }
     106
     107        return reg_msg_rc;
     108}
     109
     110/** Get name of the log level.
     111 *
     112 * @param level The log level.
     113 * @return String name or "unknown".
     114 */
     115const char *log_level_str(log_level_t level)
     116{
     117        if (level >= LVL_LIMIT)
     118                return "unknown";
     119        else
     120                return log_level_names[level];
     121}
     122
     123/** Convert log level name to the enum.
     124 *
     125 * @param[in] name Log level name or log level number.
     126 * @param[out] level_out Where to store the result (set to NULL to ignore).
     127 * @return Error code of the conversion or EOK on success.
     128 */
     129int log_level_from_str(const char *name, log_level_t *level_out)
     130{
     131        log_level_t level = LVL_FATAL;
     132
     133        while (log_level_names[level] != NULL) {
     134                if (str_cmp(name, log_level_names[level]) == 0) {
     135                        if (level_out != NULL)
     136                                *level_out = level;
     137                        return EOK;
     138                }
     139                level++;
     140        }
     141
     142        /* Maybe user specified number directly. */
     143        char *end_ptr;
     144        int level_int = strtol(name, &end_ptr, 0);
     145        if ((end_ptr == name) || (str_length(end_ptr) != 0))
     146                return EINVAL;
     147        if (level_int < 0)
     148                return ERANGE;
     149        if (level_int >= (int) LVL_LIMIT)
     150                return ERANGE;
     151
     152        if (level_out != NULL)
     153                *level_out = (log_level_t) level_int;
     154
     155        return EOK;
     156}
     157
    63158/** Initialize the logging system.
    64159 *
    65  * @param prog_name     Program name, will be printed as part of message
    66  * @param level         Minimum message level to print
    67  */
    68 int log_init(const char *prog_name, log_level_t level)
    69 {
    70         assert(level < LVL_LIMIT);
    71         log_level = level;
    72 
    73         log_stream = stdout;
     160 * @param prog_name Program name, will be printed as part of message
     161 */
     162int log_init(const char *prog_name)
     163{
    74164        log_prog_name = str_dup(prog_name);
    75165        if (log_prog_name == NULL)
    76166                return ENOMEM;
    77167
     168        logger_session = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOGGER, LOGGER_INTERFACE_WRITER, 0);
     169        if (logger_session == NULL) {
     170                return ENOMEM;
     171        }
     172
     173        default_log_id = log_create(prog_name, LOG_NO_PARENT);
     174
    78175        return EOK;
    79176}
    80177
     178/** Create a new (sub-) log.
     179 *
     180 * This function always returns a valid log_t. In case of errors,
     181 * @c parent is returned and errors are silently ignored.
     182 *
     183 * @param name Log name under which message will be reported (appended to parents name).
     184 * @param parent Parent log.
     185 * @return Opaque identifier of the newly created log.
     186 */
     187log_t log_create(const char *name, log_t parent)
     188{
     189        async_exch_t *exchange = async_exchange_begin(logger_session);
     190        if (exchange == NULL)
     191                return parent;
     192
     193        if (parent == LOG_DEFAULT)
     194                parent = default_log_id;
     195
     196        ipc_call_t answer;
     197        aid_t reg_msg = async_send_1(exchange, LOGGER_WRITER_CREATE_LOG,
     198            parent, &answer);
     199        int rc = async_data_write_start(exchange, name, str_size(name));
     200        sysarg_t reg_msg_rc;
     201        async_wait_for(reg_msg, &reg_msg_rc);
     202
     203        async_exchange_end(exchange);
     204
     205        if ((rc != EOK) || (reg_msg_rc != EOK))
     206                return parent;
     207
     208        return IPC_GET_ARG1(answer);
     209}
     210
    81211/** Write an entry to the log.
    82212 *
    83  * @param level         Message verbosity level. Message is only printed
    84  *                      if verbosity is less than or equal to current
    85  *                      reporting level.
    86  * @param fmt           Format string (no traling newline).
    87  */
    88 void log_msg(log_level_t level, const char *fmt, ...)
     213 * The message is printed only if the verbosity level is less than or
     214 * equal to currently set reporting level of the log.
     215 *
     216 * @param ctx Log to use (use LOG_DEFAULT if you have no idea what it means).
     217 * @param level Severity level of the message.
     218 * @param fmt Format string in printf-like format (without trailing newline).
     219 */
     220void log_msg(log_t ctx, log_level_t level, const char *fmt, ...)
    89221{
    90222        va_list args;
    91223
    92224        va_start(args, fmt);
    93         log_msgv(level, fmt, args);
     225        log_msgv(ctx, level, fmt, args);
    94226        va_end(args);
    95227}
     
    97229/** Write an entry to the log (va_list variant).
    98230 *
    99  * @param level         Message verbosity level. Message is only printed
    100  *                      if verbosity is less than or equal to current
    101  *                      reporting level.
    102  * @param fmt           Format string (no trailing newline)
    103  */
    104 void log_msgv(log_level_t level, const char *fmt, va_list args)
     231 * @param ctx Log to use (use LOG_DEFAULT if you have no idea what it means).
     232 * @param level Severity level of the message.
     233 * @param fmt Format string in printf-like format (without trailing newline).
     234 * @param args Arguments.
     235 */
     236void log_msgv(log_t ctx, log_level_t level, const char *fmt, va_list args)
    105237{
    106238        assert(level < LVL_LIMIT);
    107239
    108         /* Higher number means higher verbosity. */
    109         if (level <= log_level) {
    110                 fibril_mutex_lock(&log_serializer);
    111 
    112                 fprintf(log_stream, "%s: %s: ", log_prog_name,
    113                     log_level_names[level]);
    114                 vfprintf(log_stream, fmt, args);
    115                 fputc('\n', log_stream);
    116                 fflush(log_stream);
    117 
    118                 fibril_mutex_unlock(&log_serializer);
    119         }
     240        char *message_buffer = malloc(MESSAGE_BUFFER_SIZE);
     241        if (message_buffer == NULL)
     242                return;
     243
     244        vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);
     245        logger_message(logger_session, ctx, level, message_buffer);
     246        free(message_buffer);
    120247}
    121248
  • uspace/lib/c/generic/time.c

    r32b3a12 rb800b0e  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
     3 * Copyright (c) 2011 Petr Koupy
     4 * Copyright (c) 2011 Jiri Zarevucky
    35 * All rights reserved.
    46 *
     
    4345#include <ddi.h>
    4446#include <libc.h>
     47#include <stdint.h>
     48#include <stdio.h>
     49#include <ctype.h>
     50#include <assert.h>
    4551#include <unistd.h>
     52#include <loc.h>
     53#include <device/clock_dev.h>
     54#include <malloc.h>
     55
     56#define ASCTIME_BUF_LEN 26
    4657
    4758/** Pointer to kernel shared variables with time */
     
    5263} *ktime = NULL;
    5364
     65/* Helper functions ***********************************************************/
     66
     67#define HOURS_PER_DAY (24)
     68#define MINS_PER_HOUR (60)
     69#define SECS_PER_MIN (60)
     70#define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
     71#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
     72#define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
     73
     74/**
     75 * Checks whether the year is a leap year.
     76 *
     77 * @param year Year since 1900 (e.g. for 1970, the value is 70).
     78 * @return true if year is a leap year, false otherwise
     79 */
     80static bool _is_leap_year(time_t year)
     81{
     82        year += 1900;
     83
     84        if (year % 400 == 0)
     85                return true;
     86        if (year % 100 == 0)
     87                return false;
     88        if (year % 4 == 0)
     89                return true;
     90        return false;
     91}
     92
     93/**
     94 * Returns how many days there are in the given month of the given year.
     95 * Note that year is only taken into account if month is February.
     96 *
     97 * @param year Year since 1900 (can be negative).
     98 * @param mon Month of the year. 0 for January, 11 for December.
     99 * @return Number of days in the specified month.
     100 */
     101static int _days_in_month(time_t year, time_t mon)
     102{
     103        assert(mon >= 0 && mon <= 11);
     104
     105        static int month_days[] =
     106                { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
     107
     108        if (mon == 1) {
     109                year += 1900;
     110                /* february */
     111                return _is_leap_year(year) ? 29 : 28;
     112        } else {
     113                return month_days[mon];
     114        }
     115}
     116
     117/**
     118 * For specified year, month and day of month, returns which day of that year
     119 * it is.
     120 *
     121 * For example, given date 2011-01-03, the corresponding expression is:
     122 *     _day_of_year(111, 0, 3) == 2
     123 *
     124 * @param year Year (year 1900 = 0, can be negative).
     125 * @param mon Month (January = 0).
     126 * @param mday Day of month (First day is 1).
     127 * @return Day of year (First day is 0).
     128 */
     129static int _day_of_year(time_t year, time_t mon, time_t mday)
     130{
     131        static int mdays[] =
     132            { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
     133        static int leap_mdays[] =
     134            { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
     135
     136        return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
     137}
     138
     139/**
     140 * Integer division that rounds to negative infinity.
     141 * Used by some functions in this file.
     142 *
     143 * @param op1 Dividend.
     144 * @param op2 Divisor.
     145 * @return Rounded quotient.
     146 */
     147static time_t _floor_div(time_t op1, time_t op2)
     148{
     149        if (op1 >= 0 || op1 % op2 == 0) {
     150                return op1 / op2;
     151        } else {
     152                return op1 / op2 - 1;
     153        }
     154}
     155
     156/**
     157 * Modulo that rounds to negative infinity.
     158 * Used by some functions in this file.
     159 *
     160 * @param op1 Dividend.
     161 * @param op2 Divisor.
     162 * @return Remainder.
     163 */
     164static time_t _floor_mod(time_t op1, time_t op2)
     165{
     166        int div = _floor_div(op1, op2);
     167
     168        /* (a / b) * b + a % b == a */
     169        /* thus, a % b == a - (a / b) * b */
     170
     171        int result = op1 - div * op2;
     172       
     173        /* Some paranoid checking to ensure I didn't make a mistake here. */
     174        assert(result >= 0);
     175        assert(result < op2);
     176        assert(div * op2 + result == op1);
     177       
     178        return result;
     179}
     180
     181/**
     182 * Number of days since the Epoch.
     183 * Epoch is 1970-01-01, which is also equal to day 0.
     184 *
     185 * @param year Year (year 1900 = 0, may be negative).
     186 * @param mon Month (January = 0).
     187 * @param mday Day of month (first day = 1).
     188 * @return Number of days since the Epoch.
     189 */
     190static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
     191{
     192        return (year - 70) * 365 + _floor_div(year - 69, 4) -
     193            _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
     194            _day_of_year(year, mon, mday);
     195}
     196
     197/**
     198 * Seconds since the Epoch. see also _days_since_epoch().
     199 *
     200 * @param tm Normalized broken-down time.
     201 * @return Number of seconds since the epoch, not counting leap seconds.
     202 */
     203static time_t _secs_since_epoch(const struct tm *tm)
     204{
     205        return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
     206            SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
     207            tm->tm_min * SECS_PER_MIN + tm->tm_sec;
     208}
     209
     210/**
     211 * Which day of week the specified date is.
     212 *
     213 * @param year Year (year 1900 = 0).
     214 * @param mon Month (January = 0).
     215 * @param mday Day of month (first = 1).
     216 * @return Day of week (Sunday = 0).
     217 */
     218static int _day_of_week(time_t year, time_t mon, time_t mday)
     219{
     220        /* 1970-01-01 is Thursday */
     221        return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
     222}
     223
     224/**
     225 * Normalizes the broken-down time and optionally adds specified amount of
     226 * seconds.
     227 *
     228 * @param tm Broken-down time to normalize.
     229 * @param sec_add Seconds to add.
     230 * @return 0 on success, -1 on overflow
     231 */
     232static int _normalize_time(struct tm *tm, time_t sec_add)
     233{
     234        // TODO: DST correction
     235
     236        /* Set initial values. */
     237        time_t sec = tm->tm_sec + sec_add;
     238        time_t min = tm->tm_min;
     239        time_t hour = tm->tm_hour;
     240        time_t day = tm->tm_mday - 1;
     241        time_t mon = tm->tm_mon;
     242        time_t year = tm->tm_year;
     243
     244        /* Adjust time. */
     245        min += _floor_div(sec, SECS_PER_MIN);
     246        sec = _floor_mod(sec, SECS_PER_MIN);
     247        hour += _floor_div(min, MINS_PER_HOUR);
     248        min = _floor_mod(min, MINS_PER_HOUR);
     249        day += _floor_div(hour, HOURS_PER_DAY);
     250        hour = _floor_mod(hour, HOURS_PER_DAY);
     251
     252        /* Adjust month. */
     253        year += _floor_div(mon, 12);
     254        mon = _floor_mod(mon, 12);
     255
     256        /* Now the difficult part - days of month. */
     257       
     258        /* First, deal with whole cycles of 400 years = 146097 days. */
     259        year += _floor_div(day, 146097) * 400;
     260        day = _floor_mod(day, 146097);
     261       
     262        /* Then, go in one year steps. */
     263        if (mon <= 1) {
     264                /* January and February. */
     265                while (day > 365) {
     266                        day -= _is_leap_year(year) ? 366 : 365;
     267                        year++;
     268                }
     269        } else {
     270                /* Rest of the year. */
     271                while (day > 365) {
     272                        day -= _is_leap_year(year + 1) ? 366 : 365;
     273                        year++;
     274                }
     275        }
     276       
     277        /* Finally, finish it off month per month. */
     278        while (day >= _days_in_month(year, mon)) {
     279                day -= _days_in_month(year, mon);
     280                mon++;
     281                if (mon >= 12) {
     282                        mon -= 12;
     283                        year++;
     284                }
     285        }
     286       
     287        /* Calculate the remaining two fields. */
     288        tm->tm_yday = _day_of_year(year, mon, day + 1);
     289        tm->tm_wday = _day_of_week(year, mon, day + 1);
     290       
     291        /* And put the values back to the struct. */
     292        tm->tm_sec = (int) sec;
     293        tm->tm_min = (int) min;
     294        tm->tm_hour = (int) hour;
     295        tm->tm_mday = (int) day + 1;
     296        tm->tm_mon = (int) mon;
     297       
     298        /* Casts to work around libc brain-damage. */
     299        if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
     300                tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
     301                return -1;
     302        }
     303       
     304        tm->tm_year = (int) year;
     305        return 0;
     306}
     307
     308/**
     309 * Which day the week-based year starts on, relative to the first calendar day.
     310 * E.g. if the year starts on December 31st, the return value is -1.
     311 *
     312 * @param Year since 1900.
     313 * @return Offset of week-based year relative to calendar year.
     314 */
     315static int _wbyear_offset(int year)
     316{
     317        int start_wday = _day_of_week(year, 0, 1);
     318        return _floor_mod(4 - start_wday, 7) - 3;
     319}
     320
     321/**
     322 * Returns week-based year of the specified time.
     323 *
     324 * @param tm Normalized broken-down time.
     325 * @return Week-based year.
     326 */
     327static int _wbyear(const struct tm *tm)
     328{
     329        int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
     330        if (day < 0) {
     331                /* Last week of previous year. */
     332                return tm->tm_year - 1;
     333        }
     334        if (day > 364 + _is_leap_year(tm->tm_year)) {
     335                /* First week of next year. */
     336                return tm->tm_year + 1;
     337        }
     338        /* All the other days are in the calendar year. */
     339        return tm->tm_year;
     340}
     341
     342/**
     343 * Week number of the year, assuming weeks start on sunday.
     344 * The first Sunday of January is the first day of week 1;
     345 * days in the new year before this are in week 0.
     346 *
     347 * @param tm Normalized broken-down time.
     348 * @return The week number (0 - 53).
     349 */
     350static int _sun_week_number(const struct tm *tm)
     351{
     352        int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
     353        return (tm->tm_yday - first_day + 7) / 7;
     354}
     355
     356/**
     357 * Week number of the year, assuming weeks start on monday.
     358 * If the week containing January 1st has four or more days in the new year,
     359 * then it is considered week 1. Otherwise, it is the last week of the previous
     360 * year, and the next week is week 1. Both January 4th and the first Thursday
     361 * of January are always in week 1.
     362 *
     363 * @param tm Normalized broken-down time.
     364 * @return The week number (1 - 53).
     365 */
     366static int _iso_week_number(const struct tm *tm)
     367{
     368        int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
     369        if (day < 0) {
     370                /* Last week of previous year. */
     371                return 53;
     372        }
     373        if (day > 364 + _is_leap_year(tm->tm_year)) {
     374                /* First week of next year. */
     375                return 1;
     376        }
     377        /* All the other days give correct answer. */
     378        return (day / 7 + 1);
     379}
     380
     381/**
     382 * Week number of the year, assuming weeks start on monday.
     383 * The first Monday of January is the first day of week 1;
     384 * days in the new year before this are in week 0.
     385 *
     386 * @param tm Normalized broken-down time.
     387 * @return The week number (0 - 53).
     388 */
     389static int _mon_week_number(const struct tm *tm)
     390{
     391        int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
     392        return (tm->tm_yday - first_day + 7) / 7;
     393}
     394
     395/******************************************************************************/
     396
     397
    54398/** Add microseconds to given timeval.
    55399 *
     
    139483 */
    140484int gettimeofday(struct timeval *tv, struct timezone *tz)
     485{
     486        int rc;
     487        struct tm t;
     488        category_id_t cat_id;
     489        size_t svc_cnt;
     490        service_id_t *svc_ids = NULL;
     491        service_id_t svc_id;
     492        char *svc_name = NULL;
     493
     494        static async_sess_t *clock_conn = NULL;
     495
     496        if (tz) {
     497                tz->tz_minuteswest = 0;
     498                tz->tz_dsttime = DST_NONE;
     499        }
     500
     501        if (clock_conn == NULL) {
     502                rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING);
     503                if (rc != EOK)
     504                        goto ret_uptime;
     505
     506                rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
     507                if (rc != EOK)
     508                        goto ret_uptime;
     509
     510                if (svc_cnt == 0)
     511                        goto ret_uptime;
     512
     513                rc = loc_service_get_name(svc_ids[0], &svc_name);
     514                if (rc != EOK)
     515                        goto ret_uptime;
     516
     517                rc = loc_service_get_id(svc_name, &svc_id, 0);
     518                if (rc != EOK)
     519                        goto ret_uptime;
     520
     521                clock_conn = loc_service_connect(EXCHANGE_SERIALIZE,
     522                    svc_id, IPC_FLAG_BLOCKING);
     523                if (!clock_conn)
     524                        goto ret_uptime;
     525        }
     526
     527        rc = clock_dev_time_get(clock_conn, &t);
     528        if (rc != EOK)
     529                goto ret_uptime;
     530
     531        tv->tv_usec = 0;
     532        tv->tv_sec = mktime(&t);
     533
     534        free(svc_name);
     535        free(svc_ids);
     536
     537        return EOK;
     538
     539ret_uptime:
     540
     541        free(svc_name);
     542        free(svc_ids);
     543
     544        return getuptime(tv);
     545}
     546
     547int getuptime(struct timeval *tv)
    141548{
    142549        if (ktime == NULL) {
     
    160567        }
    161568       
    162         if (tz) {
    163                 tz->tz_minuteswest = 0;
    164                 tz->tz_dsttime = DST_NONE;
    165         }
    166        
    167569        sysarg_t s2 = ktime->seconds2;
    168570       
     
    178580        } else
    179581                tv->tv_sec = s1;
    180        
     582
    181583        return 0;
    182584}
     
    229631}
    230632
     633/**
     634 * This function first normalizes the provided broken-down time
     635 * (moves all values to their proper bounds) and then tries to
     636 * calculate the appropriate time_t representation.
     637 *
     638 * @param tm Broken-down time.
     639 * @return time_t representation of the time, undefined value on overflow.
     640 */
     641time_t mktime(struct tm *tm)
     642{
     643        // TODO: take DST flag into account
     644        // TODO: detect overflow
     645
     646        _normalize_time(tm, 0);
     647        return _secs_since_epoch(tm);
     648}
     649
     650/**
     651 * Convert time and date to a string, based on a specified format and
     652 * current locale.
     653 *
     654 * @param s Buffer to write string to.
     655 * @param maxsize Size of the buffer.
     656 * @param format Format of the output.
     657 * @param tm Broken-down time to format.
     658 * @return Number of bytes written.
     659 */
     660size_t strftime(char *restrict s, size_t maxsize,
     661    const char *restrict format, const struct tm *restrict tm)
     662{
     663        assert(s != NULL);
     664        assert(format != NULL);
     665        assert(tm != NULL);
     666
     667        // TODO: use locale
     668        static const char *wday_abbr[] = {
     669                "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
     670        };
     671        static const char *wday[] = {
     672                "Sunday", "Monday", "Tuesday", "Wednesday",
     673                "Thursday", "Friday", "Saturday"
     674        };
     675        static const char *mon_abbr[] = {
     676                "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     677                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
     678        };
     679        static const char *mon[] = {
     680                "January", "February", "March", "April", "May", "June", "July",
     681                "August", "September", "October", "November", "December"
     682        };
     683       
     684        if (maxsize < 1) {
     685                return 0;
     686        }
     687       
     688        char *ptr = s;
     689        size_t consumed;
     690        size_t remaining = maxsize;
     691       
     692        #define append(...) { \
     693                /* FIXME: this requires POSIX-correct snprintf */ \
     694                /*        otherwise it won't work with non-ascii chars */ \
     695                consumed = snprintf(ptr, remaining, __VA_ARGS__); \
     696                if (consumed >= remaining) { \
     697                        return 0; \
     698                } \
     699                ptr += consumed; \
     700                remaining -= consumed; \
     701        }
     702       
     703        #define recurse(fmt) { \
     704                consumed = strftime(ptr, remaining, fmt, tm); \
     705                if (consumed == 0) { \
     706                        return 0; \
     707                } \
     708                ptr += consumed; \
     709                remaining -= consumed; \
     710        }
     711       
     712        #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
     713            (((hour) == 0) ? 12 : (hour)))
     714       
     715        while (*format != '\0') {
     716                if (*format != '%') {
     717                        append("%c", *format);
     718                        format++;
     719                        continue;
     720                }
     721               
     722                format++;
     723                if (*format == '0' || *format == '+') {
     724                        // TODO: padding
     725                        format++;
     726                }
     727                while (isdigit(*format)) {
     728                        // TODO: padding
     729                        format++;
     730                }
     731                if (*format == 'O' || *format == 'E') {
     732                        // TODO: locale's alternative format
     733                        format++;
     734                }
     735               
     736                switch (*format) {
     737                case 'a':
     738                        append("%s", wday_abbr[tm->tm_wday]); break;
     739                case 'A':
     740                        append("%s", wday[tm->tm_wday]); break;
     741                case 'b':
     742                        append("%s", mon_abbr[tm->tm_mon]); break;
     743                case 'B':
     744                        append("%s", mon[tm->tm_mon]); break;
     745                case 'c':
     746                        // TODO: locale-specific datetime format
     747                        recurse("%Y-%m-%d %H:%M:%S"); break;
     748                case 'C':
     749                        append("%02d", (1900 + tm->tm_year) / 100); break;
     750                case 'd':
     751                        append("%02d", tm->tm_mday); break;
     752                case 'D':
     753                        recurse("%m/%d/%y"); break;
     754                case 'e':
     755                        append("%2d", tm->tm_mday); break;
     756                case 'F':
     757                        recurse("%+4Y-%m-%d"); break;
     758                case 'g':
     759                        append("%02d", _wbyear(tm) % 100); break;
     760                case 'G':
     761                        append("%d", _wbyear(tm)); break;
     762                case 'h':
     763                        recurse("%b"); break;
     764                case 'H':
     765                        append("%02d", tm->tm_hour); break;
     766                case 'I':
     767                        append("%02d", TO_12H(tm->tm_hour)); break;
     768                case 'j':
     769                        append("%03d", tm->tm_yday); break;
     770                case 'k':
     771                        append("%2d", tm->tm_hour); break;
     772                case 'l':
     773                        append("%2d", TO_12H(tm->tm_hour)); break;
     774                case 'm':
     775                        append("%02d", tm->tm_mon); break;
     776                case 'M':
     777                        append("%02d", tm->tm_min); break;
     778                case 'n':
     779                        append("\n"); break;
     780                case 'p':
     781                        append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
     782                case 'P':
     783                        append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
     784                case 'r':
     785                        recurse("%I:%M:%S %p"); break;
     786                case 'R':
     787                        recurse("%H:%M"); break;
     788                case 's':
     789                        append("%ld", _secs_since_epoch(tm)); break;
     790                case 'S':
     791                        append("%02d", tm->tm_sec); break;
     792                case 't':
     793                        append("\t"); break;
     794                case 'T':
     795                        recurse("%H:%M:%S"); break;
     796                case 'u':
     797                        append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
     798                        break;
     799                case 'U':
     800                        append("%02d", _sun_week_number(tm)); break;
     801                case 'V':
     802                        append("%02d", _iso_week_number(tm)); break;
     803                case 'w':
     804                        append("%d", tm->tm_wday); break;
     805                case 'W':
     806                        append("%02d", _mon_week_number(tm)); break;
     807                case 'x':
     808                        // TODO: locale-specific date format
     809                        recurse("%Y-%m-%d"); break;
     810                case 'X':
     811                        // TODO: locale-specific time format
     812                        recurse("%H:%M:%S"); break;
     813                case 'y':
     814                        append("%02d", tm->tm_year % 100); break;
     815                case 'Y':
     816                        append("%d", 1900 + tm->tm_year); break;
     817                case 'z':
     818                        // TODO: timezone
     819                        break;
     820                case 'Z':
     821                        // TODO: timezone
     822                        break;
     823                case '%':
     824                        append("%%");
     825                        break;
     826                default:
     827                        /* Invalid specifier, print verbatim. */
     828                        while (*format != '%') {
     829                                format--;
     830                        }
     831                        append("%%");
     832                        break;
     833                }
     834                format++;
     835        }
     836       
     837        #undef append
     838        #undef recurse
     839       
     840        return maxsize - remaining;
     841}
     842
     843
     844/** Converts a time value to a broken-down UTC time
     845 *
     846 * @param time    Time to convert
     847 * @param result  Structure to store the result to
     848 *
     849 * @return        EOK or a negative error code
     850 */
     851int time_utc2tm(const time_t time, struct tm *restrict result)
     852{
     853        assert(result != NULL);
     854
     855        /* Set result to epoch. */
     856        result->tm_sec = 0;
     857        result->tm_min = 0;
     858        result->tm_hour = 0;
     859        result->tm_mday = 1;
     860        result->tm_mon = 0;
     861        result->tm_year = 70; /* 1970 */
     862
     863        if (_normalize_time(result, time) == -1)
     864                return EOVERFLOW;
     865
     866        return EOK;
     867}
     868
     869/** Converts a time value to a null terminated string of the form
     870 *  "Wed Jun 30 21:49:08 1993\n" expressed in UTC.
     871 *
     872 * @param time   Time to convert.
     873 * @param buf    Buffer to store the string to, must be at least
     874 *               ASCTIME_BUF_LEN bytes long.
     875 *
     876 * @return       EOK or a negative error code.
     877 */
     878int time_utc2str(const time_t time, char *restrict buf)
     879{
     880        struct tm t;
     881        int r;
     882
     883        if ((r = time_utc2tm(time, &t)) != EOK)
     884                return r;
     885
     886        time_tm2str(&t, buf);
     887        return EOK;
     888}
     889
     890
     891/**
     892 * Converts broken-down time to a string in format
     893 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     894 *
     895 * @param timeptr Broken-down time structure.
     896 * @param buf     Buffer to store string to, must be at least ASCTIME_BUF_LEN
     897 *                bytes long.
     898 */
     899void time_tm2str(const struct tm *restrict timeptr, char *restrict buf)
     900{
     901        assert(timeptr != NULL);
     902        assert(buf != NULL);
     903
     904        static const char *wday[] = {
     905                "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
     906        };
     907        static const char *mon[] = {
     908                "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     909                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
     910        };
     911
     912        snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
     913            wday[timeptr->tm_wday],
     914            mon[timeptr->tm_mon],
     915            timeptr->tm_mday, timeptr->tm_hour,
     916            timeptr->tm_min, timeptr->tm_sec,
     917            1900 + timeptr->tm_year);
     918}
     919
     920/**
     921 * Converts a time value to a broken-down local time, expressed relative
     922 * to the user's specified timezone.
     923 *
     924 * @param timer     Time to convert.
     925 * @param result    Structure to store the result to.
     926 *
     927 * @return          EOK on success or a negative error code.
     928 */
     929int time_local2tm(const time_t time, struct tm *restrict result)
     930{
     931        // TODO: deal with timezone
     932        // currently assumes system and all times are in GMT
     933
     934        /* Set result to epoch. */
     935        result->tm_sec = 0;
     936        result->tm_min = 0;
     937        result->tm_hour = 0;
     938        result->tm_mday = 1;
     939        result->tm_mon = 0;
     940        result->tm_year = 70; /* 1970 */
     941
     942        if (_normalize_time(result, time) == -1)
     943                return EOVERFLOW;
     944
     945        return EOK;
     946}
     947
     948/**
     949 * Converts the calendar time to a null terminated string
     950 * of the form "Wed Jun 30 21:49:08 1993\n" expressed relative to the
     951 * user's specified timezone.
     952 *
     953 * @param timer  Time to convert.
     954 * @param buf    Buffer to store the string to. Must be at least
     955 *               ASCTIME_BUF_LEN bytes long.
     956 *
     957 * @return       EOK on success or a negative error code.
     958 */
     959int time_local2str(const time_t time, char *buf)
     960{
     961        struct tm loctime;
     962        int r;
     963
     964        if ((r = time_local2tm(time, &loctime)) != EOK)
     965                return r;
     966
     967        time_tm2str(&loctime, buf);
     968
     969        return EOK;
     970}
     971
     972/**
     973 * Calculate the difference between two times, in seconds.
     974 *
     975 * @param time1 First time.
     976 * @param time0 Second time.
     977 * @return Time in seconds.
     978 */
     979double difftime(time_t time1, time_t time0)
     980{
     981        return (double) (time1 - time0);
     982}
     983
    231984/** @}
    232985 */
  • uspace/lib/c/include/adt/hash_table.h

    r32b3a12 rb800b0e  
    11/*
    22 * Copyright (c) 2006 Jakub Jermar
     3 * Copyright (c) 2012 Adam Hraska
     4 *
    35 * All rights reserved.
    46 *
     
    3941#include <unistd.h>
    4042#include <bool.h>
     43#include <macros.h>
    4144
    42 typedef unsigned long hash_count_t;
    43 typedef unsigned long hash_index_t;
     45/** Opaque hash table link type. */
     46typedef struct ht_link {
     47        link_t link;
     48} ht_link_t;
    4449
    4550/** Set of operations for hash table. */
    4651typedef struct {
    47         /** Hash function.
    48          *
    49          * @param key Array of keys needed to compute hash index.
    50          *            All keys must be passed.
    51          *
    52          * @return Index into hash table.
    53          *
    54          */
    55         hash_index_t (*hash)(unsigned long key[]);
     52        /** Returns the hash of the key stored in the item (ie its lookup key). */
     53        size_t (*hash)(const ht_link_t *item);
    5654       
    57         /** Hash table item comparison function.
    58          *
    59          * @param key Array of keys that will be compared with item. It is
    60          *            not necessary to pass all keys.
    61          *
    62          * @return True if the keys match, false otherwise.
    63          *
    64          */
    65         int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
     55        /** Returns the hash of the key. */
     56        size_t (*key_hash)(void *key);
    6657       
     58        /** True if the items are equal (have the same lookup keys). */
     59        bool (*equal)(const ht_link_t *item1, const ht_link_t *item2);
     60
     61        /** Returns true if the key is equal to the item's lookup key. */
     62        bool (*key_equal)(void *key, const ht_link_t *item);
     63
    6764        /** Hash table item removal callback.
     65         *
     66         * Must not invoke any mutating functions of the hash table.
    6867         *
    6968         * @param item Item that was removed from the hash table.
    70          *
    7169         */
    72         void (*remove_callback)(link_t *item);
    73 } hash_table_operations_t;
     70        void (*remove_callback)(ht_link_t *item);
     71} hash_table_ops_t;
    7472
    7573/** Hash table structure. */
    7674typedef struct {
    77         list_t *entry;
    78         hash_count_t entries;
    79         hash_count_t max_keys;
    80         hash_table_operations_t *op;
     75        hash_table_ops_t *op;
     76        list_t *bucket;
     77        size_t bucket_cnt;
     78        size_t full_item_cnt;
     79        size_t item_cnt;
     80        size_t max_load;
     81        bool apply_ongoing;
    8182} hash_table_t;
    8283
    83 #define hash_table_get_instance(item, type, member) \
    84     list_get_instance((item), type, member)
     84#define hash_table_get_inst(item, type, member) \
     85        member_to_inst((item), type, member)
    8586
    86 extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
    87     hash_table_operations_t *);
     87extern bool hash_table_create(hash_table_t *, size_t, size_t,
     88        hash_table_ops_t *);
     89extern void hash_table_destroy(hash_table_t *);
     90
     91extern bool hash_table_empty(hash_table_t *);
     92extern size_t hash_table_size(hash_table_t *);
     93
    8894extern void hash_table_clear(hash_table_t *);
    89 extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
    90 extern link_t *hash_table_find(hash_table_t *, unsigned long []);
    91 extern void hash_table_remove(hash_table_t *, unsigned long [], hash_count_t);
    92 extern void hash_table_destroy(hash_table_t *);
    93 extern void hash_table_apply(hash_table_t *, void (*)(link_t *, void *),
    94     void *);
     95extern void hash_table_insert(hash_table_t *, ht_link_t *);
     96extern bool hash_table_insert_unique(hash_table_t *, ht_link_t *);
     97extern ht_link_t *hash_table_find(const hash_table_t *, void *);
     98extern ht_link_t *hash_table_find_next(const hash_table_t *, ht_link_t *);
     99extern size_t hash_table_remove(hash_table_t *, void *);
     100extern void hash_table_remove_item(hash_table_t *, ht_link_t *);
     101extern void hash_table_apply(hash_table_t *, bool (*)(ht_link_t *, void *),
     102        void *);
     103
    95104
    96105#endif
  • uspace/lib/c/include/adt/list.h

    r32b3a12 rb800b0e  
    7171            iterator != &(list).head; iterator = iterator->next)
    7272
     73/** Unlike list_foreach(), allows removing items while traversing a list.
     74 *
     75 * @code
     76 * list_t mylist;
     77 * typedef struct item {
     78 *     int value;
     79 *     link_t item_link;
     80 * } item_t;
     81 *
     82 * //..
     83 *
     84 * // Print each list element's value and remove the element from the list.
     85 * list_foreach_safe(mylist, cur_link, next_link) {
     86 *     item_t *cur_item = list_get_instance(cur_link, item_t, item_link);
     87 *     printf("%d\n", cur_item->value);
     88 *     list_remove(cur_link);
     89 * }
     90 * @endcode
     91 *
     92 * @param list List to traverse.
     93 * @param iterator Iterator to the current element of the list.
     94 *             The item this iterator points may be safely removed
     95 *             from the list.
     96 * @param next_iter Iterator to the next element of the list.
     97 */
     98#define list_foreach_safe(list, iterator, next_iter) \
     99        for (link_t *iterator = (list).head.next, \
     100                *next_iter = iterator->next; \
     101                iterator != &(list).head; \
     102                iterator = next_iter, next_iter = iterator->next)
     103
    73104#define assert_link_not_used(link) \
    74105        assert(((link)->prev == NULL) && ((link)->next == NULL))
     106
     107/** Returns true if the link is definitely part of a list. False if not sure. */
     108static inline int link_in_use(link_t *link)
     109{
     110        return link->prev != NULL && link->next != NULL;
     111}
    75112
    76113/** Initialize doubly-linked circular list link
  • uspace/lib/c/include/io/log.h

    r32b3a12 rb800b0e  
    3636
    3737#include <stdarg.h>
     38#include <inttypes.h>
    3839#include <io/verify.h>
    3940
     41/** Log message level. */
    4042typedef enum {
     43        /** Fatal error, program is not able to recover at all. */
    4144        LVL_FATAL,
     45        /** Serious error but the program can recover from it. */
    4246        LVL_ERROR,
     47        /** Easily recoverable problem. */
    4348        LVL_WARN,
     49        /** Information message that ought to be printed by default. */
    4450        LVL_NOTE,
     51        /** Debugging purpose message. */
    4552        LVL_DEBUG,
     53        /** More detailed debugging message. */
    4654        LVL_DEBUG2,
    4755       
     
    5058} log_level_t;
    5159
    52 extern int log_init(const char *, log_level_t);
    53 extern void log_msg(log_level_t, const char *, ...)
    54     PRINTF_ATTRIBUTE(2, 3);
    55 extern void log_msgv(log_level_t, const char *, va_list);
     60/** Log itself (logging target). */
     61typedef sysarg_t log_t;
     62/** Formatting directive for printing log_t. */
     63#define PRIlogctx PRIxn
     64
     65/** Default log (target). */
     66#define LOG_DEFAULT ((log_t) -1)
     67
     68/** Use when creating new top-level log. */
     69#define LOG_NO_PARENT ((log_t) 0)
     70
     71extern const char *log_level_str(log_level_t);
     72extern int log_level_from_str(const char *, log_level_t *);
     73
     74extern int log_init(const char *);
     75extern log_t log_create(const char *, log_t);
     76
     77extern void log_msg(log_t, log_level_t, const char *, ...)
     78    PRINTF_ATTRIBUTE(3, 4);
     79extern void log_msgv(log_t, log_level_t, const char *, va_list);
    5680
    5781#endif
  • uspace/lib/c/include/ipc/dev_iface.h

    r32b3a12 rb800b0e  
    5454        /** Interface provided by USB HID devices. */
    5555        USBHID_DEV_IFACE,
     56        /** Interface provided by Real Time Clock devices */
     57        CLOCK_DEV_IFACE,
     58        /** Interface provided by battery powered devices */
     59        BATTERY_DEV_IFACE,
    5660        /** Interface provided by AHCI devices. */
    5761        AHCI_DEV_IFACE,
  • uspace/lib/c/include/ipc/logger.h

    r32b3a12 rb800b0e  
    11/*
    2  * Copyright (c) 2006 Jakub Jermar
    3  * Copyright (c) 2011 Radim Vansa
     2 * Copyright (c) 2012 Vojtech Horky
    43 * All rights reserved.
    54 *
     
    3130 * @{
    3231 */
    33 /** @file
    34  */
    3532
    36 #ifndef LIBC_HASH_SET_H_
    37 #define LIBC_HASH_SET_H_
     33#ifndef LIBC_IPC_LOGGER_H_
     34#define LIBC_IPC_LOGGER_H_
    3835
    39 #include <adt/list.h>
    40 #include <unistd.h>
     36#include <ipc/common.h>
    4137
    42 #define HASH_SET_MIN_SIZE  8
     38typedef enum {
     39        /** Set (global) default displayed logging level.
     40         *
     41         * Arguments: new log level.
     42         * Returns: error code
     43         */
     44        LOGGER_CONTROL_SET_DEFAULT_LEVEL = IPC_FIRST_USER_METHOD,
     45        /** Set displayed level for given log.
     46         *
     47         * Arguments: new log level.
     48         * Returns: error code
     49         * Followed by: string with full log name.
     50         */
     51        LOGGER_CONTROL_SET_LOG_LEVEL
     52} logger_control_request_t;
    4353
    44 typedef unsigned long (*hash_set_hash)(const link_t *);
    45 typedef int (*hash_set_equals)(const link_t *, const link_t *);
     54typedef enum {
     55        /** Create new log.
     56         *
     57         * Arguments: parent log id (0 for top-level log).
     58         * Returns: error code, log id
     59         * Followed by: string with log name.
     60         */
     61        LOGGER_WRITER_CREATE_LOG = IPC_FIRST_USER_METHOD,
     62        /** Write a message to a given log.
     63         *
     64         * Arguments: log id, message severity level (log_level_t)
     65         * Returns: error code
     66         * Followed by: string with the message.
     67         */
     68        LOGGER_WRITER_MESSAGE
     69} logger_writer_request_t;
    4670
    47 /** Hash table structure. */
    48 typedef struct {
    49         list_t *table;
    50        
    51         /** Current table size */
    52         size_t size;
    53        
    54         /**
    55          * Current number of entries. If count > size,
    56          * the table is rehashed into table with double
    57          * size. If (4 * count < size) && (size > min_size),
    58          * the table is rehashed into table with half the size.
    59          */
    60         size_t count;
    61        
    62         /** Hash function */
    63         hash_set_hash hash;
    64        
    65         /** Hash table item equals function */
    66         hash_set_equals equals;
    67 } hash_set_t;
    68 
    69 extern int hash_set_init(hash_set_t *, hash_set_hash, hash_set_equals, size_t);
    70 extern int hash_set_insert(hash_set_t *, link_t *);
    71 extern link_t *hash_set_find(hash_set_t *, const link_t *);
    72 extern int hash_set_contains(const hash_set_t *, const link_t *);
    73 extern size_t hash_set_count(const hash_set_t *);
    74 extern link_t *hash_set_remove(hash_set_t *, const link_t *);
    75 extern void hash_set_remove_selected(hash_set_t *,
    76     int (*)(link_t *, void *), void *);
    77 extern void hash_set_destroy(hash_set_t *);
    78 extern void hash_set_apply(hash_set_t *, void (*)(link_t *, void *), void *);
    79 extern void hash_set_clear(hash_set_t *, void (*)(link_t *, void *), void *);
     71typedef enum {
     72        /** Interface for controlling logger behavior. */
     73        LOGGER_INTERFACE_CONTROL,
     74        /** Interface for servers writing to the log. */
     75        LOGGER_INTERFACE_WRITER
     76} logger_interface_t;
    8077
    8178#endif
  • uspace/lib/c/include/ipc/services.h

    r32b3a12 rb800b0e  
    4545        SERVICE_VFS        = FOURCC('v', 'f', 's', ' '),
    4646        SERVICE_LOC        = FOURCC('l', 'o', 'c', ' '),
     47        SERVICE_LOGGER     = FOURCC('l', 'o', 'g', 'g'),
    4748        SERVICE_DEVMAN     = FOURCC('d', 'e', 'v', 'n'),
    4849        SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
  • uspace/lib/c/include/macros.h

    r32b3a12 rb800b0e  
    5252            | ((((uint64_t) (up)) & 0xffffffff) << 32))
    5353
     54#ifndef member_to_inst
     55#define member_to_inst(ptr_member, type, member_identif) \
     56        ((type*) (((void*)(ptr_member)) - ((void*)&(((type*)0)->member_identif))))
     57#endif
     58
     59
    5460#endif
    5561
  • uspace/lib/c/include/sys/time.h

    r32b3a12 rb800b0e  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
     3 * Copyright (c) 2011 Petr Koupy
     4 * Copyright (c) 2011 Jiri Zarevucky
    35 * All rights reserved.
    46 *
     
    3941
    4042#define DST_NONE 0
     43#define ASCTIME_BUF_LEN 26
    4144
    4245typedef long time_t;
     
    4548typedef uint32_t useconds_t;
    4649typedef uint32_t mseconds_t;
     50
     51struct tm {
     52        int tm_sec;         /* Seconds [0,60]. */
     53        int tm_min;         /* Minutes [0,59]. */
     54        int tm_hour;        /* Hour [0,23]. */
     55        int tm_mday;        /* Day of month [1,31]. */
     56        int tm_mon;         /* Month of year [0,11]. */
     57        int tm_year;        /* Years since 1900. */
     58        int tm_wday;        /* Day of week [0,6] (Sunday = 0). */
     59        int tm_yday;        /* Day of year [0,365]. */
     60        int tm_isdst;       /* Daylight Savings flag. */
     61};
    4762
    4863struct timeval {
     
    6176extern int tv_gteq(struct timeval *tv1, struct timeval *tv2);
    6277extern int gettimeofday(struct timeval *tv, struct timezone *tz);
     78extern int getuptime(struct timeval *tv);
    6379
    6480extern void udelay(useconds_t);
     81
     82extern time_t mktime(struct tm *tm);
     83extern int time_utc2tm(const time_t time, struct tm *result);
     84extern int time_utc2str(const time_t time, char *buf);
     85extern void time_tm2str(const struct tm *timeptr, char *buf);
     86extern int time_local2tm(const time_t time, struct tm *result);
     87extern int time_local2str(const time_t time, char *buf);
     88extern double difftime(time_t time1, time_t time0);
     89extern size_t strftime(char *restrict s, size_t maxsize,
     90    const char *restrict format, const struct tm *restrict tm);
    6591
    6692#endif
  • uspace/lib/drv/Makefile

    r32b3a12 rb800b0e  
    4646        generic/remote_usbhc.c \
    4747        generic/remote_usbhid.c \
     48        generic/remote_clock_dev.c \
     49        generic/remote_battery_dev.c \
    4850        generic/remote_ahci.c
    4951
  • uspace/lib/drv/generic/dev_iface.c

    r32b3a12 rb800b0e  
    4141#include "remote_hw_res.h"
    4242#include "remote_char_dev.h"
     43#include "remote_clock_dev.h"
     44#include "remote_battery_dev.h"
    4345#include "remote_graph_dev.h"
    4446#include "remote_nic.h"
     
    5961                &remote_usbhc_iface,
    6062                &remote_usbhid_iface,
     63                &remote_clock_dev_iface,
     64                &remote_battery_dev_iface,
    6165                &remote_ahci_iface
    6266        }
  • uspace/lib/drv/generic/log.c

    r32b3a12 rb800b0e  
    3838 *
    3939 * @param drv_name Driver name, will be printed as part of message
    40  * @param level    Minimum message level to print
    4140 *
    4241 */
    43 int ddf_log_init(const char *drv_name, log_level_t level)
     42int ddf_log_init(const char *drv_name)
    4443{
    45         return log_init(drv_name, level);
     44        return log_init(drv_name);
    4645}
    4746
     
    5958       
    6059        va_start(args, fmt);
    61         log_msgv(level, fmt, args);
     60        log_msgv(LOG_DEFAULT, level, fmt, args);
    6261        va_end(args);
    6362}
  • uspace/lib/drv/include/ddf/log.h

    r32b3a12 rb800b0e  
    3737#include <io/verify.h>
    3838
    39 extern int ddf_log_init(const char *, log_level_t);
     39extern int ddf_log_init(const char *);
    4040extern void ddf_msg(log_level_t, const char *, ...)
    4141    PRINTF_ATTRIBUTE(2, 3);
  • uspace/lib/ext4/libext4_crc.c

    r32b3a12 rb800b0e  
    3333/**
    3434 * @file  libext4_crc.c
    35  * @brief CRC checksumming implementation from Linux.
    3635 */
    3736
    38 #include <byteorder.h>
    3937#include "libext4.h"
    4038
    41 /** CRC table for the CRC-16.
    42  *
    43  * The poly is 0x8005 (x^16 + x^15 + x^2 + 1).
    44  *
    45  */
    46 uint16_t const crc16_table[256] = {
    47         0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    48         0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    49         0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    50         0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    51         0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    52         0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    53         0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    54         0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    55         0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    56         0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    57         0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    58         0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    59         0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    60         0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    61         0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    62         0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    63         0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    64         0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    65         0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    66         0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    67         0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    68         0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    69         0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    70         0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    71         0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    72         0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    73         0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    74         0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    75         0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    76         0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    77         0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    78         0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
    79 };
    80 
    81 /** Modify CRC value.
    82  *
    83  * @param crc   Current CRC value
    84  * @param data  New byte of data to be "added" to CRC
    85  *
    86  * @return Updated CRC value
    87  *
    88  */
    89 static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data)
    90 {
    91         return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
    92 }
    93 
    94 /** Compute the CRC-16 for the data buffer.
    95  *
    96  * @param crc    Previous CRC value
    97  * @param buffer Data pointer
    98  * @param len    Number of bytes in the buffer
    99  *
    100  * @return Updated CRC value
    101  *
    102  */
    10339uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len)
    10440{
    105         while (len--)
    106                 crc = crc16_byte(crc, *buffer++);
    107        
    108         return crc;
     41        // TODO
     42        return 0;
    10943}
    11044
  • uspace/lib/ext4/libext4_filesystem.c

    r32b3a12 rb800b0e  
    471471
    472472/** Compute checksum of block group descriptor.
    473  *
    474  * It uses crc functions from Linux kernel implementation.
    475473 *
    476474 * @param sb   Superblock
  • uspace/lib/ext4/libext4_hash.c

    r32b3a12 rb800b0e  
    3535 */
    3636
     37#include "libext4.h"
    3738#include <errno.h>
    38 #include <mem.h>
    39 #include "libext4.h"
    4039
    41 #define TEA_DELTA  0x9E3779B9
    42 
    43 /* F, G and H are basic MD4 functions: selection, majority, parity */
    44 #define F(x, y, z)  ((z) ^ ((x) & ((y) ^ (z))))
    45 #define G(x, y, z)  (((x) & (y)) + (((x) ^ (y)) & (z)))
    46 #define H(x, y, z)  ((x) ^ (y) ^ (z))
    47 
    48 /*
    49  * The generic round function.  The application is so specific that
    50  * we don't bother protecting all the arguments with parens, as is generally
    51  * good macro practice, in favor of extra legibility.
    52  * Rotation is separate from addition to prevent recomputation
    53  */
    54 #define ROUND(f, a, b, c, d, x, s) \
    55         (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
    56 
    57 #define K1  0
    58 #define K2  013240474631UL
    59 #define K3  015666365641UL
    60 
    61 static void tea_transform(uint32_t buf[4], uint32_t const in[])
    62 {
    63         uint32_t sum = 0;
    64         uint32_t b0 = buf[0];
    65         uint32_t b1 = buf[1];
    66         uint32_t a = in[0];
    67         uint32_t b = in[1];
    68         uint32_t c = in[2];
    69         uint32_t d = in[3];
    70        
    71         int n = 16;
    72        
    73         do {
    74                 sum += TEA_DELTA;
    75                 b0 += ((b1 << 4) + a) ^ (b1 + sum) ^ ((b1 >> 5) + b);
    76                 b1 += ((b0 << 4) + c) ^ (b0 + sum) ^ ((b0 >> 5) + d);
    77         } while (--n);
    78        
    79         buf[0] += b0;
    80         buf[1] += b1;
    81 }
    82 
    83 
    84 static void half_md4_transform(uint32_t buf[4], const uint32_t in[8])
    85 {
    86         uint32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
    87        
    88         /* Round 1 */
    89         ROUND(F, a, b, c, d, in[0] + K1,  3);
    90         ROUND(F, d, a, b, c, in[1] + K1,  7);
    91         ROUND(F, c, d, a, b, in[2] + K1, 11);
    92         ROUND(F, b, c, d, a, in[3] + K1, 19);
    93         ROUND(F, a, b, c, d, in[4] + K1,  3);
    94         ROUND(F, d, a, b, c, in[5] + K1,  7);
    95         ROUND(F, c, d, a, b, in[6] + K1, 11);
    96         ROUND(F, b, c, d, a, in[7] + K1, 19);
    97        
    98         /* Round 2 */
    99         ROUND(G, a, b, c, d, in[1] + K2,  3);
    100         ROUND(G, d, a, b, c, in[3] + K2,  5);
    101         ROUND(G, c, d, a, b, in[5] + K2,  9);
    102         ROUND(G, b, c, d, a, in[7] + K2, 13);
    103         ROUND(G, a, b, c, d, in[0] + K2,  3);
    104         ROUND(G, d, a, b, c, in[2] + K2,  5);
    105         ROUND(G, c, d, a, b, in[4] + K2,  9);
    106         ROUND(G, b, c, d, a, in[6] + K2, 13);
    107        
    108         /* Round 3 */
    109         ROUND(H, a, b, c, d, in[3] + K3,  3);
    110         ROUND(H, d, a, b, c, in[7] + K3,  9);
    111         ROUND(H, c, d, a, b, in[2] + K3, 11);
    112         ROUND(H, b, c, d, a, in[6] + K3, 15);
    113         ROUND(H, a, b, c, d, in[1] + K3,  3);
    114         ROUND(H, d, a, b, c, in[5] + K3,  9);
    115         ROUND(H, c, d, a, b, in[0] + K3, 11);
    116         ROUND(H, b, c, d, a, in[4] + K3, 15);
    117        
    118         buf[0] += a;
    119         buf[1] += b;
    120         buf[2] += c;
    121         buf[3] += d;
    122 }
    123 
    124 static uint32_t hash_unsigned(const char *name, int len)
    125 {
    126         uint32_t hash;
    127         uint32_t hash0 = 0x12a3fe2d;
    128         uint32_t hash1 = 0x37abe8f9;
    129         const unsigned char *ucp = (const unsigned char *) name;
    130        
    131         while (len--) {
    132                 hash = hash1 + (hash0 ^ (((int) *ucp++) * 7152373));
    133                
    134                 if (hash & 0x80000000)
    135                         hash -= 0x7fffffff;
    136                
    137                 hash1 = hash0;
    138                 hash0 = hash;
    139         }
    140        
    141         return hash0 << 1;
    142 }
    143 
    144 static uint32_t hash_signed(const char *name, int len)
    145 {
    146         uint32_t hash;
    147         uint32_t hash0 = 0x12a3fe2d;
    148         uint32_t hash1 = 0x37abe8f9;
    149         const signed char *scp = (const signed char *) name;
    150        
    151         while (len--) {
    152                 hash = hash1 + (hash0 ^ (((int) *scp++) * 7152373));
    153                
    154                 if (hash & 0x80000000)
    155                         hash -= 0x7fffffff;
    156                
    157                 hash1 = hash0;
    158                 hash0 = hash;
    159         }
    160        
    161         return hash0 << 1;
    162 }
    163 
    164 static void str2hashbuf_signed(const char *msg, int len, uint32_t *buf, int num)
    165 {
    166         uint32_t pad, val;
    167         int i;
    168         const signed char *scp = (const signed char *) msg;
    169        
    170         pad = (uint32_t) len | ((uint32_t) len << 8);
    171         pad |= pad << 16;
    172        
    173         val = pad;
    174         if (len > num * 4)
    175                 len = num * 4;
    176        
    177         for (i = 0; i < len; i++) {
    178                 if ((i % 4) == 0)
    179                         val = pad;
    180                
    181                 val = ((int) scp[i]) + (val << 8);
    182                 if ((i % 4) == 3) {
    183                         *buf++ = val;
    184                         val = pad;
    185                         num--;
    186                 }
    187         }
    188        
    189         if (--num >= 0)
    190                 *buf++ = val;
    191        
    192         while (--num >= 0)
    193                 *buf++ = pad;
    194 }
    195 
    196 static void str2hashbuf_unsigned(const char *msg, int len, uint32_t *buf,
    197     int num)
    198 {
    199         uint32_t pad, val;
    200         int i;
    201         const unsigned char *ucp = (const unsigned char *) msg;
    202        
    203         pad = (uint32_t) len | ((uint32_t) len << 8);
    204         pad |= pad << 16;
    205        
    206         val = pad;
    207         if (len > num * 4)
    208                 len = num * 4;
    209        
    210         for (i = 0; i < len; i++) {
    211                 if ((i % 4) == 0)
    212                         val = pad;
    213                
    214                 val = ((int) ucp[i]) + (val << 8);
    215                 if ((i % 4) == 3) {
    216                         *buf++ = val;
    217                         val = pad;
    218                         num--;
    219                 }
    220         }
    221        
    222         if (--num >= 0)
    223                 *buf++ = val;
    224        
    225         while (--num >= 0)
    226                 *buf++ = pad;
    227 }
    228 
    229 /** Compute hash value of the string.
    230  *
    231  * @param hinfo Hash info structure with information about
    232  *              the algorithm, hash seed and with the place
    233  *              for the output hash value
    234  * @param len  Length of the name
    235  * @param name Name to be hashed
    236  *
    237  * @return Error code
    238  *
    239  */
    24040int ext4_hash_string(ext4_hash_info_t *hinfo, int len, const char *name)
    24141{
    242         uint32_t hash = 0;
    243         uint32_t minor_hash = 0;
    244         const char *p;
    245         int i;
    246         uint32_t in[8], buf[4];
    247         void (*str2hashbuf)(const char *, int, uint32_t *, int) =
    248             str2hashbuf_signed;
    249        
    250         /* Initialize the default seed for the hash checksum functions */
    251         buf[0] = 0x67452301;
    252         buf[1] = 0xefcdab89;
    253         buf[2] = 0x98badcfe;
    254         buf[3] = 0x10325476;
    255        
    256         /* Check if the seed is all zero's */
    257         if (hinfo->seed) {
    258                 for (i = 0; i < 4; i++) {
    259                         if (hinfo->seed[i] != 0)
    260                                 break;
    261                        
    262                 }
    263                
    264                 if (i < 4)
    265                         memcpy(buf, hinfo->seed, sizeof(buf));
    266         }
    267        
    268         switch (hinfo->hash_version) {
    269         case EXT4_HASH_VERSION_LEGACY_UNSIGNED:
    270                 hash = hash_unsigned(name, len);
    271                 break;
    272         case EXT4_HASH_VERSION_LEGACY:
    273                 hash = hash_signed(name, len);
    274                 break;
    275         case EXT4_HASH_VERSION_HALF_MD4_UNSIGNED:
    276                 str2hashbuf = str2hashbuf_unsigned;
    277         case EXT4_HASH_VERSION_HALF_MD4:
    278                 p = name;
    279                
    280                 while (len > 0) {
    281                         (*str2hashbuf)(p, len, in, 8);
    282                         half_md4_transform(buf, in);
    283                         len -= 32;
    284                         p += 32;
    285                 }
    286                
    287                 minor_hash = buf[2];
    288                 hash = buf[1];
    289                 break;
    290         case EXT4_HASH_VERSION_TEA_UNSIGNED:
    291                 str2hashbuf = str2hashbuf_unsigned;
    292         case EXT4_HASH_VERSION_TEA:
    293                 p = name;
    294                
    295                 while (len > 0) {
    296                         (*str2hashbuf)(p, len, in, 4);
    297                         tea_transform(buf, in);
    298                         len -= 16;
    299                         p += 16;
    300                 }
    301                
    302                 hash = buf[0];
    303                 minor_hash = buf[1];
    304                 break;
    305         default:
    306                 hinfo->hash = 0;
    307                 return EINVAL;
    308         }
    309        
    310         hash = hash & ~1;
    311         if (hash == (EXT4_DIRECTORY_HTREE_EOF << 1))
    312                 hash = (EXT4_DIRECTORY_HTREE_EOF - 1) << 1;
    313        
    314         hinfo->hash = hash;
    315         hinfo->minor_hash = minor_hash;
    316        
    317         return EOK;
     42        // TODO
     43        hinfo->hash = 0;
     44        return ENOTSUP;
    31845}
    31946
  • uspace/lib/fs/libfs.c

    r32b3a12 rb800b0e  
    631631                                                async_answer_0(rid, rc);
    632632                                        } else {
    633                                                 aoff64_t size = ops->size_get(fn);
    634                                                 async_answer_5(rid, fs_handle,
    635                                                     service_id,
    636                                                     ops->index_get(fn),
    637                                                     LOWER32(size),
    638                                                     UPPER32(size),
    639                                                     ops->lnkcnt_get(fn));
    640                                                 (void) ops->node_put(fn);
     633                                                (void) ops->node_put(cur);
     634                                                cur = fn;
     635                                                goto out_with_answer;
    641636                                        }
    642637                                } else
     
    715710                                        async_answer_0(rid, rc);
    716711                                } else {
    717                                         aoff64_t size = ops->size_get(fn);
    718                                         async_answer_5(rid, fs_handle,
    719                                             service_id,
    720                                             ops->index_get(fn),
    721                                             LOWER32(size),
    722                                             UPPER32(size),
    723                                             ops->lnkcnt_get(fn));
    724                                         (void) ops->node_put(fn);
     712                                        (void) ops->node_put(cur);
     713                                        cur = fn;
     714                                        goto out_with_answer;
    725715                                }
    726716                        } else
  • uspace/lib/nic/include/nic.h

    r32b3a12 rb800b0e  
    4040
    4141#include <adt/list.h>
     42#include <adt/hash_table.h>
    4243#include <ddf/driver.h>
    4344#include <device/hw_res_parsed.h>
     
    5354 */
    5455typedef struct nic_wol_virtue {
    55         link_t item;
     56        ht_link_t item;
    5657        nic_wv_id_t id;
    5758        nic_wv_type_t type;
  • uspace/lib/nic/include/nic_addr_db.h

    r32b3a12 rb800b0e  
    4343#endif
    4444
    45 #include <adt/hash_set.h>
    46 
    47 /**
    48  * Initial size of DB's hash set
    49  */
    50 #define NIC_ADDR_DB_INIT_SIZE   8
    51 /**
    52  * Maximal length of addresses in the DB (in bytes).
    53  */
    54 #define NIC_ADDR_MAX_LENGTH             16
     45#include <adt/hash_table.h>
    5546
    5647/**
     
    5849 */
    5950typedef struct nic_addr_db {
    60         hash_set_t set;
     51        hash_table_t set;
    6152        size_t addr_len;
    6253} nic_addr_db_t;
    6354
    64 /**
    65  * Helper structure for keeping the address in the hash set.
    66  */
    67 typedef struct nic_addr_entry {
    68         link_t item;
    69         size_t addr_len;
    70         uint8_t addr[NIC_ADDR_MAX_LENGTH];
    71 } nic_addr_entry_t;
    7255
    7356extern int nic_addr_db_init(nic_addr_db_t *db, size_t addr_len);
    7457extern void nic_addr_db_clear(nic_addr_db_t *db);
    7558extern void nic_addr_db_destroy(nic_addr_db_t *db);
    76 extern size_t nic_addr_db_count(const nic_addr_db_t *db);
    7759extern int nic_addr_db_insert(nic_addr_db_t *db, const uint8_t *addr);
    7860extern int nic_addr_db_remove(nic_addr_db_t *db, const uint8_t *addr);
    79 extern void nic_addr_db_remove_selected(nic_addr_db_t *db,
    80         int (*func)(const uint8_t *, void *), void *arg);
    8161extern int nic_addr_db_contains(const nic_addr_db_t *db, const uint8_t *addr);
    8262extern void nic_addr_db_foreach(const nic_addr_db_t *db,
  • uspace/lib/nic/include/nic_wol_virtues.h

    r32b3a12 rb800b0e  
    5151         * Operations for table
    5252         */
    53         hash_table_operations_t table_operations;
     53        hash_table_ops_t table_operations;
    5454        /**
    5555         * WOL virtues hashed by their ID's.
  • uspace/lib/nic/src/nic_addr_db.c

    r32b3a12 rb800b0e  
    3535 * @brief Generic hash-set based database of addresses
    3636 */
     37#include "nic_addr_db.h"
     38#include "libarch/common.h"
    3739#include <assert.h>
    3840#include <stdlib.h>
     
    4042#include <errno.h>
    4143#include <mem.h>
    42 
    43 #include "nic_addr_db.h"
    44 
    45 /**
    46  * Hash set helper function
    47  */
    48 static int nic_addr_equals(const link_t *item1, const link_t *item2)
    49 {
    50         assert(item1 && item2);
    51         size_t addr_len = ((const nic_addr_entry_t *) item1)->addr_len;
    52 
    53         assert(addr_len == ((const nic_addr_entry_t *) item2)->addr_len);
    54 
    55         size_t i;
    56         for (i = 0; i < addr_len; ++i) {
    57                 if (((nic_addr_entry_t *) item1)->addr[i] !=
    58                         ((nic_addr_entry_t *) item2)->addr[i])
    59                         return false;
     44#include <adt/hash_table.h>
     45#include <macros.h>
     46#include <stdint.h>
     47
     48
     49/**
     50 * Helper structure for keeping the address in the hash set.
     51 */
     52typedef struct nic_addr_entry {
     53        ht_link_t link;
     54        uint8_t len;
     55        uint8_t addr[1];
     56} nic_addr_entry_t;
     57
     58
     59/*
     60 * Hash table helper functions
     61 */
     62typedef struct {
     63        size_t len;
     64        const uint8_t *addr;
     65} addr_key_t;
     66
     67static bool nic_addr_key_equal(void *key_arg, const ht_link_t *item)
     68{
     69        addr_key_t *key = (addr_key_t*)key_arg;
     70        nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
     71       
     72        return 0 == bcmp(entry->addr, key->addr, entry->len);
     73}
     74
     75static size_t addr_hash(size_t len, const uint8_t *addr)
     76{
     77        size_t hash = 0;
     78       
     79        for (size_t i = 0; i < len; ++i) {
     80                hash = (hash << 5) ^ addr[i];
    6081        }
    61         return true;
    62 }
    63 
    64 /**
    65  * Hash set helper function
    66  */
    67 static unsigned long nic_addr_hash(const link_t *item)
    68 {
    69         assert(item);
    70         const nic_addr_entry_t *entry = (const nic_addr_entry_t *) item;
    71         unsigned long hash = 0;
    72 
    73         size_t i;
    74         for (i = 0; i < entry->addr_len; ++i) {
    75                 hash = (hash << 8) ^ (hash >> 24) ^ entry->addr[i];
    76         }
     82       
    7783        return hash;
    7884}
    7985
    80 /**
    81  * Helper wrapper
    82  */
    83 static void nic_addr_destroy(link_t *item, void *unused)
    84 {
    85         free(item);
    86 }
     86static size_t nic_addr_key_hash(void *k)
     87{
     88        addr_key_t *key = (addr_key_t*)k;
     89        return addr_hash(key->len, key->addr);
     90}
     91
     92static size_t nic_addr_hash(const ht_link_t *item)
     93{
     94        nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
     95        return addr_hash(entry->len, entry->addr);
     96}
     97
     98static void nic_addr_removed(ht_link_t *item)
     99{
     100        nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
     101       
     102        free(entry);
     103}
     104
     105static hash_table_ops_t set_ops = {
     106        .hash = nic_addr_hash,
     107        .key_hash = nic_addr_key_hash,
     108        .key_equal = nic_addr_key_equal,
     109        .equal = NULL,
     110        .remove_callback = nic_addr_removed
     111};
    87112
    88113/**
     
    99124{
    100125        assert(db);
    101         if (addr_len > NIC_ADDR_MAX_LENGTH) {
     126       
     127        if (addr_len > UCHAR_MAX)
    102128                return EINVAL;
    103         }
    104         if (!hash_set_init(&db->set, nic_addr_hash, nic_addr_equals,
    105                 NIC_ADDR_DB_INIT_SIZE)) {
     129       
     130        if (!hash_table_create(&db->set, 0, 0, &set_ops))
    106131                return ENOMEM;
    107         }
     132       
    108133        db->addr_len = addr_len;
    109134        return EOK;
     
    118143{
    119144        assert(db);
    120         hash_set_clear(&db->set, nic_addr_destroy, NULL);
     145        hash_table_clear(&db->set);
    121146}
    122147
     
    129154{
    130155        assert(db);
    131         hash_set_apply(&db->set, nic_addr_destroy, NULL);
    132         hash_set_destroy(&db->set);
    133 }
    134 
    135 /**
    136  * Get number of addresses in the db
    137  *
    138  * @param       db
    139  *
    140  * @return Number of adresses
    141  */
    142 size_t nic_addr_db_count(const nic_addr_db_t *db)
    143 {
    144         assert(db);
    145         return hash_set_count(&db->set);
    146 }
     156        hash_table_destroy(&db->set);
     157}
     158
    147159
    148160/**
     
    160172{
    161173        assert(db && addr);
    162         nic_addr_entry_t *entry = malloc(sizeof (nic_addr_entry_t));
    163         if (entry == NULL) {
     174
     175        addr_key_t key = {
     176                .len = db->addr_len,
     177                .addr = addr
     178        };
     179       
     180        if (hash_table_find(&db->set, &key))
     181                return EEXIST;
     182       
     183        nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t) + db->addr_len - 1);
     184        if (entry == NULL)
    164185                return ENOMEM;
    165         }
    166         entry->addr_len = db->addr_len;
     186
     187        entry->len = (uint8_t) db->addr_len;
    167188        memcpy(entry->addr, addr, db->addr_len);
    168 
    169         return hash_set_insert(&db->set, &entry->item) ? EOK : EEXIST;
     189       
     190        hash_table_insert(&db->set, &entry->link);
     191        return EOK;
    170192}
    171193
     
    182204{
    183205        assert(db && addr);
    184         nic_addr_entry_t entry;
    185         entry.addr_len = db->addr_len;
    186         memcpy(entry.addr, addr, db->addr_len);
    187 
    188         link_t *removed = hash_set_remove(&db->set, &entry.item);
    189         free(removed);
    190         return removed != NULL ? EOK : ENOENT;
     206       
     207        addr_key_t key = {
     208                .len = db->addr_len,
     209                .addr = addr
     210        };
     211       
     212        if (hash_table_remove(&db->set, &key))
     213                return EOK;
     214        else
     215                return ENOENT;
    191216}
    192217
     
    202227{
    203228        assert(db && addr);
    204         nic_addr_entry_t entry;
    205         entry.addr_len = db->addr_len;
    206         memcpy(entry.addr, addr, db->addr_len);
    207 
    208         return hash_set_contains(&db->set, &entry.item);
     229       
     230        addr_key_t key = {
     231                .len = db->addr_len,
     232                .addr = addr
     233        };
     234       
     235        return 0 != hash_table_find(&db->set, &key);
    209236}
    210237
     
    220247 * Helper function for nic_addr_db_foreach
    221248 */
    222 static void nic_addr_db_fe_helper(link_t *item, void *arg) {
     249static bool nic_addr_db_fe_helper(ht_link_t *item, void *arg)
     250{
    223251        nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg;
    224         hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
     252        nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
     253        hs->func(entry->addr, hs->arg);
     254        return true;
    225255}
    226256
     
    237267{
    238268        nic_addr_db_fe_arg_t hs = { .func = func, .arg = arg };
    239         hash_set_apply((hash_set_t *) &db->set, nic_addr_db_fe_helper, &hs);
    240 }
    241 
    242 /**
    243  * Helper structure for nic_addr_db_remove_selected
    244  */
    245 typedef struct {
    246         int (*func)(const uint8_t *, void *);
    247         void *arg;
    248 } nic_addr_db_rs_arg_t;
    249 
    250 /**
    251  * Helper function for nic_addr_db_foreach
    252  */
    253 static int nic_addr_db_rs_helper(link_t *item, void *arg) {
    254         nic_addr_db_rs_arg_t *hs = (nic_addr_db_rs_arg_t *) arg;
    255         int retval = hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
    256         if (retval) {
    257                 free(item);
    258         }
    259         return retval;
    260 }
    261 
    262 /**
    263  * Removes all addresses for which the function returns non-zero.
    264  *
    265  * @param       db
    266  * @param       func    User-defined function
    267  * @param       arg             Custom argument passed to the function
    268  */
    269 void nic_addr_db_remove_selected(nic_addr_db_t *db,
    270         int (*func)(const uint8_t *, void *), void *arg)
    271 {
    272         nic_addr_db_rs_arg_t hs = { .func = func, .arg = arg };
    273         hash_set_remove_selected(&db->set, nic_addr_db_rs_helper, &hs);
     269        hash_table_apply((hash_table_t*)&db->set, nic_addr_db_fe_helper, &hs);
    274270}
    275271
  • uspace/lib/nic/src/nic_wol_virtues.c

    r32b3a12 rb800b0e  
    3737
    3838#include "nic_wol_virtues.h"
     39#include "nic.h"
    3940#include <assert.h>
    4041#include <errno.h>
    4142
    42 #define NIC_WV_HASH_COUNT 32
    43 
    44 /**
    45  * Hash table helper function
    46  */
    47 static int nic_wv_compare(unsigned long key[], hash_count_t keys,
    48         link_t *item)
     43
     44/*
     45 * Hash table helper functions
     46 */
     47
     48static size_t nic_wv_key_hash(void *key)
     49{
     50        return *(nic_wv_id_t*) key;
     51}
     52
     53static size_t nic_wv_hash(const ht_link_t *item)
    4954{
    5055        nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item;
    51         return (virtue->id == (nic_wv_id_t) key[0]);
    52 }
    53 
    54 /**
    55  * Hash table helper function
    56  */
    57 static void nic_wv_rc(link_t *item)
    58 {
    59 }
    60 
    61 /**
    62  * Hash table helper function
    63  */
    64 static hash_index_t nic_wv_hash(unsigned long keys[])
    65 {
    66         return keys[0] % NIC_WV_HASH_COUNT;
     56        return virtue->id;
     57}
     58
     59static bool nic_wv_key_equal(void *key, const ht_link_t *item)
     60{
     61        nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item;
     62        return (virtue->id == *(nic_wv_id_t*) key);
    6763}
    6864
     
    7773int nic_wol_virtues_init(nic_wol_virtues_t *wvs)
    7874{
    79         bzero(wvs, sizeof (nic_wol_virtues_t));
    80         wvs->table_operations.compare = nic_wv_compare;
     75        bzero(wvs, sizeof(nic_wol_virtues_t));
    8176        wvs->table_operations.hash = nic_wv_hash;
    82         wvs->table_operations.remove_callback = nic_wv_rc;
    83         if (!hash_table_create(&wvs->table, NIC_WV_HASH_COUNT, 1,
    84                 &wvs->table_operations)) {
     77        wvs->table_operations.key_hash = nic_wv_key_hash;
     78        wvs->table_operations.key_equal = nic_wv_key_equal;
     79        wvs->table_operations.equal = 0;
     80        wvs->table_operations.remove_callback = 0;
     81       
     82        if (!hash_table_create(&wvs->table, 0, 0, &wvs->table_operations)) {
    8583                return ENOMEM;
    8684        }
     
    170168        do {
    171169                virtue->id = wvs->next_id++;
    172         } while (NULL !=
    173                 hash_table_find(&wvs->table, (unsigned long *) &virtue->id));
    174         hash_table_insert(&wvs->table,
    175                 (unsigned long *) &virtue->id, &virtue->item);
     170        } while (NULL != hash_table_find(&wvs->table, &virtue->id));
     171        hash_table_insert(&wvs->table, &virtue->item);
    176172        virtue->next = wvs->lists[virtue->type];
    177173        wvs->lists[virtue->type] = virtue;
     
    191187nic_wol_virtue_t *nic_wol_virtues_remove(nic_wol_virtues_t *wvs, nic_wv_id_t id)
    192188{
    193         nic_wol_virtue_t *virtue = (nic_wol_virtue_t *)
    194                 hash_table_find(&wvs->table, (unsigned long *) &id);
     189        nic_wol_virtue_t *virtue =
     190                (nic_wol_virtue_t *) hash_table_find(&wvs->table, &id);
    195191        if (virtue == NULL) {
    196192                return NULL;
     
    198194
    199195        /* Remove from filter_table */
    200         hash_table_remove(&wvs->table, (unsigned long *) &id, 1);
     196        hash_table_remove_item(&wvs->table, &virtue->item);
    201197
    202198        /* Remove from filter_types */
     
    235231         * constant virtue the retyping is correct.
    236232         */
    237         link_t *virtue = hash_table_find(
    238                 &((nic_wol_virtues_t *) wvs)->table, (unsigned long *) &id);
     233        ht_link_t *virtue = hash_table_find(&((nic_wol_virtues_t *) wvs)->table, &id);
    239234        return (const nic_wol_virtue_t *) virtue;
    240235}
  • uspace/lib/posix/include/posix/time.h

    r32b3a12 rb800b0e  
    6262#endif
    6363
    64 #undef ASCTIME_BUF_LEN
    65 #define ASCTIME_BUF_LEN 26
    66 
    6764#undef CLOCK_REALTIME
    6865#define CLOCK_REALTIME ((posix_clockid_t) 0)
    69 
    70 struct posix_tm {
    71         int tm_sec;         /* Seconds [0,60]. */
    72         int tm_min;         /* Minutes [0,59]. */
    73         int tm_hour;        /* Hour [0,23]. */
    74         int tm_mday;        /* Day of month [1,31]. */
    75         int tm_mon;         /* Month of year [0,11]. */
    76         int tm_year;        /* Years since 1900. */
    77         int tm_wday;        /* Day of week [0,6] (Sunday = 0). */
    78         int tm_yday;        /* Day of year [0,365]. */
    79         int tm_isdst;       /* Daylight Savings flag. */
    80 };
    8166
    8267struct posix_timespec {
     
    9883extern void posix_tzset(void);
    9984
    100 /* Elapsed Time */
    101 extern double posix_difftime(time_t time1, time_t time0);
    102 
    10385/* Broken-down Time */
    104 extern time_t posix_mktime(struct posix_tm *tm);
    105 extern struct posix_tm *posix_gmtime(const time_t *timer);
    106 extern struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
    107     struct posix_tm *restrict result);
    108 extern struct posix_tm *posix_localtime(const time_t *timer);
    109 extern struct posix_tm *posix_localtime_r(const time_t *restrict timer,
    110     struct posix_tm *restrict result);
     86extern struct tm *posix_gmtime_r(const time_t *restrict timer,
     87    struct tm *restrict result);
     88extern struct tm *posix_gmtime(const time_t *restrict timep);
     89extern struct tm *posix_localtime_r(const time_t *restrict timer,
     90    struct tm *restrict result);
     91extern struct tm *posix_localtime(const time_t *restrict timep);
    11192
    11293/* Formatting Calendar Time */
    113 extern char *posix_asctime(const struct posix_tm *timeptr);
    114 extern char *posix_asctime_r(const struct posix_tm *restrict timeptr,
     94extern char *posix_asctime_r(const struct tm *restrict timeptr,
    11595    char *restrict buf);
     96extern char *posix_asctime(const struct tm *restrict timeptr);
     97extern char *posix_ctime_r(const time_t *timer, char *buf);
    11698extern char *posix_ctime(const time_t *timer);
    117 extern char *posix_ctime_r(const time_t *timer, char *buf);
    118 extern size_t posix_strftime(char *restrict s, size_t maxsize,
    119     const char *restrict format, const struct posix_tm *restrict tm);
    12099
    121100/* Clocks */
     
    133112
    134113#ifndef LIBPOSIX_INTERNAL
    135         #define tm posix_tm
    136         #define timespec posix_timespec
    137         #define itimerspec posix_itimerspec
    138         #define timer_t posix_timer_t
     114        #define timespec    posix_timespec
     115        #define itimerspec  posix_itimerspec
     116        #define timer_t     posix_timer_t
    139117
    140         #define daylight posix_daylight
    141         #define timezone posix_timezone
    142         #define tzname posix_tzname
    143         #define tzset posix_tzset
     118        #define daylight    posix_daylight
     119        #define timezone    posix_timezone
     120        #define tzname      posix_tzname
     121        #define tzset       posix_tzset
    144122
    145         #define difftime posix_difftime
     123        #define gmtime_r    posix_gmtime_r
     124        #define gmtime      posix_gmtime
     125        #define localtime_r posix_localtime_r
     126        #define localtime   posix_localtime
    146127
    147         #define mktime posix_mktime
    148         #define gmtime posix_gmtime
    149         #define gmtime_r posix_gmtime_r
    150         #define localtime posix_localtime
    151         #define localtime_r posix_localtime_r
    152 
    153         #define asctime posix_asctime
    154         #define asctime_r posix_asctime_r
    155         #define ctime posix_ctime
    156         #define ctime_r posix_ctime_r
    157         #define strftime posix_strftime
     128        #define asctime_r   posix_asctime_r
     129        #define asctime     posix_asctime
     130        #define ctime_r     posix_ctime_r
     131        #define ctime       posix_ctime
    158132
    159133        #define clock_getres posix_clock_getres
  • uspace/lib/posix/source/time.c

    r32b3a12 rb800b0e  
    6161 */
    6262
    63 
    64 
    65 /* Helper functions ***********************************************************/
    66 
    67 #define HOURS_PER_DAY (24)
    68 #define MINS_PER_HOUR (60)
    69 #define SECS_PER_MIN (60)
    70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
    71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
    72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
    73 
    74 /**
    75  * Checks whether the year is a leap year.
    76  *
    77  * @param year Year since 1900 (e.g. for 1970, the value is 70).
    78  * @return true if year is a leap year, false otherwise
    79  */
    80 static bool _is_leap_year(time_t year)
    81 {
    82         year += 1900;
    83 
    84         if (year % 400 == 0)
    85                 return true;
    86         if (year % 100 == 0)
    87                 return false;
    88         if (year % 4 == 0)
    89                 return true;
    90         return false;
    91 }
    92 
    93 /**
    94  * Returns how many days there are in the given month of the given year.
    95  * Note that year is only taken into account if month is February.
    96  *
    97  * @param year Year since 1900 (can be negative).
    98  * @param mon Month of the year. 0 for January, 11 for December.
    99  * @return Number of days in the specified month.
    100  */
    101 static int _days_in_month(time_t year, time_t mon)
    102 {
    103         assert(mon >= 0 && mon <= 11);
    104 
    105         static int month_days[] =
    106                 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    107 
    108         if (mon == 1) {
    109                 year += 1900;
    110                 /* february */
    111                 return _is_leap_year(year) ? 29 : 28;
    112         } else {
    113                 return month_days[mon];
    114         }
    115 }
    116 
    117 /**
    118  * For specified year, month and day of month, returns which day of that year
    119  * it is.
    120  *
    121  * For example, given date 2011-01-03, the corresponding expression is:
    122  *     _day_of_year(111, 0, 3) == 2
    123  *
    124  * @param year Year (year 1900 = 0, can be negative).
    125  * @param mon Month (January = 0).
    126  * @param mday Day of month (First day is 1).
    127  * @return Day of year (First day is 0).
    128  */
    129 static int _day_of_year(time_t year, time_t mon, time_t mday)
    130 {
    131         static int mdays[] =
    132             { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
    133         static int leap_mdays[] =
    134             { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
    135 
    136         return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
    137 }
    138 
    139 /**
    140  * Integer division that rounds to negative infinity.
    141  * Used by some functions in this file.
    142  *
    143  * @param op1 Divident.
    144  * @param op2 Divisor.
    145  * @return Rounded quotient.
    146  */
    147 static time_t _floor_div(time_t op1, time_t op2)
    148 {
    149         if (op1 >= 0 || op1 % op2 == 0) {
    150                 return op1 / op2;
    151         } else {
    152                 return op1 / op2 - 1;
    153         }
    154 }
    155 
    156 /**
    157  * Modulo that rounds to negative infinity.
    158  * Used by some functions in this file.
    159  *
    160  * @param op1 Divident.
    161  * @param op2 Divisor.
    162  * @return Remainder.
    163  */
    164 static time_t _floor_mod(time_t op1, time_t op2)
    165 {
    166         int div = _floor_div(op1, op2);
    167 
    168         /* (a / b) * b + a % b == a */
    169         /* thus, a % b == a - (a / b) * b */
    170 
    171         int result = op1 - div * op2;
    172        
    173         /* Some paranoid checking to ensure I didn't make a mistake here. */
    174         assert(result >= 0);
    175         assert(result < op2);
    176         assert(div * op2 + result == op1);
    177        
    178         return result;
    179 }
    180 
    181 /**
    182  * Number of days since the Epoch.
    183  * Epoch is 1970-01-01, which is also equal to day 0.
    184  *
    185  * @param year Year (year 1900 = 0, may be negative).
    186  * @param mon Month (January = 0).
    187  * @param mday Day of month (first day = 1).
    188  * @return Number of days since the Epoch.
    189  */
    190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
    191 {
    192         return (year - 70) * 365 + _floor_div(year - 69, 4) -
    193             _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
    194             _day_of_year(year, mon, mday);
    195 }
    196 
    197 /**
    198  * Seconds since the Epoch. see also _days_since_epoch().
    199  *
    200  * @param tm Normalized broken-down time.
    201  * @return Number of seconds since the epoch, not counting leap seconds.
    202  */
    203 static time_t _secs_since_epoch(const struct posix_tm *tm)
    204 {
    205         return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
    206             SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
    207             tm->tm_min * SECS_PER_MIN + tm->tm_sec;
    208 }
    209 
    210 /**
    211  * Which day of week the specified date is.
    212  *
    213  * @param year Year (year 1900 = 0).
    214  * @param mon Month (January = 0).
    215  * @param mday Day of month (first = 1).
    216  * @return Day of week (Sunday = 0).
    217  */
    218 static int _day_of_week(time_t year, time_t mon, time_t mday)
    219 {
    220         /* 1970-01-01 is Thursday */
    221         return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
    222 }
    223 
    224 /**
    225  * Normalizes the broken-down time and optionally adds specified amount of
    226  * seconds.
    227  *
    228  * @param tm Broken-down time to normalize.
    229  * @param sec_add Seconds to add.
    230  * @return 0 on success, -1 on overflow
    231  */
    232 static int _normalize_time(struct posix_tm *tm, time_t sec_add)
    233 {
    234         // TODO: DST correction
    235 
    236         /* Set initial values. */
    237         time_t sec = tm->tm_sec + sec_add;
    238         time_t min = tm->tm_min;
    239         time_t hour = tm->tm_hour;
    240         time_t day = tm->tm_mday - 1;
    241         time_t mon = tm->tm_mon;
    242         time_t year = tm->tm_year;
    243 
    244         /* Adjust time. */
    245         min += _floor_div(sec, SECS_PER_MIN);
    246         sec = _floor_mod(sec, SECS_PER_MIN);
    247         hour += _floor_div(min, MINS_PER_HOUR);
    248         min = _floor_mod(min, MINS_PER_HOUR);
    249         day += _floor_div(hour, HOURS_PER_DAY);
    250         hour = _floor_mod(hour, HOURS_PER_DAY);
    251 
    252         /* Adjust month. */
    253         year += _floor_div(mon, 12);
    254         mon = _floor_mod(mon, 12);
    255 
    256         /* Now the difficult part - days of month. */
    257        
    258         /* First, deal with whole cycles of 400 years = 146097 days. */
    259         year += _floor_div(day, 146097) * 400;
    260         day = _floor_mod(day, 146097);
    261        
    262         /* Then, go in one year steps. */
    263         if (mon <= 1) {
    264                 /* January and February. */
    265                 while (day > 365) {
    266                         day -= _is_leap_year(year) ? 366 : 365;
    267                         year++;
    268                 }
    269         } else {
    270                 /* Rest of the year. */
    271                 while (day > 365) {
    272                         day -= _is_leap_year(year + 1) ? 366 : 365;
    273                         year++;
    274                 }
    275         }
    276        
    277         /* Finally, finish it off month per month. */
    278         while (day >= _days_in_month(year, mon)) {
    279                 day -= _days_in_month(year, mon);
    280                 mon++;
    281                 if (mon >= 12) {
    282                         mon -= 12;
    283                         year++;
    284                 }
    285         }
    286        
    287         /* Calculate the remaining two fields. */
    288         tm->tm_yday = _day_of_year(year, mon, day + 1);
    289         tm->tm_wday = _day_of_week(year, mon, day + 1);
    290        
    291         /* And put the values back to the struct. */
    292         tm->tm_sec = (int) sec;
    293         tm->tm_min = (int) min;
    294         tm->tm_hour = (int) hour;
    295         tm->tm_mday = (int) day + 1;
    296         tm->tm_mon = (int) mon;
    297        
    298         /* Casts to work around libc brain-damage. */
    299         if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
    300                 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
    301                 return -1;
    302         }
    303        
    304         tm->tm_year = (int) year;
    305         return 0;
    306 }
    307 
    308 /**
    309  * Which day the week-based year starts on, relative to the first calendar day.
    310  * E.g. if the year starts on December 31st, the return value is -1.
    311  *
    312  * @param Year since 1900.
    313  * @return Offset of week-based year relative to calendar year.
    314  */
    315 static int _wbyear_offset(int year)
    316 {
    317         int start_wday = _day_of_week(year, 0, 1);
    318         return _floor_mod(4 - start_wday, 7) - 3;
    319 }
    320 
    321 /**
    322  * Returns week-based year of the specified time.
    323  *
    324  * @param tm Normalized broken-down time.
    325  * @return Week-based year.
    326  */
    327 static int _wbyear(const struct posix_tm *tm)
    328 {
    329         int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
    330         if (day < 0) {
    331                 /* Last week of previous year. */
    332                 return tm->tm_year - 1;
    333         }
    334         if (day > 364 + _is_leap_year(tm->tm_year)) {
    335                 /* First week of next year. */
    336                 return tm->tm_year + 1;
    337         }
    338         /* All the other days are in the calendar year. */
    339         return tm->tm_year;
    340 }
    341 
    342 /**
    343  * Week number of the year, assuming weeks start on sunday.
    344  * The first Sunday of January is the first day of week 1;
    345  * days in the new year before this are in week 0.
    346  *
    347  * @param tm Normalized broken-down time.
    348  * @return The week number (0 - 53).
    349  */
    350 static int _sun_week_number(const struct posix_tm *tm)
    351 {
    352         int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
    353         return (tm->tm_yday - first_day + 7) / 7;
    354 }
    355 
    356 /**
    357  * Week number of the year, assuming weeks start on monday.
    358  * If the week containing January 1st has four or more days in the new year,
    359  * then it is considered week 1. Otherwise, it is the last week of the previous
    360  * year, and the next week is week 1. Both January 4th and the first Thursday
    361  * of January are always in week 1.
    362  *
    363  * @param tm Normalized broken-down time.
    364  * @return The week number (1 - 53).
    365  */
    366 static int _iso_week_number(const struct posix_tm *tm)
    367 {
    368         int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
    369         if (day < 0) {
    370                 /* Last week of previous year. */
    371                 return 53;
    372         }
    373         if (day > 364 + _is_leap_year(tm->tm_year)) {
    374                 /* First week of next year. */
    375                 return 1;
    376         }
    377         /* All the other days give correct answer. */
    378         return (day / 7 + 1);
    379 }
    380 
    381 /**
    382  * Week number of the year, assuming weeks start on monday.
    383  * The first Monday of January is the first day of week 1;
    384  * days in the new year before this are in week 0.
    385  *
    386  * @param tm Normalized broken-down time.
    387  * @return The week number (0 - 53).
    388  */
    389 static int _mon_week_number(const struct posix_tm *tm)
    390 {
    391         int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
    392         return (tm->tm_yday - first_day + 7) / 7;
    393 }
    394 
    395 /******************************************************************************/
    396 
    39763int posix_daylight;
    39864long posix_timezone;
     
    41278
    41379/**
    414  * Calculate the difference between two times, in seconds.
    415  *
    416  * @param time1 First time.
    417  * @param time0 Second time.
    418  * @return Time in seconds.
    419  */
    420 double posix_difftime(time_t time1, time_t time0)
    421 {
    422         return (double) (time1 - time0);
    423 }
    424 
    425 /**
    426  * This function first normalizes the provided broken-down time
    427  * (moves all values to their proper bounds) and then tries to
    428  * calculate the appropriate time_t representation.
    429  *
    430  * @param tm Broken-down time.
    431  * @return time_t representation of the time, undefined value on overflow.
    432  */
    433 time_t posix_mktime(struct posix_tm *tm)
    434 {
    435         // TODO: take DST flag into account
    436         // TODO: detect overflow
    437 
    438         _normalize_time(tm, 0);
    439         return _secs_since_epoch(tm);
    440 }
    441 
    442 /**
    443  * Converts a time value to a broken-down UTC time.
    444  *
    445  * @param timer Time to convert.
    446  * @return Normalized broken-down time in UTC, NULL on overflow.
    447  */
    448 struct posix_tm *posix_gmtime(const time_t *timer)
    449 {
    450         assert(timer != NULL);
    451 
    452         static struct posix_tm result;
    453         return posix_gmtime_r(timer, &result);
    454 }
    455 
    456 /**
    45780 * Converts a time value to a broken-down UTC time.
    45881 *
     
    46184 * @return Value of result on success, NULL on overflow.
    46285 */
    463 struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
    464     struct posix_tm *restrict result)
    465 {
    466         assert(timer != NULL);
    467         assert(result != NULL);
    468 
    469         /* Set result to epoch. */
    470         result->tm_sec = 0;
    471         result->tm_min = 0;
    472         result->tm_hour = 0;
    473         result->tm_mday = 1;
    474         result->tm_mon = 0;
    475         result->tm_year = 70; /* 1970 */
    476 
    477         if (_normalize_time(result, *timer) == -1) {
    478                 errno = EOVERFLOW;
     86struct tm *posix_gmtime_r(const time_t *restrict timer,
     87    struct tm *restrict result)
     88{
     89        int rc = time_utc2tm(*timer, result);
     90        if (rc != EOK) {
     91                errno = rc;
    47992                return NULL;
    48093        }
     
    48497
    48598/**
    486  * Converts a time value to a broken-down local time.
    487  *
    488  * @param timer Time to convert.
    489  * @return Normalized broken-down time in local timezone, NULL on overflow.
    490  */
    491 struct posix_tm *posix_localtime(const time_t *timer)
    492 {
    493         static struct posix_tm result;
    494         return posix_localtime_r(timer, &result);
     99 * Converts a time value to a broken-down UTC time.
     100 * (non reentrant version)
     101 *
     102 * @param timep  Time to convert
     103 * @return       Pointer to a statically allocated structure that stores
     104 *               the result, NULL in case of error.
     105 */
     106struct tm *posix_gmtime(const time_t *restrict timep)
     107{
     108        static struct tm result;
     109
     110        return posix_gmtime_r(timep, &result);
    495111}
    496112
     
    502118 * @return Value of result on success, NULL on overflow.
    503119 */
    504 struct posix_tm *posix_localtime_r(const time_t *restrict timer,
    505     struct posix_tm *restrict result)
     120struct tm *posix_localtime_r(const time_t *restrict timer,
     121    struct tm *restrict result)
    506122{
    507123        // TODO: deal with timezone
     
    511127
    512128/**
    513  * Converts broken-down time to a string in format
    514  * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
    515  *
    516  * @param timeptr Broken-down time structure.
    517  * @return Pointer to a statically allocated string.
    518  */
    519 char *posix_asctime(const struct posix_tm *timeptr)
    520 {
    521         static char buf[ASCTIME_BUF_LEN];
    522         return posix_asctime_r(timeptr, buf);
     129 * Converts a time value to a broken-down local time.
     130 * (non reentrant version)
     131 *
     132 * @param timep    Time to convert.
     133 * @return         Pointer to a statically allocated structure that stores
     134 *                 the result, NULL in case of error.
     135 */
     136struct tm *posix_localtime(const time_t *restrict timep)
     137{
     138        static struct tm result;
     139
     140        return posix_localtime_r(timep, &result);
    523141}
    524142
     
    532150 * @return Value of buf.
    533151 */
    534 char *posix_asctime_r(const struct posix_tm *restrict timeptr,
     152char *posix_asctime_r(const struct tm *restrict timeptr,
    535153    char *restrict buf)
    536154{
    537         assert(timeptr != NULL);
    538         assert(buf != NULL);
    539 
    540         static const char *wday[] = {
    541                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    542         };
    543         static const char *mon[] = {
    544                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    545                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    546         };
    547 
    548         snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
    549             wday[timeptr->tm_wday],
    550             mon[timeptr->tm_mon],
    551             timeptr->tm_mday, timeptr->tm_hour,
    552             timeptr->tm_min, timeptr->tm_sec,
    553             1900 + timeptr->tm_year);
    554 
     155        time_tm2str(timeptr, buf);
    555156        return buf;
    556157}
    557158
    558159/**
    559  * Equivalent to asctime(localtime(clock)).
    560  *
    561  * @param timer Time to convert.
    562  * @return Pointer to a statically allocated string holding the date.
    563  */
    564 char *posix_ctime(const time_t *timer)
    565 {
    566         struct posix_tm *loctime = posix_localtime(timer);
    567         if (loctime == NULL) {
    568                 return NULL;
    569         }
    570         return posix_asctime(loctime);
    571 }
    572 
    573 /**
    574  * Reentrant variant of ctime().
     160 * Convers broken-down time to a string in format
     161 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     162 * (non reentrant version)
     163 *
     164 * @param timeptr    Broken-down time structure.
     165 * @return           Pointer to a statically allocated buffer that stores
     166 *                   the result, NULL in case of error.
     167 */
     168char *posix_asctime(const struct tm *restrict timeptr)
     169{
     170        static char buf[ASCTIME_BUF_LEN];
     171
     172        return posix_asctime_r(timeptr, buf);
     173}
     174
     175/**
     176 * Converts the calendar time to a string in format
     177 * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
    575178 *
    576179 * @param timer Time to convert.
    577180 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
    578181 *     bytes long.
    579  * @return Pointer to buf on success, NULL on falure.
     182 * @return Pointer to buf on success, NULL on failure.
    580183 */
    581184char *posix_ctime_r(const time_t *timer, char *buf)
    582185{
    583         struct posix_tm loctime;
    584         if (posix_localtime_r(timer, &loctime) == NULL) {
     186        int r = time_local2str(*timer, buf);
     187        if (r != EOK) {
     188                errno = r;
    585189                return NULL;
    586190        }
    587         return posix_asctime_r(&loctime, buf);
    588 }
    589 
    590 /**
    591  * Convert time and date to a string, based on a specified format and
    592  * current locale.
    593  *
    594  * @param s Buffer to write string to.
    595  * @param maxsize Size of the buffer.
    596  * @param format Format of the output.
    597  * @param tm Broken-down time to format.
    598  * @return Number of bytes written.
    599  */
    600 size_t posix_strftime(char *restrict s, size_t maxsize,
    601     const char *restrict format, const struct posix_tm *restrict tm)
    602 {
    603         assert(s != NULL);
    604         assert(format != NULL);
    605         assert(tm != NULL);
    606 
    607         // TODO: use locale
    608         static const char *wday_abbr[] = {
    609                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    610         };
    611         static const char *wday[] = {
    612                 "Sunday", "Monday", "Tuesday", "Wednesday",
    613                 "Thursday", "Friday", "Saturday"
    614         };
    615         static const char *mon_abbr[] = {
    616                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    617                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    618         };
    619         static const char *mon[] = {
    620                 "January", "February", "March", "April", "May", "June", "July",
    621                 "August", "September", "October", "November", "December"
    622         };
    623        
    624         if (maxsize < 1) {
    625                 return 0;
    626         }
    627        
    628         char *ptr = s;
    629         size_t consumed;
    630         size_t remaining = maxsize;
    631        
    632         #define append(...) { \
    633                 /* FIXME: this requires POSIX-correct snprintf */ \
    634                 /*        otherwise it won't work with non-ascii chars */ \
    635                 consumed = snprintf(ptr, remaining, __VA_ARGS__); \
    636                 if (consumed >= remaining) { \
    637                         return 0; \
    638                 } \
    639                 ptr += consumed; \
    640                 remaining -= consumed; \
    641         }
    642        
    643         #define recurse(fmt) { \
    644                 consumed = posix_strftime(ptr, remaining, fmt, tm); \
    645                 if (consumed == 0) { \
    646                         return 0; \
    647                 } \
    648                 ptr += consumed; \
    649                 remaining -= consumed; \
    650         }
    651        
    652         #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
    653             (((hour) == 0) ? 12 : (hour)))
    654        
    655         while (*format != '\0') {
    656                 if (*format != '%') {
    657                         append("%c", *format);
    658                         format++;
    659                         continue;
    660                 }
    661                
    662                 format++;
    663                 if (*format == '0' || *format == '+') {
    664                         // TODO: padding
    665                         format++;
    666                 }
    667                 while (isdigit(*format)) {
    668                         // TODO: padding
    669                         format++;
    670                 }
    671                 if (*format == 'O' || *format == 'E') {
    672                         // TODO: locale's alternative format
    673                         format++;
    674                 }
    675                
    676                 switch (*format) {
    677                 case 'a':
    678                         append("%s", wday_abbr[tm->tm_wday]); break;
    679                 case 'A':
    680                         append("%s", wday[tm->tm_wday]); break;
    681                 case 'b':
    682                         append("%s", mon_abbr[tm->tm_mon]); break;
    683                 case 'B':
    684                         append("%s", mon[tm->tm_mon]); break;
    685                 case 'c':
    686                         // TODO: locale-specific datetime format
    687                         recurse("%Y-%m-%d %H:%M:%S"); break;
    688                 case 'C':
    689                         append("%02d", (1900 + tm->tm_year) / 100); break;
    690                 case 'd':
    691                         append("%02d", tm->tm_mday); break;
    692                 case 'D':
    693                         recurse("%m/%d/%y"); break;
    694                 case 'e':
    695                         append("%2d", tm->tm_mday); break;
    696                 case 'F':
    697                         recurse("%+4Y-%m-%d"); break;
    698                 case 'g':
    699                         append("%02d", _wbyear(tm) % 100); break;
    700                 case 'G':
    701                         append("%d", _wbyear(tm)); break;
    702                 case 'h':
    703                         recurse("%b"); break;
    704                 case 'H':
    705                         append("%02d", tm->tm_hour); break;
    706                 case 'I':
    707                         append("%02d", TO_12H(tm->tm_hour)); break;
    708                 case 'j':
    709                         append("%03d", tm->tm_yday); break;
    710                 case 'k':
    711                         append("%2d", tm->tm_hour); break;
    712                 case 'l':
    713                         append("%2d", TO_12H(tm->tm_hour)); break;
    714                 case 'm':
    715                         append("%02d", tm->tm_mon); break;
    716                 case 'M':
    717                         append("%02d", tm->tm_min); break;
    718                 case 'n':
    719                         append("\n"); break;
    720                 case 'p':
    721                         append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
    722                 case 'P':
    723                         append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
    724                 case 'r':
    725                         recurse("%I:%M:%S %p"); break;
    726                 case 'R':
    727                         recurse("%H:%M"); break;
    728                 case 's':
    729                         append("%ld", _secs_since_epoch(tm)); break;
    730                 case 'S':
    731                         append("%02d", tm->tm_sec); break;
    732                 case 't':
    733                         append("\t"); break;
    734                 case 'T':
    735                         recurse("%H:%M:%S"); break;
    736                 case 'u':
    737                         append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); break;
    738                 case 'U':
    739                         append("%02d", _sun_week_number(tm)); break;
    740                 case 'V':
    741                         append("%02d", _iso_week_number(tm)); break;
    742                 case 'w':
    743                         append("%d", tm->tm_wday); break;
    744                 case 'W':
    745                         append("%02d", _mon_week_number(tm)); break;
    746                 case 'x':
    747                         // TODO: locale-specific date format
    748                         recurse("%Y-%m-%d"); break;
    749                 case 'X':
    750                         // TODO: locale-specific time format
    751                         recurse("%H:%M:%S"); break;
    752                 case 'y':
    753                         append("%02d", tm->tm_year % 100); break;
    754                 case 'Y':
    755                         append("%d", 1900 + tm->tm_year); break;
    756                 case 'z':
    757                         // TODO: timezone
    758                         break;
    759                 case 'Z':
    760                         // TODO: timezone
    761                         break;
    762                 case '%':
    763                         append("%%");
    764                         break;
    765                 default:
    766                         /* Invalid specifier, print verbatim. */
    767                         while (*format != '%') {
    768                                 format--;
    769                         }
    770                         append("%%");
    771                         break;
    772                 }
    773                 format++;
    774         }
    775        
    776         #undef append
    777         #undef recurse
    778        
    779         return maxsize - remaining;
     191
     192        return buf;
     193}
     194
     195/**
     196 * Converts the calendar time to a string in format
     197 * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
     198 * (non reentrant version)
     199 *
     200 * @param timep    Time to convert.
     201 * @return         Pointer to a statically allocated buffer that stores
     202 *                 the result, NULL in case of error.
     203 */
     204char *posix_ctime(const time_t *timep)
     205{
     206        static char buf[ASCTIME_BUF_LEN];
     207
     208        return posix_ctime_r(timep, buf);
    780209}
    781210
     
    894323        stats_task_t *task_stats = stats_get_task(task_get_id());
    895324        if (task_stats) {
    896                 total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles);
     325                total_cycles = (posix_clock_t) (task_stats->kcycles +
     326                    task_stats->ucycles);
    897327                free(task_stats);
    898328                task_stats = 0;
  • uspace/lib/softfloat/Makefile

    r32b3a12 rb800b0e  
    2929
    3030USPACE_PREFIX = ../..
    31 EXTRA_CFLAGS = -Iinclude
    3231LIBRARY = libsoftfloat
    3332
    3433SOURCES = \
    35         generic/add.c \
    36         generic/common.c \
    37         generic/comparison.c \
    38         generic/conversion.c \
    39         generic/div.c \
    40         generic/mul.c \
    41         generic/other.c \
    42         generic/softfloat.c \
    43         generic/sub.c
     34        softfloat.c \
     35        common.c \
     36        add.c \
     37        sub.c \
     38        div.c \
     39        mul.c \
     40        comparison.c \
     41        conversion.c \
     42        other.c
    4443
    4544include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/softfloat/add.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <add.h>
    38 #include <comparison.h>
    39 #include <common.h>
     36#include "sftypes.h"
     37#include "add.h"
     38#include "comparison.h"
     39#include "common.h"
    4040
    4141/** Add two single-precision floats with the same sign.
     
    9090                /* both are denormalized */
    9191                frac1 += frac2;
    92                 if (frac1 & FLOAT32_HIDDEN_BIT_MASK ) {
     92                if (frac1 & FLOAT32_HIDDEN_BIT_MASK) {
    9393                        /* result is not denormalized */
    9494                        a.parts.exp = 1;
     
    112112        frac2 <<= 6;
    113113       
    114         if (expdiff < (FLOAT32_FRACTION_SIZE + 2) ) {
     114        if (expdiff < (FLOAT32_FRACTION_SIZE + 2)) {
    115115                frac2 >>= expdiff;
    116116                frac1 += frac2;
     
    121121        }
    122122       
    123         if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7) ) {
     123        if (frac1 & (FLOAT32_HIDDEN_BIT_MASK << 7)) {
    124124                ++exp1;
    125125                frac1 >>= 1;
     
    135135        }
    136136       
    137         if ((exp1 == FLOAT32_MAX_EXPONENT ) || (exp2 > exp1)) {
     137        if ((exp1 == FLOAT32_MAX_EXPONENT) || (exp2 > exp1)) {
    138138                /* overflow - set infinity as result */
    139139                a.parts.exp = FLOAT32_MAX_EXPONENT;
     
    250250        }
    251251       
    252         if ((exp1 == FLOAT64_MAX_EXPONENT ) || (exp2 > exp1)) {
     252        if ((exp1 == FLOAT64_MAX_EXPONENT) || (exp2 > exp1)) {
    253253                /* overflow - set infinity as result */
    254254                a.parts.exp = FLOAT64_MAX_EXPONENT;
     
    259259        a.parts.exp = exp1;
    260260        /* Clear hidden bit and shift */
    261         a.parts.fraction = ((frac1 >> 6 ) & (~FLOAT64_HIDDEN_BIT_MASK));
     261        a.parts.fraction = ((frac1 >> 6) & (~FLOAT64_HIDDEN_BIT_MASK));
    262262        return a;
    263263}
  • uspace/lib/softfloat/common.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <common.h>
     36#include "sftypes.h"
     37#include "common.h"
    3838
    3939/* Table for fast leading zeroes counting. */
     
    5757};
    5858
    59 /** 
     59/**
    6060 * Take fraction shifted by 10 bits to the left, round it, normalize it
    6161 * and detect exceptions
     
    7575        while ((cexp > 0) && (cfrac) &&
    7676            (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1))))) {
    77                 cexp--; 
     77                cexp--;
    7878                cfrac <<= 1;
    7979                /* TODO: fix underflow */
     
    110110                ++cexp;
    111111                cfrac >>= 1;
    112         }       
     112        }
    113113
    114114        /* check overflow */
  • uspace/lib/softfloat/common.h

    r32b3a12 rb800b0e  
    3737#define __COMMON_H__
    3838
    39 #include <sftypes.h>
     39#include "sftypes.h"
    4040
    4141extern float64 finish_float64(int32_t, uint64_t, char);
  • uspace/lib/softfloat/comparison.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <comparison.h>
    38 #include <common.h>
     36#include "sftypes.h"
     37#include "comparison.h"
     38#include "common.h"
    3939
    4040/**
  • uspace/lib/softfloat/conversion.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <conversion.h>
    38 #include <comparison.h>
    39 #include <common.h>
     36#include "sftypes.h"
     37#include "conversion.h"
     38#include "comparison.h"
     39#include "common.h"
    4040
    4141float64 float32_to_float64(float32 a)
  • uspace/lib/softfloat/div.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <add.h>
    38 #include <div.h>
    39 #include <comparison.h>
    40 #include <mul.h>
    41 #include <common.h>
     36#include "sftypes.h"
     37#include "add.h"
     38#include "div.h"
     39#include "comparison.h"
     40#include "mul.h"
     41#include "common.h"
    4242
    4343/** Divide two single-precision floats.
  • uspace/lib/softfloat/mul.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <mul.h>
    38 #include <comparison.h>
    39 #include <common.h>
     36#include "sftypes.h"
     37#include "mul.h"
     38#include "comparison.h"
     39#include "common.h"
    4040
    4141/** Multiply two single-precision floats.
  • uspace/lib/softfloat/softfloat.c

    r32b3a12 rb800b0e  
    3636 */
    3737
    38 #include <softfloat.h>
    39 #include <sftypes.h>
    40 
    41 #include <add.h>
    42 #include <sub.h>
    43 #include <mul.h>
    44 #include <div.h>
    45 
    46 #include <conversion.h>
    47 #include <comparison.h>
    48 #include <other.h>
     38#include "softfloat.h"
     39#include "sftypes.h"
     40#include "add.h"
     41#include "sub.h"
     42#include "mul.h"
     43#include "div.h"
     44#include "conversion.h"
     45#include "comparison.h"
     46#include "other.h"
    4947
    5048/* Arithmetic functions */
     
    12771275}
    12781276
     1277int __aeabi_f2iz(float a)
     1278{
     1279        return __fixsfsi(a);
     1280}
     1281
    12791282int __aeabi_d2iz(double a)
    12801283{
     
    13001303{
    13011304        return __ltdf2(a, b);
     1305}
     1306
     1307int __aeabi_dcmpeq(double a, double b)
     1308{
     1309        return __eqdf2(a, b);
     1310}
     1311
     1312float __aeabi_fadd(float a, float b)
     1313{
     1314        return __addsf3(a, b);
     1315}
     1316
     1317float __aeabi_fsub(float a, float b)
     1318{
     1319        return __subsf3(a, b);
     1320}
     1321
     1322float __aeabi_fmul(float a, float b)
     1323{
     1324        return __mulsf3(a, b);
     1325}
     1326
     1327float __aeabi_fdiv(float a, float b)
     1328{
     1329        return __divsf3(a, b);
    13021330}
    13031331
  • uspace/lib/softfloat/softfloat.h

    r32b3a12 rb800b0e  
    207207extern double __aeabi_ui2d(unsigned int);
    208208extern unsigned int __aeabi_d2uiz(double);
     209
     210extern int __aeabi_f2iz(float);
    209211extern int __aeabi_d2iz(double);
    210212
     
    212214extern int __aeabi_dcmpgt(double, double);
    213215extern int __aeabi_dcmplt(double, double);
     216extern int __aeabi_dcmpeq(double, double);
     217
     218extern float __aeabi_fadd(float, float);
     219extern float __aeabi_fsub(float, float);
     220extern float __aeabi_fmul(float, float);
     221extern float __aeabi_fdiv(float, float);
    214222
    215223extern double __aeabi_dadd(double, double);
  • uspace/lib/softfloat/sub.c

    r32b3a12 rb800b0e  
    3434 */
    3535
    36 #include <sftypes.h>
    37 #include <sub.h>
    38 #include <comparison.h>
    39 #include <common.h>
     36#include "sftypes.h"
     37#include "sub.h"
     38#include "comparison.h"
     39#include "common.h"
    4040
    4141/** Subtract two single-precision floats with the same sign.
  • uspace/lib/usb/include/usb/debug.h

    r32b3a12 rb800b0e  
    3838#include <inttypes.h>
    3939#include <usb/usb.h>
     40#include <io/log.h>
    4041#include <assert.h>
    4142
     
    4344    const uint8_t *, size_t);
    4445
    45 /** Logging level. */
    46 typedef enum {
    47         /** Fatal, unrecoverable, error.
    48          * Such error prevents the driver from working at all.
    49          */
    50         USB_LOG_LEVEL_FATAL,
     46#define USB_LOG_LEVEL_FATAL LVL_FATAL
     47#define USB_LOG_LEVEL_ERROR LVL_ERROR
     48#define USB_LOG_LEVEL_WARNING LVL_WARN
     49#define USB_LOG_LEVEL_INFO LVL_NOTE
     50#define USB_LOG_LEVEL_DEBUG LVL_DEBUG
     51#define USB_LOG_LEVEL_DEBUG2 LVL_DEBUG2
    5152
    52         /** Serious but recoverable error
    53          * Shall be used for errors fatal for single device but not for
    54          * driver itself.
    55          */
    56         USB_LOG_LEVEL_ERROR,
    57 
    58         /** Warning.
    59          * Problems from which the driver is able to recover gracefully.
    60          */
    61         USB_LOG_LEVEL_WARNING,
    62 
    63         /** Information message.
    64          * This should be the last level that is printed by default to
    65          * the screen.
    66          * Typical usage is to inform that new device was found and what
    67          * are its capabilities.
    68          * Do not use for repetitive actions (such as device polling).
    69          */
    70         USB_LOG_LEVEL_INFO,
    71 
    72         /** Debugging message. */
    73         USB_LOG_LEVEL_DEBUG,
    74 
    75         /** More detailed debugging message. */
    76         USB_LOG_LEVEL_DEBUG2,
    77 
    78         /** Terminating constant for logging levels. */
    79         USB_LOG_LEVEL_MAX
    80 } usb_log_level_t;
    81 
    82 /** Default log level. */
    83 #ifdef CONFIG_USB_VERBOSE
    84         #define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_DEBUG
    85 #else
    86         #define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_INFO
    87 #endif
    88 
    89 void usb_log_enable(usb_log_level_t, const char *);
    90 
    91 void usb_log_printf(usb_log_level_t, const char *, ...)
    92         PRINTF_ATTRIBUTE(2, 3);
     53#define usb_log_printf(level, format, ...) \
     54        log_msg(LOG_DEFAULT, level, format, ##__VA_ARGS__)
    9355
    9456/** Log fatal error. */
  • uspace/lib/usb/src/debug.c

    r32b3a12 rb800b0e  
    4040#include <ddf/log.h>
    4141#include <usb/debug.h>
    42 
    43 /** Level of logging messages. */
    44 static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
    45 
    46 /** Prefix for logging messages. */
    47 static const char *log_prefix = "usb";
    48 
    49 /** Serialization mutex for logging functions. */
    50 static FIBRIL_MUTEX_INITIALIZE(log_serializer);
    51 
    52 /** File where to store the log. */
    53 static FILE *log_stream = NULL;
    54 
    55 
    56 /** Enable logging.
    57  *
    58  * @param level Maximal enabled level (including this one).
    59  * @param message_prefix Prefix for each printed message.
    60  */
    61 void usb_log_enable(usb_log_level_t level, const char *message_prefix)
    62 {
    63         log_prefix = message_prefix;
    64         log_level = level;
    65         if (log_stream == NULL) {
    66                 char *fname;
    67                 int rc = asprintf(&fname, "/log/%s", message_prefix);
    68                 if (rc > 0) {
    69                         log_stream = fopen(fname, "w");
    70                         if (log_stream != NULL)
    71                                 setvbuf(log_stream, NULL, _IOFBF, BUFSIZ);
    72                        
    73                         free(fname);
    74                 }
    75         }
    76 }
    77 
    78 /** Get log level name prefix.
    79  *
    80  * @param level Log level.
    81  * @return String prefix for the message.
    82  */
    83 static const char *log_level_name(usb_log_level_t level)
    84 {
    85         switch (level) {
    86                 case USB_LOG_LEVEL_FATAL:
    87                         return " FATAL";
    88                 case USB_LOG_LEVEL_ERROR:
    89                         return " ERROR";
    90                 case USB_LOG_LEVEL_WARNING:
    91                         return " WARN";
    92                 case USB_LOG_LEVEL_INFO:
    93                         return " info";
    94                 default:
    95                         return "";
    96         }
    97 }
    98 
    99 /** Print logging message.
    100  *
    101  * @param level Verbosity level of the message.
    102  * @param format Formatting directive.
    103  */
    104 void usb_log_printf(usb_log_level_t level, const char *format, ...)
    105 {
    106         FILE *screen_stream = NULL;
    107         switch (level) {
    108                 case USB_LOG_LEVEL_FATAL:
    109                 case USB_LOG_LEVEL_ERROR:
    110                         screen_stream = stderr;
    111                         break;
    112                 default:
    113                         screen_stream = stdout;
    114                         break;
    115         }
    116         assert(screen_stream != NULL);
    117 
    118         va_list args;
    119 
    120         /*
    121          * Serialize access to log files.
    122          * Print to screen only messages with higher level than the one
    123          * specified during logging initialization.
    124          * Print also to file, to it print one more (lower) level as well.
    125          */
    126         fibril_mutex_lock(&log_serializer);
    127 
    128         const char *level_name = log_level_name(level);
    129 
    130         if ((log_stream != NULL) && (level <= log_level + 1)) {
    131                 va_start(args, format);
    132 
    133                 fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
    134                 vfprintf(log_stream, format, args);
    135                 fflush(log_stream);
    136 
    137                 va_end(args);
    138         }
    139 
    140         if (level <= log_level) {
    141                 va_start(args, format);
    142 
    143                 fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
    144                 vfprintf(screen_stream, format, args);
    145                 fflush(screen_stream);
    146 
    147                 va_end(args);
    148         }
    149 
    150         fibril_mutex_unlock(&log_serializer);
    151 }
    152 
    15342
    15443#define REMAINDER_STR_FMT " (%zu)..."
Note: See TracChangeset for help on using the changeset viewer.