Changeset e2a6b72 in mainline for uspace/lib/c


Ignore:
Timestamp:
2012-10-15T16:28:58Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b3ab8f7
Parents:
7eb49f4 (diff), c4c2406 (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 and io improvements.

Location:
uspace/lib/c
Files:
8 added
1 deleted
30 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/Makefile

    r7eb49f4 re2a6b72  
    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 \
     
    101103        generic/io/printf.c \
    102104        generic/io/log.c \
     105        generic/io/logctl.c \
    103106        generic/io/klog.c \
    104107        generic/io/snprintf.c \
     
    121124        generic/adt/list.c \
    122125        generic/adt/hash_table.c \
    123         generic/adt/hash_set.c \
    124126        generic/adt/dynamic_fifo.c \
    125127        generic/adt/char_map.c \
     
    138140        generic/sort.c \
    139141        generic/stats.c \
    140         generic/assert.c
     142        generic/assert.c \
     143        generic/pio_trace.c
    141144
    142145ifeq ($(CONFIG_RTLD),y)
  • uspace/lib/c/arch/abs32le/include/ddi.h

    r7eb49f4 re2a6b72  
    3636#include <libarch/types.h>
    3737
    38 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     38static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    3939{
    4040        *port = v;
    4141}
    4242
    43 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     43static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    4444{
    4545        *port = v;
    4646}
    4747
    48 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     48static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    4949{
    5050        *port = v;
    5151}
    5252
    53 static inline uint8_t pio_read_8(ioport8_t *port)
     53static inline uint8_t arch_pio_read_8(ioport8_t *port)
    5454{
    5555        return *port;
    5656}
    5757
    58 static inline uint16_t pio_read_16(ioport16_t *port)
     58static inline uint16_t arch_pio_read_16(ioport16_t *port)
    5959{
    6060        return *port;
    6161}
    6262
    63 static inline uint32_t pio_read_32(ioport32_t *port)
     63static inline uint32_t arch_pio_read_32(ioport32_t *port)
    6464{
    6565        return *port;
  • uspace/lib/c/arch/arm32/Makefile.common

    r7eb49f4 re2a6b72  
    2828#
    2929
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR))
    3132
  • uspace/lib/c/arch/arm32/include/ddi.h

    r7eb49f4 re2a6b72  
    3737#include <libarch/types.h>
    3838
    39 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     39static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    4040{
    4141        *port = v;
    4242}
    4343
    44 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     44static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    4545{
    4646        *port = v;
    4747}
    4848
    49 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     49static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    5050{
    5151        *port = v;
    5252}
    5353
    54 static inline uint8_t pio_read_8(ioport8_t *port)
     54static inline uint8_t arch_pio_read_8(ioport8_t *port)
    5555{
    5656        return *port;
    5757}
    5858
    59 static inline uint16_t pio_read_16(ioport16_t *port)
     59static inline uint16_t arch_pio_read_16(ioport16_t *port)
    6060{
    6161        return *port;
    6262}
    6363
    64 static inline uint32_t pio_read_32(ioport32_t *port)
     64static inline uint32_t arch_pio_read_32(ioport32_t *port)
    6565{
    6666        return *port;
  • uspace/lib/c/arch/ia32/include/ddi.h

    r7eb49f4 re2a6b72  
    3939#define IO_SPACE_BOUNDARY  ((void *) (64 * 1024))
    4040
    41 static inline uint8_t pio_read_8(ioport8_t *port)
     41static inline uint8_t arch_pio_read_8(ioport8_t *port)
    4242{
    4343        if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
     
    5555}
    5656
    57 static inline uint16_t pio_read_16(ioport16_t *port)
     57static inline uint16_t arch_pio_read_16(ioport16_t *port)
    5858{
    5959        if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
     
    7171}
    7272
    73 static inline uint32_t pio_read_32(ioport32_t *port)
     73static inline uint32_t arch_pio_read_32(ioport32_t *port)
    7474{
    7575        if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
     
    8787}
    8888
    89 static inline void pio_write_8(ioport8_t *port, uint8_t val)
     89static inline void arch_pio_write_8(ioport8_t *port, uint8_t val)
    9090{
    9191        if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
     
    9898}
    9999
    100 static inline void pio_write_16(ioport16_t *port, uint16_t val)
     100static inline void arch_pio_write_16(ioport16_t *port, uint16_t val)
    101101{
    102102        if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
     
    109109}
    110110
    111 static inline void pio_write_32(ioport32_t *port, uint32_t val)
     111static inline void arch_pio_write_32(ioport32_t *port, uint32_t val)
    112112{
    113113        if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
  • uspace/lib/c/arch/ia64/include/ddi.h

    r7eb49f4 re2a6b72  
    5050            (ia64_iospace_address = get_ia64_iospace_address()))
    5151
    52 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     52static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    5353{
    5454        if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
     
    6565}
    6666
    67 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     67static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    6868{
    6969        if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
     
    8080}
    8181
    82 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     82static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    8383{
    8484        if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
     
    9595}
    9696
    97 static inline uint8_t pio_read_8(ioport8_t *port)
     97static inline uint8_t arch_pio_read_8(ioport8_t *port)
    9898{
    9999        uint8_t v;
     
    115115}
    116116
    117 static inline uint16_t pio_read_16(ioport16_t *port)
     117static inline uint16_t arch_pio_read_16(ioport16_t *port)
    118118{
    119119        uint16_t v;
     
    135135}
    136136
    137 static inline uint32_t pio_read_32(ioport32_t *port)
     137static inline uint32_t arch_pio_read_32(ioport32_t *port)
    138138{
    139139        uint32_t v;
  • uspace/lib/c/arch/ia64/src/ddi.c

    r7eb49f4 re2a6b72  
     1/*
     2 * Copyright (c) 2006 Martin Decky
     3 * All rights reserved.
     4 *
     5 * Redistribution and use in source and binary forms, with or without
     6 * modification, are permitted provided that the following conditions
     7 * are met:
     8 *
     9 * - Redistributions of source code must retain the above copyright
     10 *   notice, this list of conditions and the following disclaimer.
     11 * - Redistributions in binary form must reproduce the above copyright
     12 *   notice, this list of conditions and the following disclaimer in the
     13 *   documentation and/or other materials provided with the distribution.
     14 * - The name of the author may not be used to endorse or promote products
     15 *   derived from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
    128#include <libarch/ddi.h>
    229#include <sysinfo.h>
     
    1239        return addr;
    1340}
    14 
  • uspace/lib/c/arch/mips32/Makefile.common

    r7eb49f4 re2a6b72  
    2828
    2929GCC_CFLAGS += -msoft-float -mips3 -mabi=32
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031
    3132ENDIANESS = LE
  • uspace/lib/c/arch/mips32/include/ddi.h

    r7eb49f4 re2a6b72  
    3737#include <libarch/types.h>
    3838
    39 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     39static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    4040{
    4141        *port = v;
    4242}
    4343
    44 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     44static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    4545{
    4646        *port = v;
    4747}
    4848
    49 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     49static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    5050{
    5151        *port = v;
    5252}
    5353
    54 static inline uint8_t pio_read_8(ioport8_t *port)
     54static inline uint8_t arch_pio_read_8(ioport8_t *port)
    5555{
    5656        return *port;
    5757}
    5858
    59 static inline uint16_t pio_read_16(ioport16_t *port)
     59static inline uint16_t arch_pio_read_16(ioport16_t *port)
    6060{
    6161        return *port;
    6262}
    6363
    64 static inline uint32_t pio_read_32(ioport32_t *port)
     64static inline uint32_t arch_pio_read_32(ioport32_t *port)
    6565{
    6666        return *port;
  • uspace/lib/c/arch/mips32eb/Makefile.common

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

    r7eb49f4 re2a6b72  
    2828
    2929GCC_CFLAGS += -msoft-float -mips3 -mabi=64
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031AFLAGS = -64
    3132
  • uspace/lib/c/arch/mips64/include/ddi.h

    r7eb49f4 re2a6b72  
    3737#include <libarch/types.h>
    3838
    39 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     39static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    4040{
    4141        *port = v;
    4242}
    4343
    44 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     44static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    4545{
    4646        *port = v;
    4747}
    4848
    49 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     49static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    5050{
    5151        *port = v;
    5252}
    5353
    54 static inline uint8_t pio_read_8(ioport8_t *port)
     54static inline uint8_t arch_pio_read_8(ioport8_t *port)
    5555{
    5656        return *port;
    5757}
    5858
    59 static inline uint16_t pio_read_16(ioport16_t *port)
     59static inline uint16_t arch_pio_read_16(ioport16_t *port)
    6060{
    6161        return *port;
    6262}
    6363
    64 static inline uint32_t pio_read_32(ioport32_t *port)
     64static inline uint32_t arch_pio_read_32(ioport32_t *port)
    6565{
    6666        return *port;
  • uspace/lib/c/arch/ppc32/Makefile.common

    r7eb49f4 re2a6b72  
    2828
    2929GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32
     30BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
    3031AFLAGS = -a32
    3132
  • uspace/lib/c/arch/ppc32/include/ddi.h

    r7eb49f4 re2a6b72  
    3737#include <libarch/types.h>
    3838
    39 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     39static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    4040{
    4141        *port = v;
    4242}
    4343
    44 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     44static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    4545{
    4646        *port = v;
    4747}
    4848
    49 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     49static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    5050{
    5151        *port = v;
    5252}
    5353
    54 static inline uint8_t pio_read_8(ioport8_t *port)
     54static inline uint8_t arch_pio_read_8(ioport8_t *port)
    5555{
    5656        return *port;
    5757}
    5858
    59 static inline uint16_t pio_read_16(ioport16_t *port)
     59static inline uint16_t arch_pio_read_16(ioport16_t *port)
    6060{
    6161        return *port;
    6262}
    6363
    64 static inline uint32_t pio_read_32(ioport32_t *port)
     64static inline uint32_t arch_pio_read_32(ioport32_t *port)
    6565{
    6666        return *port;
  • uspace/lib/c/arch/sparc64/include/ddi.h

    r7eb49f4 re2a6b72  
    4545}
    4646
    47 static inline void pio_write_8(ioport8_t *port, uint8_t v)
     47static inline void arch_pio_write_8(ioport8_t *port, uint8_t v)
    4848{
    4949        *port = v;
     
    5151}
    5252
    53 static inline void pio_write_16(ioport16_t *port, uint16_t v)
     53static inline void arch_pio_write_16(ioport16_t *port, uint16_t v)
    5454{
    5555        *port = v;
     
    5757}
    5858
    59 static inline void pio_write_32(ioport32_t *port, uint32_t v)
     59static inline void arch_pio_write_32(ioport32_t *port, uint32_t v)
    6060{
    6161        *port = v;
     
    6363}
    6464
    65 static inline uint8_t pio_read_8(ioport8_t *port)
     65static inline uint8_t arch_pio_read_8(ioport8_t *port)
    6666{
    6767        uint8_t rv;
     
    7373}
    7474
    75 static inline uint16_t pio_read_16(ioport16_t *port)
     75static inline uint16_t arch_pio_read_16(ioport16_t *port)
    7676{
    7777        uint16_t rv;
     
    8383}
    8484
    85 static inline uint32_t pio_read_32(ioport32_t *port)
     85static inline uint32_t arch_pio_read_32(ioport32_t *port)
    8686{
    8787        uint32_t rv;
  • uspace/lib/c/generic/adt/hash_table.c

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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/ddi.c

    r7eb49f4 re2a6b72  
    3434
    3535#include <assert.h>
     36#include <atomic.h>
    3637#include <unistd.h>
     38#include <stdio.h>
    3739#include <errno.h>
    3840#include <sys/types.h>
     
    4749#include "private/libc.h"
    4850
     51
    4952/** Return unique device number.
    5053 *
     
    120123 *
    121124 */
    122 int iospace_enable(task_id_t id, void *ioaddr, unsigned long size)
    123 {
    124         ddi_ioarg_t arg;
    125        
    126         arg.task_id = id;
    127         arg.ioaddr = ioaddr;
    128         arg.size = size;
     125static int iospace_enable(task_id_t id, void *ioaddr, size_t size)
     126{
     127        const ddi_ioarg_t arg = {
     128                .task_id = id,
     129                .ioaddr = ioaddr,
     130                .size = size
     131        };
    129132       
    130133        return __SYSCALL1(SYS_IOSPACE_ENABLE, (sysarg_t) &arg);
     
    136139 * @param size     Size of the I/O region.
    137140 * @param virt     Virtual address for application's
    138  *                 PIO operations.
     141 *                 PIO operations. Can be NULL for PMIO.
    139142 *
    140143 * @return EOK on success.
     
    146149#ifdef IO_SPACE_BOUNDARY
    147150        if (pio_addr < IO_SPACE_BOUNDARY) {
    148                 *virt = pio_addr;
     151                if (virt)
     152                        *virt = pio_addr;
    149153                return iospace_enable(task_get_id(), pio_addr, size);
    150154        }
    151155#endif
    152        
     156        if (!virt)
     157                return EINVAL;
     158
    153159        void *phys_frame =
    154160            (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE);
     
    166172}
    167173
     174void pio_write_8(ioport8_t *reg, uint8_t val)
     175{
     176        pio_trace_log(reg, val, true);
     177        arch_pio_write_8(reg, val);
     178}
     179
     180void pio_write_16(ioport16_t *reg, uint16_t val)
     181{
     182        pio_trace_log(reg, val, true);
     183        arch_pio_write_16(reg, val);
     184}
     185
     186void pio_write_32(ioport32_t *reg, uint32_t val)
     187{
     188        pio_trace_log(reg, val, true);
     189        arch_pio_write_32(reg, val);
     190}
     191
     192uint8_t pio_read_8(ioport8_t *reg)
     193{
     194        const uint8_t val = arch_pio_read_8(reg);
     195        pio_trace_log(reg, val, false);
     196        return val;
     197}
     198
     199uint16_t pio_read_16(ioport16_t *reg)
     200{
     201        const uint16_t val = arch_pio_read_16(reg);
     202        pio_trace_log(reg, val, false);
     203        return val;
     204}
     205
     206uint32_t pio_read_32(ioport32_t *reg)
     207{
     208        const uint32_t val = arch_pio_read_32(reg);
     209        pio_trace_log(reg, val, false);
     210        return val;
     211}
     212
    168213/** Register IRQ notification.
    169214 *
  • uspace/lib/c/generic/fibril_synch.c

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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
     245        vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);
     246        logger_message(logger_session, ctx, level, message_buffer);
    120247}
    121248
  • uspace/lib/c/generic/malloc.c

    r7eb49f4 re2a6b72  
    289289        size_t asize = ALIGN_UP(size, PAGE_SIZE);
    290290        void *astart = as_area_create(AS_AREA_ANY, asize,
    291             AS_AREA_WRITE | AS_AREA_READ);
     291            AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE);
    292292        if (astart == AS_MAP_FAILED)
    293293                return false;
  • uspace/lib/c/generic/time.c

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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/ddi.h

    r7eb49f4 re2a6b72  
    3636#define LIBC_DDI_H_
    3737
     38#include <bool.h>
    3839#include <sys/types.h>
     40#include <sys/time.h>
    3941#include <abi/ddi/irq.h>
    4042#include <task.h>
     
    5052extern int dmamem_unmap_anonymous(void *);
    5153
    52 extern int iospace_enable(task_id_t, void *, unsigned long);
    5354extern int pio_enable(void *, size_t, void **);
     55
     56typedef void (*trace_fnc)(volatile void *place, uint32_t val,
     57    volatile void* base, size_t size, void *data, bool write);
     58
     59extern int pio_trace_enable(void *, size_t, trace_fnc, void *);
     60extern void pio_trace_log(volatile void *, uint32_t val, bool write);
     61extern void pio_trace_disable(void *);
     62
     63extern void pio_write_8(ioport8_t *, uint8_t);
     64extern void pio_write_16(ioport16_t *, uint16_t);
     65extern void pio_write_32(ioport32_t *, uint32_t);
     66
     67extern uint8_t pio_read_8(ioport8_t *);
     68extern uint16_t pio_read_16(ioport16_t *);
     69extern uint32_t pio_read_32(ioport32_t *);
     70
     71static inline uint8_t pio_change_8(
     72    ioport8_t *reg, uint8_t val, uint8_t mask, useconds_t delay)
     73{
     74        uint8_t v = pio_read_8(reg);
     75        udelay(delay);
     76        pio_write_8(reg, (v & ~mask) | val);
     77        return v;
     78}
     79
     80static inline uint16_t pio_change_16(
     81    ioport16_t *reg, uint16_t val, uint16_t mask, useconds_t delay)
     82{
     83        uint16_t v = pio_read_16(reg);
     84        udelay(delay);
     85        pio_write_16(reg, (v & ~mask) | val);
     86        return v;
     87}
     88
     89static inline uint32_t pio_change_32(
     90    ioport32_t *reg, uint32_t val, uint32_t mask, useconds_t delay)
     91{
     92        uint32_t v = pio_read_32(reg);
     93        udelay(delay);
     94        pio_write_32(reg, (v & ~mask) | val);
     95        return v;
     96}
     97
     98static inline uint8_t pio_set_8(ioport8_t *r, uint8_t v, useconds_t d)
     99{
     100        return pio_change_8(r, v, 0, d);
     101}
     102static inline uint16_t pio_set_16(ioport16_t *r, uint16_t v, useconds_t d)
     103{
     104        return pio_change_16(r, v, 0, d);
     105}
     106static inline uint32_t pio_set_32(ioport32_t *r, uint32_t v, useconds_t d)
     107{
     108        return pio_change_32(r, v, 0, d);
     109}
     110
     111static inline uint8_t pio_clear_8(ioport8_t *r, uint8_t v, useconds_t d)
     112{
     113        return pio_change_8(r, 0, v, d);
     114}
     115static inline uint16_t pio_clear_16(ioport16_t *r, uint16_t v, useconds_t d)
     116{
     117        return pio_change_16(r, 0, v, d);
     118}
     119static inline uint32_t pio_clear_32(ioport32_t *r, uint32_t v, useconds_t d)
     120{
     121        return pio_change_32(r, 0, v, d);
     122}
    54123
    55124extern int irq_register(int, int, int, irq_code_t *);
  • uspace/lib/c/include/io/log.h

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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

    r7eb49f4 re2a6b72  
    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
Note: See TracChangeset for help on using the changeset viewer.