Changeset e2a6b72 in mainline for uspace/lib/c
- Timestamp:
- 2012-10-15T16:28:58Z (13 years ago)
- 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. - Location:
- uspace/lib/c
- Files:
-
- 8 added
- 1 deleted
- 30 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
r7eb49f4 re2a6b72 71 71 generic/device/hw_res_parsed.c \ 72 72 generic/device/char_dev.c \ 73 generic/device/clock_dev.c \ 74 generic/device/battery_dev.c \ 73 75 generic/device/graph_dev.c \ 74 76 generic/device/nic.c \ … … 101 103 generic/io/printf.c \ 102 104 generic/io/log.c \ 105 generic/io/logctl.c \ 103 106 generic/io/klog.c \ 104 107 generic/io/snprintf.c \ … … 121 124 generic/adt/list.c \ 122 125 generic/adt/hash_table.c \ 123 generic/adt/hash_set.c \124 126 generic/adt/dynamic_fifo.c \ 125 127 generic/adt/char_map.c \ … … 138 140 generic/sort.c \ 139 141 generic/stats.c \ 140 generic/assert.c 142 generic/assert.c \ 143 generic/pio_trace.c 141 144 142 145 ifeq ($(CONFIG_RTLD),y) -
uspace/lib/c/arch/abs32le/include/ddi.h
r7eb49f4 re2a6b72 36 36 #include <libarch/types.h> 37 37 38 static inline void pio_write_8(ioport8_t *port, uint8_t v)38 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 39 39 { 40 40 *port = v; 41 41 } 42 42 43 static inline void pio_write_16(ioport16_t *port, uint16_t v)43 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 44 44 { 45 45 *port = v; 46 46 } 47 47 48 static inline void pio_write_32(ioport32_t *port, uint32_t v)48 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 49 49 { 50 50 *port = v; 51 51 } 52 52 53 static inline uint8_t pio_read_8(ioport8_t *port)53 static inline uint8_t arch_pio_read_8(ioport8_t *port) 54 54 { 55 55 return *port; 56 56 } 57 57 58 static inline uint16_t pio_read_16(ioport16_t *port)58 static inline uint16_t arch_pio_read_16(ioport16_t *port) 59 59 { 60 60 return *port; 61 61 } 62 62 63 static inline uint32_t pio_read_32(ioport32_t *port)63 static inline uint32_t arch_pio_read_32(ioport32_t *port) 64 64 { 65 65 return *port; -
uspace/lib/c/arch/arm32/Makefile.common
r7eb49f4 re2a6b72 28 28 # 29 29 30 BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a 30 31 GCC_CFLAGS += -ffixed-r9 -mtp=soft -fno-omit-frame-pointer -mapcs-frame -march=$(subst _,-,$(PROCESSOR)) 31 32 -
uspace/lib/c/arch/arm32/include/ddi.h
r7eb49f4 re2a6b72 37 37 #include <libarch/types.h> 38 38 39 static inline void pio_write_8(ioport8_t *port, uint8_t v)39 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 40 40 { 41 41 *port = v; 42 42 } 43 43 44 static inline void pio_write_16(ioport16_t *port, uint16_t v)44 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 45 45 { 46 46 *port = v; 47 47 } 48 48 49 static inline void pio_write_32(ioport32_t *port, uint32_t v)49 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 50 50 { 51 51 *port = v; 52 52 } 53 53 54 static inline uint8_t pio_read_8(ioport8_t *port)54 static inline uint8_t arch_pio_read_8(ioport8_t *port) 55 55 { 56 56 return *port; 57 57 } 58 58 59 static inline uint16_t pio_read_16(ioport16_t *port)59 static inline uint16_t arch_pio_read_16(ioport16_t *port) 60 60 { 61 61 return *port; 62 62 } 63 63 64 static inline uint32_t pio_read_32(ioport32_t *port)64 static inline uint32_t arch_pio_read_32(ioport32_t *port) 65 65 { 66 66 return *port; -
uspace/lib/c/arch/ia32/include/ddi.h
r7eb49f4 re2a6b72 39 39 #define IO_SPACE_BOUNDARY ((void *) (64 * 1024)) 40 40 41 static inline uint8_t pio_read_8(ioport8_t *port)41 static inline uint8_t arch_pio_read_8(ioport8_t *port) 42 42 { 43 43 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) { … … 55 55 } 56 56 57 static inline uint16_t pio_read_16(ioport16_t *port)57 static inline uint16_t arch_pio_read_16(ioport16_t *port) 58 58 { 59 59 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) { … … 71 71 } 72 72 73 static inline uint32_t pio_read_32(ioport32_t *port)73 static inline uint32_t arch_pio_read_32(ioport32_t *port) 74 74 { 75 75 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) { … … 87 87 } 88 88 89 static inline void pio_write_8(ioport8_t *port, uint8_t val)89 static inline void arch_pio_write_8(ioport8_t *port, uint8_t val) 90 90 { 91 91 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) { … … 98 98 } 99 99 100 static inline void pio_write_16(ioport16_t *port, uint16_t val)100 static inline void arch_pio_write_16(ioport16_t *port, uint16_t val) 101 101 { 102 102 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) { … … 109 109 } 110 110 111 static inline void pio_write_32(ioport32_t *port, uint32_t val)111 static inline void arch_pio_write_32(ioport32_t *port, uint32_t val) 112 112 { 113 113 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) { -
uspace/lib/c/arch/ia64/include/ddi.h
r7eb49f4 re2a6b72 50 50 (ia64_iospace_address = get_ia64_iospace_address())) 51 51 52 static inline void pio_write_8(ioport8_t *port, uint8_t v)52 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 53 53 { 54 54 if (port < (ioport8_t *) IO_SPACE_BOUNDARY) { … … 65 65 } 66 66 67 static inline void pio_write_16(ioport16_t *port, uint16_t v)67 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 68 68 { 69 69 if (port < (ioport16_t *) IO_SPACE_BOUNDARY) { … … 80 80 } 81 81 82 static inline void pio_write_32(ioport32_t *port, uint32_t v)82 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 83 83 { 84 84 if (port < (ioport32_t *) IO_SPACE_BOUNDARY) { … … 95 95 } 96 96 97 static inline uint8_t pio_read_8(ioport8_t *port)97 static inline uint8_t arch_pio_read_8(ioport8_t *port) 98 98 { 99 99 uint8_t v; … … 115 115 } 116 116 117 static inline uint16_t pio_read_16(ioport16_t *port)117 static inline uint16_t arch_pio_read_16(ioport16_t *port) 118 118 { 119 119 uint16_t v; … … 135 135 } 136 136 137 static inline uint32_t pio_read_32(ioport32_t *port)137 static inline uint32_t arch_pio_read_32(ioport32_t *port) 138 138 { 139 139 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 */ 1 28 #include <libarch/ddi.h> 2 29 #include <sysinfo.h> … … 12 39 return addr; 13 40 } 14 -
uspace/lib/c/arch/mips32/Makefile.common
r7eb49f4 re2a6b72 28 28 29 29 GCC_CFLAGS += -msoft-float -mips3 -mabi=32 30 BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a 30 31 31 32 ENDIANESS = LE -
uspace/lib/c/arch/mips32/include/ddi.h
r7eb49f4 re2a6b72 37 37 #include <libarch/types.h> 38 38 39 static inline void pio_write_8(ioport8_t *port, uint8_t v)39 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 40 40 { 41 41 *port = v; 42 42 } 43 43 44 static inline void pio_write_16(ioport16_t *port, uint16_t v)44 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 45 45 { 46 46 *port = v; 47 47 } 48 48 49 static inline void pio_write_32(ioport32_t *port, uint32_t v)49 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 50 50 { 51 51 *port = v; 52 52 } 53 53 54 static inline uint8_t pio_read_8(ioport8_t *port)54 static inline uint8_t arch_pio_read_8(ioport8_t *port) 55 55 { 56 56 return *port; 57 57 } 58 58 59 static inline uint16_t pio_read_16(ioport16_t *port)59 static inline uint16_t arch_pio_read_16(ioport16_t *port) 60 60 { 61 61 return *port; 62 62 } 63 63 64 static inline uint32_t pio_read_32(ioport32_t *port)64 static inline uint32_t arch_pio_read_32(ioport32_t *port) 65 65 { 66 66 return *port; -
uspace/lib/c/arch/mips32eb/Makefile.common
r7eb49f4 re2a6b72 28 28 29 29 GCC_CFLAGS += -msoft-float -mips3 -mabi=32 30 BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a 30 31 31 32 ENDIANESS = BE -
uspace/lib/c/arch/mips64/Makefile.common
r7eb49f4 re2a6b72 28 28 29 29 GCC_CFLAGS += -msoft-float -mips3 -mabi=64 30 BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a 30 31 AFLAGS = -64 31 32 -
uspace/lib/c/arch/mips64/include/ddi.h
r7eb49f4 re2a6b72 37 37 #include <libarch/types.h> 38 38 39 static inline void pio_write_8(ioport8_t *port, uint8_t v)39 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 40 40 { 41 41 *port = v; 42 42 } 43 43 44 static inline void pio_write_16(ioport16_t *port, uint16_t v)44 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 45 45 { 46 46 *port = v; 47 47 } 48 48 49 static inline void pio_write_32(ioport32_t *port, uint32_t v)49 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 50 50 { 51 51 *port = v; 52 52 } 53 53 54 static inline uint8_t pio_read_8(ioport8_t *port)54 static inline uint8_t arch_pio_read_8(ioport8_t *port) 55 55 { 56 56 return *port; 57 57 } 58 58 59 static inline uint16_t pio_read_16(ioport16_t *port)59 static inline uint16_t arch_pio_read_16(ioport16_t *port) 60 60 { 61 61 return *port; 62 62 } 63 63 64 static inline uint32_t pio_read_32(ioport32_t *port)64 static inline uint32_t arch_pio_read_32(ioport32_t *port) 65 65 { 66 66 return *port; -
uspace/lib/c/arch/ppc32/Makefile.common
r7eb49f4 re2a6b72 28 28 29 29 GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32 30 BASE_LIBS += $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a 30 31 AFLAGS = -a32 31 32 -
uspace/lib/c/arch/ppc32/include/ddi.h
r7eb49f4 re2a6b72 37 37 #include <libarch/types.h> 38 38 39 static inline void pio_write_8(ioport8_t *port, uint8_t v)39 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 40 40 { 41 41 *port = v; 42 42 } 43 43 44 static inline void pio_write_16(ioport16_t *port, uint16_t v)44 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 45 45 { 46 46 *port = v; 47 47 } 48 48 49 static inline void pio_write_32(ioport32_t *port, uint32_t v)49 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 50 50 { 51 51 *port = v; 52 52 } 53 53 54 static inline uint8_t pio_read_8(ioport8_t *port)54 static inline uint8_t arch_pio_read_8(ioport8_t *port) 55 55 { 56 56 return *port; 57 57 } 58 58 59 static inline uint16_t pio_read_16(ioport16_t *port)59 static inline uint16_t arch_pio_read_16(ioport16_t *port) 60 60 { 61 61 return *port; 62 62 } 63 63 64 static inline uint32_t pio_read_32(ioport32_t *port)64 static inline uint32_t arch_pio_read_32(ioport32_t *port) 65 65 { 66 66 return *port; -
uspace/lib/c/arch/sparc64/include/ddi.h
r7eb49f4 re2a6b72 45 45 } 46 46 47 static inline void pio_write_8(ioport8_t *port, uint8_t v)47 static inline void arch_pio_write_8(ioport8_t *port, uint8_t v) 48 48 { 49 49 *port = v; … … 51 51 } 52 52 53 static inline void pio_write_16(ioport16_t *port, uint16_t v)53 static inline void arch_pio_write_16(ioport16_t *port, uint16_t v) 54 54 { 55 55 *port = v; … … 57 57 } 58 58 59 static inline void pio_write_32(ioport32_t *port, uint32_t v)59 static inline void arch_pio_write_32(ioport32_t *port, uint32_t v) 60 60 { 61 61 *port = v; … … 63 63 } 64 64 65 static inline uint8_t pio_read_8(ioport8_t *port)65 static inline uint8_t arch_pio_read_8(ioport8_t *port) 66 66 { 67 67 uint8_t rv; … … 73 73 } 74 74 75 static inline uint16_t pio_read_16(ioport16_t *port)75 static inline uint16_t arch_pio_read_16(ioport16_t *port) 76 76 { 77 77 uint16_t rv; … … 83 83 } 84 84 85 static inline uint32_t pio_read_32(ioport32_t *port)85 static inline uint32_t arch_pio_read_32(ioport32_t *port) 86 86 { 87 87 uint32_t rv; -
uspace/lib/c/generic/adt/hash_table.c
r7eb49f4 re2a6b72 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2012 Adam Hraska 4 * 3 5 * All rights reserved. 4 6 * … … 34 36 35 37 /* 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. 37 49 */ 38 50 … … 44 56 #include <str.h> 45 57 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 64 static size_t round_up_size(size_t); 65 static bool alloc_table(size_t, list_t **); 66 static void clear_items(hash_table_t *); 67 static void resize(hash_table_t *, size_t); 68 static void grow_if_needed(hash_table_t *); 69 static void shrink_if_needed(hash_table_t *); 70 71 /* Dummy do nothing callback to invoke in place of remove_callback == NULL. */ 72 static void nop_remove_callback(ht_link_t *item) 73 { 74 /* no-op */ 75 } 76 77 46 78 /** Create chained hash table. 47 79 * 48 80 * @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. 50 83 * @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. 52 89 * 53 90 * @return True on success 54 91 * 55 92 */ 56 bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,57 hash_table_op erations_t *op)93 bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_load, 94 hash_table_ops_t *op) 58 95 { 59 96 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) 65 101 return false; 66 102 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; 75 110 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 } 76 117 77 118 return true; 78 119 } 79 120 121 /** Destroy a hash table instance. 122 * 123 * @param h Hash table to be destroyed. 124 * 125 */ 126 void 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. */ 140 bool 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. */ 147 size_t hash_table_size(hash_table_t *h) 148 { 149 assert(h && h->bucket); 150 return h->item_cnt; 151 } 152 80 153 /** Remove all elements from the hash table 81 154 * … … 84 157 void hash_table_clear(hash_table_t *h) 85 158 { 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. */ 171 static 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 94 181 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; 111 187 } 112 188 … … 117 193 * @param item Item to be inserted into the hash table. 118 194 */ 119 void hash_table_insert(hash_table_t *h, unsigned long key[],link_t *item)195 void hash_table_insert(hash_table_t *h, ht_link_t *item) 120 196 { 121 197 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 */ 218 bool 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; 128 243 } 129 244 … … 136 251 * 137 252 */ 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 253 ht_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. */ 275 ht_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 154 294 return NULL; 155 295 } … … 163 303 * the hash table. 164 304 * @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 */ 308 size_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.*/ 334 void 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 */ 355 void 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. */ 384 static 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.*/ 396 static 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. */ 413 static 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. 177 419 */ 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. */ 426 static 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. */ 437 static 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) 185 444 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]); 207 461 } 208 462 } 209 463 } 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 237 471 238 472 /** @} -
uspace/lib/c/generic/async.c
r7eb49f4 re2a6b72 116 116 #include "private/libc.h" 117 117 118 #define CLIENT_HASH_TABLE_BUCKETS 32119 #define CONN_HASH_TABLE_BUCKETS 32120 118 121 119 /** Session data */ … … 205 203 /* Client connection data */ 206 204 typedef struct { 207 link_t link;205 ht_link_t link; 208 206 209 207 task_id_t in_task_id; … … 217 215 218 216 /** Hash table link. */ 219 link_t link;217 ht_link_t link; 220 218 221 219 /** Incoming client task ID. */ … … 393 391 static LIST_INITIALIZE(timeout_list); 394 392 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 } 393 static size_t client_key_hash(void *k) 394 { 395 task_id_t key = *(task_id_t*)k; 396 return key; 397 } 398 399 static 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 405 static 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 416 412 417 413 /** Operations for the client hash table. */ 418 static hash_table_op erations_t client_hash_table_ops = {414 static hash_table_ops_t client_hash_table_ops = { 419 415 .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 422 420 }; 423 421 … … 429 427 * 430 428 */ 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 } 429 static size_t conn_key_hash(void *key) 430 { 431 sysarg_t in_phone_hash = *(sysarg_t*)key; 432 return in_phone_hash ; 433 } 434 435 static 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 441 static 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 459 448 460 449 /** Operations for the connection hash table. */ 461 static hash_table_op erations_t conn_hash_table_ops = {450 static hash_table_ops_t conn_hash_table_ops = { 462 451 .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 465 456 }; 466 457 … … 510 501 futex_down(&async_futex); 511 502 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); 514 504 515 505 if (!hlp) { … … 518 508 } 519 509 520 connection_t *conn = hash_table_get_inst ance(hlp, connection_t, link);510 connection_t *conn = hash_table_get_inst(hlp, connection_t, link); 521 511 522 512 msg_t *msg = malloc(sizeof(*msg)); … … 638 628 639 629 if (usecs) { 640 get timeofday(&conn->wdata.to_event.expires, NULL);630 getuptime(&conn->wdata.to_event.expires); 641 631 tv_add(&conn->wdata.to_event.expires, usecs); 642 632 } else … … 698 688 static client_t *async_client_get(task_id_t client_id, bool create) 699 689 { 700 unsigned long key[2] = {701 LOWER32(client_id),702 UPPER32(client_id),703 };704 690 client_t *client = NULL; 705 691 706 692 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); 708 694 if (lnk) { 709 client = hash_table_get_inst ance(lnk, client_t, link);695 client = hash_table_get_inst(lnk, client_t, link); 710 696 atomic_inc(&client->refcnt); 711 697 } else if (create) { … … 716 702 717 703 atomic_set(&client->refcnt, 1); 718 hash_table_insert(&client_hash_table, key,&client->link);704 hash_table_insert(&client_hash_table, &client->link); 719 705 } 720 706 } … … 727 713 { 728 714 bool destroy; 729 unsigned long key[2] = { 730 LOWER32(client->in_task_id), 731 UPPER32(client->in_task_id) 732 }; 733 715 734 716 futex_down(&async_futex); 735 717 736 718 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); 738 720 destroy = true; 739 721 } else … … 831 813 */ 832 814 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); 835 816 futex_up(&async_futex); 836 817 … … 916 897 917 898 /* Add connection to the connection hash table */ 918 unsigned long key = conn->in_phone_hash;919 899 920 900 futex_down(&async_futex); 921 hash_table_insert(&conn_hash_table, & key, &conn->link);901 hash_table_insert(&conn_hash_table, &conn->link); 922 902 futex_up(&async_futex); 923 903 … … 967 947 { 968 948 struct timeval tv; 969 get timeofday(&tv, NULL);949 getuptime(&tv); 970 950 971 951 futex_down(&async_futex); … … 1024 1004 1025 1005 struct timeval tv; 1026 get timeofday(&tv, NULL);1006 getuptime(&tv); 1027 1007 1028 1008 if (tv_gteq(&tv, &waiter->to_event.expires)) { … … 1111 1091 void __async_init(void) 1112 1092 { 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)) 1115 1094 abort(); 1116 1095 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)) 1119 1097 abort(); 1120 1098 … … 1331 1309 timeout = 0; 1332 1310 1333 get timeofday(&msg->wdata.to_event.expires, NULL);1311 getuptime(&msg->wdata.to_event.expires); 1334 1312 tv_add(&msg->wdata.to_event.expires, timeout); 1335 1313 … … 1413 1391 msg->wdata.fid = fibril_get_id(); 1414 1392 1415 get timeofday(&msg->wdata.to_event.expires, NULL);1393 getuptime(&msg->wdata.to_event.expires); 1416 1394 tv_add(&msg->wdata.to_event.expires, timeout); 1417 1395 -
uspace/lib/c/generic/ddi.c
r7eb49f4 re2a6b72 34 34 35 35 #include <assert.h> 36 #include <atomic.h> 36 37 #include <unistd.h> 38 #include <stdio.h> 37 39 #include <errno.h> 38 40 #include <sys/types.h> … … 47 49 #include "private/libc.h" 48 50 51 49 52 /** Return unique device number. 50 53 * … … 120 123 * 121 124 */ 122 int iospace_enable(task_id_t id, void *ioaddr, unsigned longsize)123 { 124 ddi_ioarg_t arg;125 126 arg.task_id = id;127 arg.ioaddr = ioaddr;128 arg.size = size;125 static 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 }; 129 132 130 133 return __SYSCALL1(SYS_IOSPACE_ENABLE, (sysarg_t) &arg); … … 136 139 * @param size Size of the I/O region. 137 140 * @param virt Virtual address for application's 138 * PIO operations. 141 * PIO operations. Can be NULL for PMIO. 139 142 * 140 143 * @return EOK on success. … … 146 149 #ifdef IO_SPACE_BOUNDARY 147 150 if (pio_addr < IO_SPACE_BOUNDARY) { 148 *virt = pio_addr; 151 if (virt) 152 *virt = pio_addr; 149 153 return iospace_enable(task_get_id(), pio_addr, size); 150 154 } 151 155 #endif 152 156 if (!virt) 157 return EINVAL; 158 153 159 void *phys_frame = 154 160 (void *) ALIGN_DOWN((uintptr_t) pio_addr, PAGE_SIZE); … … 166 172 } 167 173 174 void 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 180 void 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 186 void 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 192 uint8_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 199 uint16_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 206 uint32_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 168 213 /** Register IRQ notification. 169 214 * -
uspace/lib/c/generic/fibril_synch.c
r7eb49f4 re2a6b72 379 379 futex_down(&async_futex); 380 380 if (timeout) { 381 get timeofday(&wdata.to_event.expires, NULL);381 getuptime(&wdata.to_event.expires); 382 382 tv_add(&wdata.to_event.expires, timeout); 383 383 async_insert_timeout(&wdata); -
uspace/lib/c/generic/io/log.c
r7eb49f4 re2a6b72 38 38 #include <stdlib.h> 39 39 #include <stdio.h> 40 40 #include <async.h> 41 41 #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. */ 46 static sysarg_t default_log_id; 47 48 /** Log messages are printed under this name. */ 51 49 static const char *log_prog_name; 52 50 53 /** Prefixes for individual logging levels. */51 /** Names of individual log levels. */ 54 52 static 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 61 60 }; 62 61 62 /** IPC session with the logger service. */ 63 static 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 */ 76 static 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, ®_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 */ 115 const 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 */ 129 int 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 63 158 /** Initialize the logging system. 64 159 * 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 */ 162 int log_init(const char *prog_name) 163 { 74 164 log_prog_name = str_dup(prog_name); 75 165 if (log_prog_name == NULL) 76 166 return ENOMEM; 77 167 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 78 175 return EOK; 79 176 } 80 177 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 */ 187 log_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, ®_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 81 211 /** Write an entry to the log. 82 212 * 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 */ 220 void log_msg(log_t ctx, log_level_t level, const char *fmt, ...) 89 221 { 90 222 va_list args; 91 223 92 224 va_start(args, fmt); 93 log_msgv( level, fmt, args);225 log_msgv(ctx, level, fmt, args); 94 226 va_end(args); 95 227 } … … 97 229 /** Write an entry to the log (va_list variant). 98 230 * 99 * @param level Message verbosity level. Message is only printed100 * if verbosity is less than or equal to current101 * 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 */ 236 void log_msgv(log_t ctx, log_level_t level, const char *fmt, va_list args) 105 237 { 106 238 assert(level < LVL_LIMIT); 107 239 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); 120 247 } 121 248 -
uspace/lib/c/generic/malloc.c
r7eb49f4 re2a6b72 289 289 size_t asize = ALIGN_UP(size, PAGE_SIZE); 290 290 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); 292 292 if (astart == AS_MAP_FAILED) 293 293 return false; -
uspace/lib/c/generic/time.c
r7eb49f4 re2a6b72 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2011 Jiri Zarevucky 3 5 * All rights reserved. 4 6 * … … 43 45 #include <ddi.h> 44 46 #include <libc.h> 47 #include <stdint.h> 48 #include <stdio.h> 49 #include <ctype.h> 50 #include <assert.h> 45 51 #include <unistd.h> 52 #include <loc.h> 53 #include <device/clock_dev.h> 54 #include <malloc.h> 55 56 #define ASCTIME_BUF_LEN 26 46 57 47 58 /** Pointer to kernel shared variables with time */ … … 52 63 } *ktime = NULL; 53 64 65 /* Helper functions ***********************************************************/ 66 67 #define HOURS_PER_DAY (24) 68 #define MINS_PER_HOUR (60) 69 #define SECS_PER_MIN (60) 70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) 72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 73 74 /** 75 * Checks whether the year is a leap year. 76 * 77 * @param year Year since 1900 (e.g. for 1970, the value is 70). 78 * @return true if year is a leap year, false otherwise 79 */ 80 static bool _is_leap_year(time_t year) 81 { 82 year += 1900; 83 84 if (year % 400 == 0) 85 return true; 86 if (year % 100 == 0) 87 return false; 88 if (year % 4 == 0) 89 return true; 90 return false; 91 } 92 93 /** 94 * Returns how many days there are in the given month of the given year. 95 * Note that year is only taken into account if month is February. 96 * 97 * @param year Year since 1900 (can be negative). 98 * @param mon Month of the year. 0 for January, 11 for December. 99 * @return Number of days in the specified month. 100 */ 101 static int _days_in_month(time_t year, time_t mon) 102 { 103 assert(mon >= 0 && mon <= 11); 104 105 static int month_days[] = 106 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 107 108 if (mon == 1) { 109 year += 1900; 110 /* february */ 111 return _is_leap_year(year) ? 29 : 28; 112 } else { 113 return month_days[mon]; 114 } 115 } 116 117 /** 118 * For specified year, month and day of month, returns which day of that year 119 * it is. 120 * 121 * For example, given date 2011-01-03, the corresponding expression is: 122 * _day_of_year(111, 0, 3) == 2 123 * 124 * @param year Year (year 1900 = 0, can be negative). 125 * @param mon Month (January = 0). 126 * @param mday Day of month (First day is 1). 127 * @return Day of year (First day is 0). 128 */ 129 static int _day_of_year(time_t year, time_t mon, time_t mday) 130 { 131 static int mdays[] = 132 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 133 static int leap_mdays[] = 134 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; 135 136 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 137 } 138 139 /** 140 * Integer division that rounds to negative infinity. 141 * Used by some functions in this file. 142 * 143 * @param op1 Dividend. 144 * @param op2 Divisor. 145 * @return Rounded quotient. 146 */ 147 static time_t _floor_div(time_t op1, time_t op2) 148 { 149 if (op1 >= 0 || op1 % op2 == 0) { 150 return op1 / op2; 151 } else { 152 return op1 / op2 - 1; 153 } 154 } 155 156 /** 157 * Modulo that rounds to negative infinity. 158 * Used by some functions in this file. 159 * 160 * @param op1 Dividend. 161 * @param op2 Divisor. 162 * @return Remainder. 163 */ 164 static time_t _floor_mod(time_t op1, time_t op2) 165 { 166 int div = _floor_div(op1, op2); 167 168 /* (a / b) * b + a % b == a */ 169 /* thus, a % b == a - (a / b) * b */ 170 171 int result = op1 - div * op2; 172 173 /* Some paranoid checking to ensure I didn't make a mistake here. */ 174 assert(result >= 0); 175 assert(result < op2); 176 assert(div * op2 + result == op1); 177 178 return result; 179 } 180 181 /** 182 * Number of days since the Epoch. 183 * Epoch is 1970-01-01, which is also equal to day 0. 184 * 185 * @param year Year (year 1900 = 0, may be negative). 186 * @param mon Month (January = 0). 187 * @param mday Day of month (first day = 1). 188 * @return Number of days since the Epoch. 189 */ 190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday) 191 { 192 return (year - 70) * 365 + _floor_div(year - 69, 4) - 193 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) + 194 _day_of_year(year, mon, mday); 195 } 196 197 /** 198 * Seconds since the Epoch. see also _days_since_epoch(). 199 * 200 * @param tm Normalized broken-down time. 201 * @return Number of seconds since the epoch, not counting leap seconds. 202 */ 203 static time_t _secs_since_epoch(const struct tm *tm) 204 { 205 return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) * 206 SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR + 207 tm->tm_min * SECS_PER_MIN + tm->tm_sec; 208 } 209 210 /** 211 * Which day of week the specified date is. 212 * 213 * @param year Year (year 1900 = 0). 214 * @param mon Month (January = 0). 215 * @param mday Day of month (first = 1). 216 * @return Day of week (Sunday = 0). 217 */ 218 static int _day_of_week(time_t year, time_t mon, time_t mday) 219 { 220 /* 1970-01-01 is Thursday */ 221 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7); 222 } 223 224 /** 225 * Normalizes the broken-down time and optionally adds specified amount of 226 * seconds. 227 * 228 * @param tm Broken-down time to normalize. 229 * @param sec_add Seconds to add. 230 * @return 0 on success, -1 on overflow 231 */ 232 static int _normalize_time(struct tm *tm, time_t sec_add) 233 { 234 // TODO: DST correction 235 236 /* Set initial values. */ 237 time_t sec = tm->tm_sec + sec_add; 238 time_t min = tm->tm_min; 239 time_t hour = tm->tm_hour; 240 time_t day = tm->tm_mday - 1; 241 time_t mon = tm->tm_mon; 242 time_t year = tm->tm_year; 243 244 /* Adjust time. */ 245 min += _floor_div(sec, SECS_PER_MIN); 246 sec = _floor_mod(sec, SECS_PER_MIN); 247 hour += _floor_div(min, MINS_PER_HOUR); 248 min = _floor_mod(min, MINS_PER_HOUR); 249 day += _floor_div(hour, HOURS_PER_DAY); 250 hour = _floor_mod(hour, HOURS_PER_DAY); 251 252 /* Adjust month. */ 253 year += _floor_div(mon, 12); 254 mon = _floor_mod(mon, 12); 255 256 /* Now the difficult part - days of month. */ 257 258 /* First, deal with whole cycles of 400 years = 146097 days. */ 259 year += _floor_div(day, 146097) * 400; 260 day = _floor_mod(day, 146097); 261 262 /* Then, go in one year steps. */ 263 if (mon <= 1) { 264 /* January and February. */ 265 while (day > 365) { 266 day -= _is_leap_year(year) ? 366 : 365; 267 year++; 268 } 269 } else { 270 /* Rest of the year. */ 271 while (day > 365) { 272 day -= _is_leap_year(year + 1) ? 366 : 365; 273 year++; 274 } 275 } 276 277 /* Finally, finish it off month per month. */ 278 while (day >= _days_in_month(year, mon)) { 279 day -= _days_in_month(year, mon); 280 mon++; 281 if (mon >= 12) { 282 mon -= 12; 283 year++; 284 } 285 } 286 287 /* Calculate the remaining two fields. */ 288 tm->tm_yday = _day_of_year(year, mon, day + 1); 289 tm->tm_wday = _day_of_week(year, mon, day + 1); 290 291 /* And put the values back to the struct. */ 292 tm->tm_sec = (int) sec; 293 tm->tm_min = (int) min; 294 tm->tm_hour = (int) hour; 295 tm->tm_mday = (int) day + 1; 296 tm->tm_mon = (int) mon; 297 298 /* Casts to work around libc brain-damage. */ 299 if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) { 300 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX); 301 return -1; 302 } 303 304 tm->tm_year = (int) year; 305 return 0; 306 } 307 308 /** 309 * Which day the week-based year starts on, relative to the first calendar day. 310 * E.g. if the year starts on December 31st, the return value is -1. 311 * 312 * @param Year since 1900. 313 * @return Offset of week-based year relative to calendar year. 314 */ 315 static int _wbyear_offset(int year) 316 { 317 int start_wday = _day_of_week(year, 0, 1); 318 return _floor_mod(4 - start_wday, 7) - 3; 319 } 320 321 /** 322 * Returns week-based year of the specified time. 323 * 324 * @param tm Normalized broken-down time. 325 * @return Week-based year. 326 */ 327 static int _wbyear(const struct tm *tm) 328 { 329 int day = tm->tm_yday - _wbyear_offset(tm->tm_year); 330 if (day < 0) { 331 /* Last week of previous year. */ 332 return tm->tm_year - 1; 333 } 334 if (day > 364 + _is_leap_year(tm->tm_year)) { 335 /* First week of next year. */ 336 return tm->tm_year + 1; 337 } 338 /* All the other days are in the calendar year. */ 339 return tm->tm_year; 340 } 341 342 /** 343 * Week number of the year, assuming weeks start on sunday. 344 * The first Sunday of January is the first day of week 1; 345 * days in the new year before this are in week 0. 346 * 347 * @param tm Normalized broken-down time. 348 * @return The week number (0 - 53). 349 */ 350 static int _sun_week_number(const struct tm *tm) 351 { 352 int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7; 353 return (tm->tm_yday - first_day + 7) / 7; 354 } 355 356 /** 357 * Week number of the year, assuming weeks start on monday. 358 * If the week containing January 1st has four or more days in the new year, 359 * then it is considered week 1. Otherwise, it is the last week of the previous 360 * year, and the next week is week 1. Both January 4th and the first Thursday 361 * of January are always in week 1. 362 * 363 * @param tm Normalized broken-down time. 364 * @return The week number (1 - 53). 365 */ 366 static int _iso_week_number(const struct tm *tm) 367 { 368 int day = tm->tm_yday - _wbyear_offset(tm->tm_year); 369 if (day < 0) { 370 /* Last week of previous year. */ 371 return 53; 372 } 373 if (day > 364 + _is_leap_year(tm->tm_year)) { 374 /* First week of next year. */ 375 return 1; 376 } 377 /* All the other days give correct answer. */ 378 return (day / 7 + 1); 379 } 380 381 /** 382 * Week number of the year, assuming weeks start on monday. 383 * The first Monday of January is the first day of week 1; 384 * days in the new year before this are in week 0. 385 * 386 * @param tm Normalized broken-down time. 387 * @return The week number (0 - 53). 388 */ 389 static int _mon_week_number(const struct 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 54 398 /** Add microseconds to given timeval. 55 399 * … … 139 483 */ 140 484 int 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 539 ret_uptime: 540 541 free(svc_name); 542 free(svc_ids); 543 544 return getuptime(tv); 545 } 546 547 int getuptime(struct timeval *tv) 141 548 { 142 549 if (ktime == NULL) { … … 160 567 } 161 568 162 if (tz) {163 tz->tz_minuteswest = 0;164 tz->tz_dsttime = DST_NONE;165 }166 167 569 sysarg_t s2 = ktime->seconds2; 168 570 … … 178 580 } else 179 581 tv->tv_sec = s1; 180 582 181 583 return 0; 182 584 } … … 229 631 } 230 632 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 */ 641 time_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 */ 660 size_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 */ 851 int 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 */ 878 int 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 */ 899 void 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 */ 929 int 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 */ 959 int 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 */ 979 double difftime(time_t time1, time_t time0) 980 { 981 return (double) (time1 - time0); 982 } 983 231 984 /** @} 232 985 */ -
uspace/lib/c/include/adt/hash_table.h
r7eb49f4 re2a6b72 1 1 /* 2 2 * Copyright (c) 2006 Jakub Jermar 3 * Copyright (c) 2012 Adam Hraska 4 * 3 5 * All rights reserved. 4 6 * … … 39 41 #include <unistd.h> 40 42 #include <bool.h> 43 #include <macros.h> 41 44 42 typedef unsigned long hash_count_t; 43 typedef unsigned long hash_index_t; 45 /** Opaque hash table link type. */ 46 typedef struct ht_link { 47 link_t link; 48 } ht_link_t; 44 49 45 50 /** Set of operations for hash table. */ 46 51 typedef 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); 56 54 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); 66 57 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 67 64 /** Hash table item removal callback. 65 * 66 * Must not invoke any mutating functions of the hash table. 68 67 * 69 68 * @param item Item that was removed from the hash table. 70 *71 69 */ 72 void (*remove_callback)( link_t *item);73 } hash_table_op erations_t;70 void (*remove_callback)(ht_link_t *item); 71 } hash_table_ops_t; 74 72 75 73 /** Hash table structure. */ 76 74 typedef 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; 81 82 } hash_table_t; 82 83 83 #define hash_table_get_inst ance(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) 85 86 86 extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t, 87 hash_table_operations_t *); 87 extern bool hash_table_create(hash_table_t *, size_t, size_t, 88 hash_table_ops_t *); 89 extern void hash_table_destroy(hash_table_t *); 90 91 extern bool hash_table_empty(hash_table_t *); 92 extern size_t hash_table_size(hash_table_t *); 93 88 94 extern 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 *); 95 extern void hash_table_insert(hash_table_t *, ht_link_t *); 96 extern bool hash_table_insert_unique(hash_table_t *, ht_link_t *); 97 extern ht_link_t *hash_table_find(const hash_table_t *, void *); 98 extern ht_link_t *hash_table_find_next(const hash_table_t *, ht_link_t *); 99 extern size_t hash_table_remove(hash_table_t *, void *); 100 extern void hash_table_remove_item(hash_table_t *, ht_link_t *); 101 extern void hash_table_apply(hash_table_t *, bool (*)(ht_link_t *, void *), 102 void *); 103 95 104 96 105 #endif -
uspace/lib/c/include/adt/list.h
r7eb49f4 re2a6b72 71 71 iterator != &(list).head; iterator = iterator->next) 72 72 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 73 104 #define assert_link_not_used(link) \ 74 105 assert(((link)->prev == NULL) && ((link)->next == NULL)) 106 107 /** Returns true if the link is definitely part of a list. False if not sure. */ 108 static inline int link_in_use(link_t *link) 109 { 110 return link->prev != NULL && link->next != NULL; 111 } 75 112 76 113 /** Initialize doubly-linked circular list link -
uspace/lib/c/include/ddi.h
r7eb49f4 re2a6b72 36 36 #define LIBC_DDI_H_ 37 37 38 #include <bool.h> 38 39 #include <sys/types.h> 40 #include <sys/time.h> 39 41 #include <abi/ddi/irq.h> 40 42 #include <task.h> … … 50 52 extern int dmamem_unmap_anonymous(void *); 51 53 52 extern int iospace_enable(task_id_t, void *, unsigned long);53 54 extern int pio_enable(void *, size_t, void **); 55 56 typedef void (*trace_fnc)(volatile void *place, uint32_t val, 57 volatile void* base, size_t size, void *data, bool write); 58 59 extern int pio_trace_enable(void *, size_t, trace_fnc, void *); 60 extern void pio_trace_log(volatile void *, uint32_t val, bool write); 61 extern void pio_trace_disable(void *); 62 63 extern void pio_write_8(ioport8_t *, uint8_t); 64 extern void pio_write_16(ioport16_t *, uint16_t); 65 extern void pio_write_32(ioport32_t *, uint32_t); 66 67 extern uint8_t pio_read_8(ioport8_t *); 68 extern uint16_t pio_read_16(ioport16_t *); 69 extern uint32_t pio_read_32(ioport32_t *); 70 71 static 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 80 static 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 89 static 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 98 static 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 } 102 static 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 } 106 static 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 111 static 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 } 115 static 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 } 119 static 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 } 54 123 55 124 extern int irq_register(int, int, int, irq_code_t *); -
uspace/lib/c/include/io/log.h
r7eb49f4 re2a6b72 36 36 37 37 #include <stdarg.h> 38 #include <inttypes.h> 38 39 #include <io/verify.h> 39 40 41 /** Log message level. */ 40 42 typedef enum { 43 /** Fatal error, program is not able to recover at all. */ 41 44 LVL_FATAL, 45 /** Serious error but the program can recover from it. */ 42 46 LVL_ERROR, 47 /** Easily recoverable problem. */ 43 48 LVL_WARN, 49 /** Information message that ought to be printed by default. */ 44 50 LVL_NOTE, 51 /** Debugging purpose message. */ 45 52 LVL_DEBUG, 53 /** More detailed debugging message. */ 46 54 LVL_DEBUG2, 47 55 … … 50 58 } log_level_t; 51 59 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). */ 61 typedef 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 71 extern const char *log_level_str(log_level_t); 72 extern int log_level_from_str(const char *, log_level_t *); 73 74 extern int log_init(const char *); 75 extern log_t log_create(const char *, log_t); 76 77 extern void log_msg(log_t, log_level_t, const char *, ...) 78 PRINTF_ATTRIBUTE(3, 4); 79 extern void log_msgv(log_t, log_level_t, const char *, va_list); 56 80 57 81 #endif -
uspace/lib/c/include/ipc/dev_iface.h
r7eb49f4 re2a6b72 54 54 /** Interface provided by USB HID devices. */ 55 55 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, 56 60 /** Interface provided by AHCI devices. */ 57 61 AHCI_DEV_IFACE, -
uspace/lib/c/include/ipc/logger.h
r7eb49f4 re2a6b72 1 1 /* 2 * Copyright (c) 2006 Jakub Jermar 3 * Copyright (c) 2011 Radim Vansa 2 * Copyright (c) 2012 Vojtech Horky 4 3 * All rights reserved. 5 4 * … … 31 30 * @{ 32 31 */ 33 /** @file34 */35 32 36 #ifndef LIBC_ HASH_SET_H_37 #define LIBC_ HASH_SET_H_33 #ifndef LIBC_IPC_LOGGER_H_ 34 #define LIBC_IPC_LOGGER_H_ 38 35 39 #include <adt/list.h> 40 #include <unistd.h> 36 #include <ipc/common.h> 41 37 42 #define HASH_SET_MIN_SIZE 8 38 typedef 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; 43 53 44 typedef unsigned long (*hash_set_hash)(const link_t *); 45 typedef int (*hash_set_equals)(const link_t *, const link_t *); 54 typedef 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; 46 70 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 *); 71 typedef 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; 80 77 81 78 #endif -
uspace/lib/c/include/ipc/services.h
r7eb49f4 re2a6b72 45 45 SERVICE_VFS = FOURCC('v', 'f', 's', ' '), 46 46 SERVICE_LOC = FOURCC('l', 'o', 'c', ' '), 47 SERVICE_LOGGER = FOURCC('l', 'o', 'g', 'g'), 47 48 SERVICE_DEVMAN = FOURCC('d', 'e', 'v', 'n'), 48 49 SERVICE_IRC = FOURCC('i', 'r', 'c', ' '), -
uspace/lib/c/include/macros.h
r7eb49f4 re2a6b72 52 52 | ((((uint64_t) (up)) & 0xffffffff) << 32)) 53 53 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 54 60 #endif 55 61 -
uspace/lib/c/include/sys/time.h
r7eb49f4 re2a6b72 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2011 Jiri Zarevucky 3 5 * All rights reserved. 4 6 * … … 39 41 40 42 #define DST_NONE 0 43 #define ASCTIME_BUF_LEN 26 41 44 42 45 typedef long time_t; … … 45 48 typedef uint32_t useconds_t; 46 49 typedef uint32_t mseconds_t; 50 51 struct 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 }; 47 62 48 63 struct timeval { … … 61 76 extern int tv_gteq(struct timeval *tv1, struct timeval *tv2); 62 77 extern int gettimeofday(struct timeval *tv, struct timezone *tz); 78 extern int getuptime(struct timeval *tv); 63 79 64 80 extern void udelay(useconds_t); 81 82 extern time_t mktime(struct tm *tm); 83 extern int time_utc2tm(const time_t time, struct tm *result); 84 extern int time_utc2str(const time_t time, char *buf); 85 extern void time_tm2str(const struct tm *timeptr, char *buf); 86 extern int time_local2tm(const time_t time, struct tm *result); 87 extern int time_local2str(const time_t time, char *buf); 88 extern double difftime(time_t time1, time_t time0); 89 extern size_t strftime(char *restrict s, size_t maxsize, 90 const char *restrict format, const struct tm *restrict tm); 65 91 66 92 #endif
Note:
See TracChangeset
for help on using the changeset viewer.