Changeset 82cbf8c6 in mainline
- Timestamp:
- 2017-10-08T19:37:24Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2fd26bb
- Parents:
- 81b9d3e
- Location:
- kernel
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/include/genarch/mm/as_ht.h
r81b9d3e r82cbf8c6 37 37 38 38 #include <mm/mm.h> 39 #include <adt/ list.h>39 #include <adt/hash_table.h> 40 40 #include <typedefs.h> 41 41 … … 46 46 47 47 typedef struct pte { 48 link_t link; /**< Page hash table link. */48 ht_link_t link; /**< Page hash table link. */ 49 49 struct as *as; /**< Address space. */ 50 50 uintptr_t page; /**< Virtual memory page. */ -
kernel/genarch/include/genarch/mm/page_ht.h
r81b9d3e r82cbf8c6 46 46 #include <adt/hash_table.h> 47 47 48 #define PAGE_HT_KEYS 249 48 #define KEY_AS 0 50 49 #define KEY_PAGE 1 51 52 #define PAGE_HT_ENTRIES_BITS 1353 #define PAGE_HT_ENTRIES (1 << PAGE_HT_ENTRIES_BITS)54 50 55 51 /* Macros for querying page hash table PTEs. */ … … 66 62 extern slab_cache_t *pte_cache; 67 63 extern hash_table_t page_ht; 68 extern hash_table_op erations_t ht_operations;64 extern hash_table_ops_t ht_ops; 69 65 70 66 #endif -
kernel/genarch/src/mm/as_ht.c
r81b9d3e r82cbf8c6 75 75 { 76 76 if (flags & FLAG_AS_KERNEL) { 77 hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations);77 hash_table_create(&page_ht, 0, 0, &ht_ops); 78 78 pte_cache = slab_cache_create("pte_t", sizeof(pte_t), 0, 79 79 NULL, NULL, SLAB_CACHE_MAGDEFERRED); -
kernel/genarch/src/mm/page_ht.c
r81b9d3e r82cbf8c6 49 49 #include <arch.h> 50 50 #include <assert.h> 51 #include <adt/hash.h> 51 52 #include <adt/hash_table.h> 52 53 #include <align.h> 53 54 54 static size_t hash(sysarg_t[]); 55 static bool compare(sysarg_t[], size_t, link_t *); 56 static void remove_callback(link_t *); 55 static size_t ht_hash(const ht_link_t *); 56 static size_t ht_key_hash(void *); 57 static bool ht_key_equal(void *, const ht_link_t *); 58 static void ht_remove_callback(ht_link_t *); 57 59 58 60 static void ht_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int); … … 80 82 81 83 /** Hash table operations for page hash table. */ 82 hash_table_operations_t ht_operations = { 83 .hash = hash, 84 .compare = compare, 85 .remove_callback = remove_callback 84 hash_table_ops_t ht_ops = { 85 .hash = ht_hash, 86 .key_hash = ht_key_hash, 87 .key_equal = ht_key_equal, 88 .remove_callback = ht_remove_callback 86 89 }; 87 90 … … 95 98 }; 96 99 97 /** Compute page hash table index. 98 * 99 * @param key Array of two keys (i.e. page and address space). 100 * 101 * @return Index into page hash table. 102 * 103 */ 104 size_t hash(sysarg_t key[]) 105 { 106 as_t *as = (as_t *) key[KEY_AS]; 107 uintptr_t page = (uintptr_t) key[KEY_PAGE]; 108 109 /* 110 * Virtual page addresses have roughly the same probability 111 * of occurring. Least significant bits of VPN compose the 112 * hash index. 113 * 114 */ 115 size_t index = ((page >> PAGE_WIDTH) & (PAGE_HT_ENTRIES - 1)); 116 117 /* 118 * Address space structures are likely to be allocated from 119 * similar addresses. Least significant bits compose the 120 * hash index. 121 * 122 */ 123 index |= ((sysarg_t) as) & (PAGE_HT_ENTRIES - 1); 124 125 return index; 126 } 127 128 /** Compare page hash table item with page and/or address space. 129 * 130 * @param key Array of one or two keys (i.e. page and/or address space). 131 * @param keys Number of keys passed. 132 * @param item Item to compare the keys with. 133 * 134 * @return true on match, false otherwise. 135 * 136 */ 137 bool compare(sysarg_t key[], size_t keys, link_t *item) 100 /** Return the hash of the key stored in the item */ 101 size_t ht_hash(const ht_link_t *item) 102 { 103 pte_t *pte = hash_table_get_inst(item, pte_t, link); 104 size_t hash = 0; 105 hash = hash_combine(hash, (uintptr_t) pte->as); 106 hash = hash_combine(hash, pte->page >> PAGE_WIDTH); 107 return hash; 108 } 109 110 /** Return the hash of the key. */ 111 size_t ht_key_hash(void *arg) 112 { 113 uintptr_t *key = (uintptr_t *) arg; 114 size_t hash = 0; 115 hash = hash_combine(hash, key[KEY_AS]); 116 hash = hash_combine(hash, key[KEY_PAGE] >> PAGE_WIDTH); 117 return hash; 118 } 119 120 /** Return true if the key is equal to the item's lookup key. */ 121 bool ht_key_equal(void *arg, const ht_link_t *item) 122 { 123 uintptr_t *key = (uintptr_t *) arg; 124 pte_t *pte = hash_table_get_inst(item, pte_t, link); 125 return (key[KEY_AS] == (uintptr_t) pte->as) && 126 (key[KEY_PAGE] == pte->page); 127 } 128 129 /** Callback on page hash table item removal. 130 * 131 * @param item Page hash table item being removed. 132 * 133 */ 134 void ht_remove_callback(ht_link_t *item) 138 135 { 139 136 assert(item); 140 assert(keys > 0); 141 assert(keys <= PAGE_HT_KEYS); 142 143 /* 144 * Convert item to PTE. 145 * 146 */ 147 pte_t *pte = hash_table_get_instance(item, pte_t, link); 148 149 if (keys == PAGE_HT_KEYS) 150 return (key[KEY_AS] == (uintptr_t) pte->as) && 151 (key[KEY_PAGE] == pte->page); 152 153 return (key[KEY_AS] == (uintptr_t) pte->as); 154 } 155 156 /** Callback on page hash table item removal. 157 * 158 * @param item Page hash table item being removed. 159 * 160 */ 161 void remove_callback(link_t *item) 162 { 163 assert(item); 164 165 /* 166 * Convert item to PTE. 167 * 168 */ 169 pte_t *pte = hash_table_get_instance(item, pte_t, link); 170 137 138 pte_t *pte = hash_table_get_inst(item, pte_t, link); 171 139 slab_free(pte_cache, pte); 172 140 } … … 186 154 unsigned int flags) 187 155 { 188 sysarg_t key[2] = {189 (uintptr_t) as,190 page= ALIGN_DOWN(page, PAGE_SIZE)156 uintptr_t key[2] = { 157 [KEY_AS] = (uintptr_t) as, 158 [KEY_PAGE] = ALIGN_DOWN(page, PAGE_SIZE) 191 159 }; 192 160 … … 218 186 write_barrier(); 219 187 220 hash_table_insert(&page_ht, key,&pte->link);188 hash_table_insert(&page_ht, &pte->link); 221 189 } 222 190 … … 236 204 void ht_mapping_remove(as_t *as, uintptr_t page) 237 205 { 238 sysarg_t key[2] = {239 (uintptr_t) as,240 page= ALIGN_DOWN(page, PAGE_SIZE)206 uintptr_t key[2] = { 207 [KEY_AS] = (uintptr_t) as, 208 [KEY_PAGE] = ALIGN_DOWN(page, PAGE_SIZE) 241 209 }; 242 210 … … 249 217 * by remove_callback(). 250 218 */ 251 hash_table_remove(&page_ht, key , 2);219 hash_table_remove(&page_ht, key); 252 220 253 221 irq_spinlock_unlock(&page_ht_lock, true); 254 222 } 255 223 256 static pte_t *ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock) 257 { 258 sysarg_t key[2] = { 259 (uintptr_t) as, 260 page = ALIGN_DOWN(page, PAGE_SIZE) 224 static pte_t * 225 ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock) 226 { 227 uintptr_t key[2] = { 228 [KEY_AS] = (uintptr_t) as, 229 [KEY_PAGE] = ALIGN_DOWN(page, PAGE_SIZE) 261 230 }; 262 231 263 232 assert(nolock || page_table_locked(as)); 264 233 265 link_t *cur = hash_table_find(&page_ht, key);234 ht_link_t *cur = hash_table_find(&page_ht, key); 266 235 if (cur) 267 return hash_table_get_inst ance(cur, pte_t, link);236 return hash_table_get_inst(cur, pte_t, link); 268 237 269 238 return NULL; -
kernel/generic/include/adt/hash.h
r81b9d3e r82cbf8c6 45 45 * Public domain. 46 46 */ 47 hash = ~hash + (hash << 15); 47 hash = ~hash + (hash << 15); 48 48 hash = hash ^ (hash >> 12); 49 49 hash = hash + (hash << 2); 50 50 hash = hash ^ (hash >> 4); 51 hash = hash * 2057; 51 hash = hash * 2057; 52 52 hash = hash ^ (hash >> 16); 53 return hash; 53 return hash; 54 54 } 55 55 … … 65 65 hash = hash ^ (hash >> 4); 66 66 hash = hash * 0x27d4eb2d; 67 hash = hash ^ (hash >> 15); 68 /* 67 hash = hash ^ (hash >> 15); 68 /* 69 69 * Lower order bits are mixed more thoroughly. Swap them with 70 70 * the higher order bits and make the resulting higher order bits … … 105 105 * http://burtleburtle.net/bob/c/lookup3.c 106 106 */ 107 seed ^= hash + 0x9e3779b9 107 seed ^= hash + 0x9e3779b9 108 108 + ((seed << 5) | (seed >> (sizeof(size_t) * 8 - 5))); 109 return seed; 109 return seed; 110 110 } 111 111 -
kernel/generic/include/adt/hash_table.h
r81b9d3e r82cbf8c6 1 1 /* 2 2 * Copyright (c) 2006 Jakub Jermar 3 * Copyright (c) 2012 Adam Hraska 4 * 3 5 * All rights reserved. 4 6 * … … 27 29 */ 28 30 29 /** @addtogroup genericadt31 /** @addtogroup libc 30 32 * @{ 31 33 */ … … 33 35 */ 34 36 35 #ifndef KERN_HASH_TABLE_H_36 #define KERN_HASH_TABLE_H_37 #ifndef LIBC_HASH_TABLE_H_ 38 #define LIBC_HASH_TABLE_H_ 37 39 38 40 #include <adt/list.h> 39 #include <typedefs.h> 41 #include <stdbool.h> 42 #include <macros.h> 43 44 /** Opaque hash table link type. */ 45 typedef struct ht_link { 46 link_t link; 47 } ht_link_t; 40 48 41 49 /** Set of operations for hash table. */ 42 50 typedef struct { 43 /** Hash function. 44 * 45 * @param key Array of keys needed to compute hash index. All keys must 46 * be passed. 47 * 48 * @return Index into hash table. 49 */ 50 size_t (* hash)(sysarg_t key[]); 51 /** Returns the hash of the key stored in the item (ie its lookup key). */ 52 size_t (*hash)(const ht_link_t *item); 51 53 52 /** Hash table item comparison function.53 *54 * @param key Array of keys that will be compared with item. It is not55 * necessary to pass all keys.56 *57 * @return true if the keys match, false otherwise. 58 */59 bool (* compare)(sysarg_t key[], size_t keys,link_t *item);54 /** Returns the hash of the key. */ 55 size_t (*key_hash)(void *key); 56 57 /** True if the items are equal (have the same lookup keys). */ 58 bool (*equal)(const ht_link_t *item1, const ht_link_t *item2); 59 60 /** Returns true if the key is equal to the item's lookup key. */ 61 bool (*key_equal)(void *key, const ht_link_t *item); 60 62 61 63 /** Hash table item removal callback. 64 * 65 * Must not invoke any mutating functions of the hash table. 62 66 * 63 67 * @param item Item that was removed from the hash table. 64 68 */ 65 void (*remove_callback)( link_t *item);66 } hash_table_op erations_t;69 void (*remove_callback)(ht_link_t *item); 70 } hash_table_ops_t; 67 71 68 72 /** Hash table structure. */ 69 73 typedef struct { 70 list_t *entry; 71 size_t entries; 72 size_t max_keys; 73 hash_table_operations_t *op; 74 hash_table_ops_t *op; 75 list_t *bucket; 76 size_t bucket_cnt; 77 size_t full_item_cnt; 78 size_t item_cnt; 79 size_t max_load; 80 bool apply_ongoing; 74 81 } hash_table_t; 75 82 76 #define hash_table_get_inst ance(item, type, member) \77 list_get_instance((item), type, member)83 #define hash_table_get_inst(item, type, member) \ 84 member_to_inst((item), type, member) 78 85 79 extern void hash_table_create(hash_table_t *h, size_t m, size_t max_keys, 80 hash_table_operations_t *op); 81 extern void hash_table_insert(hash_table_t *h, sysarg_t key[], link_t *item); 82 extern link_t *hash_table_find(hash_table_t *h, sysarg_t key[]); 83 extern void hash_table_remove(hash_table_t *h, sysarg_t key[], size_t keys); 84 extern void hash_table_remove_item(hash_table_t *h, link_t *item); 86 extern bool hash_table_create(hash_table_t *, size_t, size_t, 87 hash_table_ops_t *); 88 extern void hash_table_destroy(hash_table_t *); 89 90 extern bool hash_table_empty(hash_table_t *); 91 extern size_t hash_table_size(hash_table_t *); 92 93 extern void hash_table_clear(hash_table_t *); 94 extern void hash_table_insert(hash_table_t *, ht_link_t *); 95 extern bool hash_table_insert_unique(hash_table_t *, ht_link_t *); 96 extern ht_link_t *hash_table_find(const hash_table_t *, void *); 97 extern ht_link_t *hash_table_find_next(const hash_table_t *, ht_link_t *); 98 extern size_t hash_table_remove(hash_table_t *, void *); 99 extern void hash_table_remove_item(hash_table_t *, ht_link_t *); 100 extern void hash_table_apply(hash_table_t *, bool (*)(ht_link_t *, void *), 101 void *); 102 85 103 86 104 #endif -
kernel/generic/include/ddi/irq.h
r81b9d3e r82cbf8c6 102 102 typedef struct irq { 103 103 /** Hash table link. */ 104 link_t link;104 ht_link_t link; 105 105 106 106 /** Lock protecting everything in this structure -
kernel/generic/include/lib/ra.h
r81b9d3e r82cbf8c6 71 71 typedef struct { 72 72 link_t segment_link; /**< Span's segment list link. */ 73 link_t fu_link; /**< Span's free list or used hash link. */ 73 74 /* 75 * A segment cannot be both on the free list and in the used hash. 76 * Their respective links can therefore occupy the same space. 77 */ 78 union { 79 link_t fl_link; /**< Span's free list link. */ 80 ht_link_t uh_link; /**< Span's used hash link. */ 81 }; 74 82 75 83 uintptr_t base; /**< Segment base. */ -
kernel/generic/include/synch/futex.h
r81b9d3e r82cbf8c6 38 38 #include <typedefs.h> 39 39 #include <synch/waitq.h> 40 #include <adt/hash_table.h> 40 41 41 42 /** Kernel-side futex structure. */ … … 46 47 waitq_t wq; 47 48 /** Futex hash table link. */ 48 link_t ht_link;49 ht_link_t ht_link; 49 50 /** Number of tasks that reference this futex. */ 50 51 size_t refcount; -
kernel/generic/src/adt/hash_table.c
r81b9d3e r82cbf8c6 1 1 /* 2 * Copyright (c) 2006 Jakub Jermar 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2012 Adam Hraska 4 * 3 5 * All rights reserved. 4 6 * … … 27 29 */ 28 30 29 /** @addtogroup genericadt31 /** @addtogroup libc 30 32 * @{ 31 33 */ 32 33 /** 34 * @file 35 * @brief Implementation of generic chained hash table. 36 * 37 * This file contains implementation of generic chained hash table. 34 /** @file 35 */ 36 37 /* 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. 38 49 */ 39 50 40 51 #include <adt/hash_table.h> 41 52 #include <adt/list.h> 53 #include <mm/slab.h> 42 54 #include <assert.h> 43 #include <typedefs.h> 44 #include <mm/slab.h> 45 #include <mem.h> 55 #include <str.h> 56 57 /* Optimal initial bucket count. See comment above. */ 58 #define HT_MIN_BUCKETS 89 59 /* The table is resized when the average load per bucket exceeds this number. */ 60 #define HT_MAX_LOAD 2 61 62 63 static size_t round_up_size(size_t); 64 static bool alloc_table(size_t, list_t **); 65 static void clear_items(hash_table_t *); 66 static void resize(hash_table_t *, size_t); 67 static void grow_if_needed(hash_table_t *); 68 static void shrink_if_needed(hash_table_t *); 69 70 /* Dummy do nothing callback to invoke in place of remove_callback == NULL. */ 71 static void nop_remove_callback(ht_link_t *item) 72 { 73 /* no-op */ 74 } 75 46 76 47 77 /** Create chained hash table. 48 78 * 49 * @param h Hash table structure. Will be initialized by this call. 50 * @param m Number of slots in the hash table. 51 * @param max_keys Maximal number of keys needed to identify an item. 52 * @param op Hash table operations structure. 53 */ 54 void hash_table_create(hash_table_t *h, size_t m, size_t max_keys, hash_table_operations_t *op) 55 { 56 size_t i; 57 79 * @param h Hash table structure. Will be initialized by this call. 80 * @param init_size Initial desired number of hash table buckets. Pass zero 81 * if you want the default initial size. 82 * @param max_load The table is resized when the average load per bucket 83 * exceeds this number. Pass zero if you want the default. 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. 89 * 90 * @return True on success 91 * 92 */ 93 bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_load, 94 hash_table_ops_t *op) 95 { 58 96 assert(h); 59 assert(op); 60 assert(op->hash); 61 assert(op->compare); 62 assert(max_keys > 0); 63 64 h->entry = (list_t *) malloc(m * sizeof(list_t), 0); 65 if (!h->entry) 66 panic("Cannot allocate memory for hash table."); 67 68 memsetb(h->entry, m * sizeof(list_t), 0); 69 70 for (i = 0; i < m; i++) 71 list_initialize(&h->entry[i]); 72 73 h->entries = m; 74 h->max_keys = max_keys; 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) 101 return false; 102 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; 76 } 77 78 /** Insert item into hash table. 79 * 80 * @param h Hash table. 81 * @param key Array of all keys necessary to compute hash index. 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 } 117 118 return true; 119 } 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 = NULL; 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 153 /** Remove all elements from the hash table 154 * 155 * @param h Hash table to be cleared 156 */ 157 void hash_table_clear(hash_table_t *h) 158 { 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 181 list_remove(cur); 182 h->op->remove_callback(cur_link); 183 } 184 } 185 186 h->item_cnt = 0; 187 } 188 189 /** Insert item into a hash table. 190 * 191 * @param h Hash table. 82 192 * @param item Item to be inserted into the hash table. 83 193 */ 84 void hash_table_insert(hash_table_t *h, sysarg_t key[], link_t *item) 85 { 86 size_t chain; 87 194 void hash_table_insert(hash_table_t *h, ht_link_t *item) 195 { 88 196 assert(item); 89 assert(h); 90 assert(h->op); 91 assert(h->op->hash); 92 assert(h->op->compare); 93 94 chain = h->op->hash(key); 95 assert(chain < h->entries); 96 97 list_append(item, &h->entry[chain]); 197 assert(h && h->bucket); 198 assert(!h->apply_ongoing); 199 200 size_t idx = h->op->hash(item) % h->bucket_cnt; 201 202 list_append(&item->link, &h->bucket[idx]); 203 ++h->item_cnt; 204 grow_if_needed(h); 205 } 206 207 208 /** Insert item into a hash table if not already present. 209 * 210 * @param h Hash table. 211 * @param item Item to be inserted into the hash table. 212 * 213 * @return False if such an item had already been inserted. 214 * @return True if the inserted item was the only item with such a lookup key. 215 */ 216 bool hash_table_insert_unique(hash_table_t *h, ht_link_t *item) 217 { 218 assert(item); 219 assert(h && h->bucket && h->bucket_cnt); 220 assert(h->op && h->op->hash && h->op->equal); 221 assert(!h->apply_ongoing); 222 223 size_t idx = h->op->hash(item) % h->bucket_cnt; 224 225 /* Check for duplicates. */ 226 list_foreach(h->bucket[idx], link, ht_link_t, cur_link) { 227 /* 228 * We could filter out items using their hashes first, but 229 * calling equal() might very well be just as fast. 230 */ 231 if (h->op->equal(cur_link, item)) 232 return false; 233 } 234 235 list_append(&item->link, &h->bucket[idx]); 236 ++h->item_cnt; 237 grow_if_needed(h); 238 239 return true; 98 240 } 99 241 100 242 /** Search hash table for an item matching keys. 101 243 * 102 * @param h Hash table.244 * @param h Hash table. 103 245 * @param key Array of all keys needed to compute hash index. 104 246 * 105 247 * @return Matching item on success, NULL if there is no such item. 106 */ 107 link_t *hash_table_find(hash_table_t *h, sysarg_t key[]) 108 { 109 size_t chain; 110 111 assert(h); 112 assert(h->op); 113 assert(h->op->hash); 114 assert(h->op->compare); 115 116 chain = h->op->hash(key); 117 assert(chain < h->entries); 118 119 link_t *cur = list_first(&h->entry[chain]); 120 while (cur != NULL) { 121 if (h->op->compare(key, h->max_keys, cur)) { 122 /* 123 * The entry is there. 248 * 249 */ 250 ht_link_t *hash_table_find(const hash_table_t *h, void *key) 251 { 252 assert(h && h->bucket); 253 254 size_t idx = h->op->key_hash(key) % h->bucket_cnt; 255 256 list_foreach(h->bucket[idx], link, ht_link_t, cur_link) { 257 /* 258 * Is this is the item we are looking for? We could have first 259 * checked if the hashes match but op->key_equal() may very well be 260 * just as fast as op->hash(). 261 */ 262 if (h->op->key_equal(key, cur_link)) { 263 return cur_link; 264 } 265 } 266 267 return NULL; 268 } 269 270 /** Find the next item equal to item. */ 271 ht_link_t *hash_table_find_next(const hash_table_t *h, ht_link_t *item) 272 { 273 assert(item); 274 assert(h && h->bucket); 275 276 /* Traverse the circular list until we reach the starting item again. */ 277 for (link_t *cur = item->link.next; cur != &item->link; cur = cur->next) { 278 assert(cur); 279 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 280 /* 281 * Is this is the item we are looking for? We could have first 282 * checked if the hashes match but op->equal() may very well be 283 * just as fast as op->hash(). 284 */ 285 if (h->op->equal(cur_link, item)) { 286 return cur_link; 287 } 288 } 289 290 return NULL; 291 } 292 293 /** Remove all matching items from hash table. 294 * 295 * For each removed item, h->remove_callback() is called. 296 * 297 * @param h Hash table. 298 * @param key Array of keys that will be compared against items of 299 * the hash table. 300 * 301 * @return Returns the number of removed items. 302 */ 303 size_t hash_table_remove(hash_table_t *h, void *key) 304 { 305 assert(h && h->bucket); 306 assert(!h->apply_ongoing); 307 308 size_t idx = h->op->key_hash(key) % h->bucket_cnt; 309 310 size_t removed = 0; 311 312 list_foreach_safe(h->bucket[idx], cur, next) { 313 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 314 315 if (h->op->key_equal(key, cur_link)) { 316 ++removed; 317 list_remove(cur); 318 h->op->remove_callback(cur_link); 319 } 320 } 321 322 h->item_cnt -= removed; 323 shrink_if_needed(h); 324 325 return removed; 326 } 327 328 /** Removes an item already present in the table. The item must be in the table.*/ 329 void hash_table_remove_item(hash_table_t *h, ht_link_t *item) 330 { 331 assert(item); 332 assert(h && h->bucket); 333 assert(link_in_use(&item->link)); 334 335 list_remove(&item->link); 336 --h->item_cnt; 337 h->op->remove_callback(item); 338 shrink_if_needed(h); 339 } 340 341 /** Apply function to all items in hash table. 342 * 343 * @param h Hash table. 344 * @param f Function to be applied. Return false if no more items 345 * should be visited. The functor may only delete the supplied 346 * item. It must not delete the successor of the item passed 347 * in the first argument. 348 * @param arg Argument to be passed to the function. 349 */ 350 void hash_table_apply(hash_table_t *h, bool (*f)(ht_link_t *, void *), void *arg) 351 { 352 assert(f); 353 assert(h && h->bucket); 354 355 if (h->item_cnt == 0) 356 return; 357 358 h->apply_ongoing = true; 359 360 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 361 list_foreach_safe(h->bucket[idx], cur, next) { 362 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 363 /* 364 * The next pointer had already been saved. f() may safely 365 * delete cur (but not next!). 124 366 */ 125 return cur; 126 } 127 cur = list_next(cur, &h->entry[chain]); 128 } 129 130 return NULL; 131 } 132 133 /** Remove all matching items from hash table. 134 * 135 * For each removed item, h->remove_callback() is called (if not NULL). 136 * 137 * @param h Hash table. 138 * @param key Array of keys that will be compared against items of the hash table. 139 * @param keys Number of keys in the key array. 140 */ 141 void hash_table_remove(hash_table_t *h, sysarg_t key[], size_t keys) 142 { 143 size_t chain; 144 145 assert(h); 146 assert(h->op); 147 assert(h->op->hash); 148 assert(h->op->compare); 149 assert(keys <= h->max_keys); 150 151 152 if (keys == h->max_keys) { 153 link_t *cur; 367 if (!f(cur_link, arg)) 368 goto out; 369 } 370 } 371 out: 372 h->apply_ongoing = false; 373 374 shrink_if_needed(h); 375 grow_if_needed(h); 376 } 377 378 /** Rounds up size to the nearest suitable table size. */ 379 static size_t round_up_size(size_t size) 380 { 381 size_t rounded_size = HT_MIN_BUCKETS; 382 383 while (rounded_size < size) { 384 rounded_size = 2 * rounded_size + 1; 385 } 386 387 return rounded_size; 388 } 389 390 /** Allocates and initializes the desired number of buckets. True if successful.*/ 391 static bool alloc_table(size_t bucket_cnt, list_t **pbuckets) 392 { 393 assert(pbuckets && HT_MIN_BUCKETS <= bucket_cnt); 154 394 155 /* 156 * All keys are known, hash_table_find() can be used to find the entry. 395 list_t *buckets = malloc(bucket_cnt * sizeof(list_t), FRAME_ATOMIC); 396 if (!buckets) 397 return false; 398 399 for (size_t i = 0; i < bucket_cnt; i++) 400 list_initialize(&buckets[i]); 401 402 *pbuckets = buckets; 403 return true; 404 } 405 406 407 /** Shrinks the table if the table is only sparely populated. */ 408 static inline void shrink_if_needed(hash_table_t *h) 409 { 410 if (h->item_cnt <= h->full_item_cnt / 4 && HT_MIN_BUCKETS < h->bucket_cnt) { 411 /* 412 * Keep the bucket_cnt odd (possibly also prime). 413 * Shrink from 2n + 1 to n. Integer division discards the +1. 157 414 */ 158 159 cur = hash_table_find(h, key); 160 if (cur) { 161 list_remove(cur); 162 if (h->op->remove_callback) 163 h->op->remove_callback(cur); 164 } 415 size_t new_bucket_cnt = h->bucket_cnt / 2; 416 resize(h, new_bucket_cnt); 417 } 418 } 419 420 /** Grows the table if table load exceeds the maximum allowed. */ 421 static inline void grow_if_needed(hash_table_t *h) 422 { 423 /* Grow the table if the average bucket load exceeds the maximum. */ 424 if (h->full_item_cnt < h->item_cnt) { 425 /* Keep the bucket_cnt odd (possibly also prime). */ 426 size_t new_bucket_cnt = 2 * h->bucket_cnt + 1; 427 resize(h, new_bucket_cnt); 428 } 429 } 430 431 /** Allocates and rehashes items to a new table. Frees the old table. */ 432 static void resize(hash_table_t *h, size_t new_bucket_cnt) 433 { 434 assert(h && h->bucket); 435 assert(HT_MIN_BUCKETS <= new_bucket_cnt); 436 437 /* We are traversing the table and resizing would mess up the buckets. */ 438 if (h->apply_ongoing) 165 439 return; 166 } 167 168 /* 169 * Fewer keys were passed. 170 * Any partially matching entries are to be removed. 171 */ 172 for (chain = 0; chain < h->entries; chain++) { 173 link_t *cur; 174 for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head; 175 cur = cur->next) { 176 if (h->op->compare(key, keys, cur)) { 177 link_t *hlp; 178 179 hlp = cur; 180 cur = cur->prev; 181 182 list_remove(hlp); 183 if (h->op->remove_callback) 184 h->op->remove_callback(hlp); 185 186 continue; 440 441 list_t *new_buckets; 442 443 /* Leave the table as is if we cannot resize. */ 444 if (!alloc_table(new_bucket_cnt, &new_buckets)) 445 return; 446 447 if (0 < h->item_cnt) { 448 /* Rehash all the items to the new table. */ 449 for (size_t old_idx = 0; old_idx < h->bucket_cnt; ++old_idx) { 450 list_foreach_safe(h->bucket[old_idx], cur, next) { 451 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 452 453 size_t new_idx = h->op->hash(cur_link) % new_bucket_cnt; 454 list_remove(cur); 455 list_append(cur, &new_buckets[new_idx]); 187 456 } 188 457 } 189 458 } 190 } 191 192 /** Remove an existing item from hash table. 193 * 194 * @param h Hash table. 195 * @param item Item to remove from the hash table. 196 */ 197 void hash_table_remove_item(hash_table_t *h, link_t *item) 198 { 199 assert(h); 200 assert(h->op); 201 202 list_remove(item); 203 if (h->op->remove_callback) 204 h->op->remove_callback(item); 205 } 459 460 free(h->bucket); 461 h->bucket = new_buckets; 462 h->bucket_cnt = new_bucket_cnt; 463 h->full_item_cnt = h->max_load * h->bucket_cnt; 464 } 465 206 466 207 467 /** @} -
kernel/generic/src/ddi/irq.c
r81b9d3e r82cbf8c6 40 40 41 41 #include <ddi/irq.h> 42 #include <adt/hash.h> 42 43 #include <adt/hash_table.h> 43 44 #include <mm/slab.h> … … 71 72 hash_table_t irq_uspace_hash_table; 72 73 73 static size_t irq_ht_hash(sysarg_t *key); 74 static bool irq_ht_compare(sysarg_t *key, size_t keys, link_t *item); 75 static void irq_ht_remove(link_t *item); 76 77 static hash_table_operations_t irq_ht_ops = { 74 static size_t irq_ht_hash(const ht_link_t *); 75 static size_t irq_ht_key_hash(void *); 76 static bool irq_ht_equal(const ht_link_t *, const ht_link_t *); 77 static bool irq_ht_key_equal(void *, const ht_link_t *); 78 79 static hash_table_ops_t irq_ht_ops = { 78 80 .hash = irq_ht_hash, 79 .compare = irq_ht_compare, 80 .remove_callback = irq_ht_remove, 81 .key_hash = irq_ht_key_hash, 82 .equal = irq_ht_equal, 83 .key_equal = irq_ht_key_equal 81 84 }; 82 83 /** Number of buckets in either of the hash tables */84 static size_t buckets;85 85 86 86 /** Last valid INR */ … … 95 95 void irq_init(size_t inrs, size_t chains) 96 96 { 97 buckets = chains;98 97 last_inr = inrs - 1; 99 98 … … 102 101 assert(irq_slab); 103 102 104 hash_table_create(&irq_uspace_hash_table, chains, 2, &irq_ht_ops);105 hash_table_create(&irq_kernel_hash_table, chains, 2, &irq_ht_ops);103 hash_table_create(&irq_uspace_hash_table, chains, 0, &irq_ht_ops); 104 hash_table_create(&irq_kernel_hash_table, chains, 0, &irq_ht_ops); 106 105 } 107 106 … … 114 113 { 115 114 memsetb(irq, sizeof(irq_t), 0); 116 link_initialize(&irq->link);117 115 irq_spinlock_initialize(&irq->lock, "irq.lock"); 118 116 irq->inr = -1; … … 131 129 void irq_register(irq_t *irq) 132 130 { 133 sysarg_t key[] = {134 [IRQ_HT_KEY_INR] = (sysarg_t) irq->inr,135 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_NO_CLAIM136 };137 138 131 irq_spinlock_lock(&irq_kernel_hash_table_lock, true); 139 132 irq_spinlock_lock(&irq->lock, false); 140 hash_table_insert(&irq_kernel_hash_table, key,&irq->link);133 hash_table_insert(&irq_kernel_hash_table, &irq->link); 141 134 irq_spinlock_unlock(&irq->lock, false); 142 135 irq_spinlock_unlock(&irq_kernel_hash_table_lock, true); 143 136 } 144 137 145 /** Search and lock the uspaceIRQ hash table */146 static irq_t * irq_dispatch_and_lock_uspace(inr_t inr)147 { 148 link_t *lnk; 149 sysarg_t key[] = {150 [IRQ_HT_KEY_INR] = (sysarg_t) inr,151 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_CLAIM152 };153 154 irq_spinlock_lock(&irq_uspace_hash_table_lock, false);155 lnk = hash_table_find(&irq_uspace_hash_table, key);156 if (lnk) {157 irq_t *irq = hash_table_get_instance(lnk, irq_t, link);158 irq_spinlock_unlock(&irq_uspace_hash_table_lock, false);159 return irq;138 /** Search and lock an IRQ hash table */ 139 static irq_t * 140 irq_dispatch_and_lock_table(hash_table_t *h, irq_spinlock_t *l, inr_t inr) 141 { 142 irq_spinlock_lock(l, false); 143 for (ht_link_t *lnk = hash_table_find(h, &inr); lnk; 144 lnk = hash_table_find_next(h, lnk)) { 145 irq_t *irq = hash_table_get_inst(lnk, irq_t, link); 146 irq_spinlock_lock(&irq->lock, false); 147 if (irq->claim(irq) == IRQ_ACCEPT) { 148 /* leave irq locked */ 149 irq_spinlock_unlock(l, false); 150 return irq; 151 } 152 irq_spinlock_unlock(&irq->lock, false); 160 153 } 161 irq_spinlock_unlock(&irq_uspace_hash_table_lock, false); 162 163 return NULL; 164 } 165 166 /** Search and lock the kernel IRQ hash table */ 167 static irq_t *irq_dispatch_and_lock_kernel(inr_t inr) 168 { 169 link_t *lnk; 170 sysarg_t key[] = { 171 [IRQ_HT_KEY_INR] = (sysarg_t) inr, 172 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_CLAIM 173 }; 174 175 irq_spinlock_lock(&irq_kernel_hash_table_lock, false); 176 lnk = hash_table_find(&irq_kernel_hash_table, key); 177 if (lnk) { 178 irq_t *irq = hash_table_get_instance(lnk, irq_t, link); 179 irq_spinlock_unlock(&irq_kernel_hash_table_lock, false); 180 return irq; 181 } 182 irq_spinlock_unlock(&irq_kernel_hash_table_lock, false); 154 irq_spinlock_unlock(l, false); 183 155 184 156 return NULL; … … 209 181 210 182 if (console_override) { 211 irq_t *irq = irq_dispatch_and_lock_kernel(inr); 183 irq_t *irq = irq_dispatch_and_lock_table(&irq_kernel_hash_table, 184 &irq_kernel_hash_table_lock, inr); 212 185 if (irq) 213 186 return irq; 214 187 215 return irq_dispatch_and_lock_uspace(inr); 188 return irq_dispatch_and_lock_table(&irq_uspace_hash_table, 189 &irq_uspace_hash_table_lock, inr); 216 190 } 217 191 218 irq_t *irq = irq_dispatch_and_lock_uspace(inr); 192 irq_t *irq = irq_dispatch_and_lock_table(&irq_uspace_hash_table, 193 &irq_uspace_hash_table_lock, inr); 219 194 if (irq) 220 195 return irq; 221 196 222 return irq_dispatch_and_lock_kernel(inr); 223 } 224 225 /** Compute hash index for the key 226 * 227 * @param key The first of the keys is inr and the second is mode. Only inr is 228 * used to compute the hash. 229 * 230 * @return Index into the hash table. 231 * 232 */ 233 size_t irq_ht_hash(sysarg_t key[]) 234 { 235 inr_t inr = (inr_t) key[IRQ_HT_KEY_INR]; 236 return inr % buckets; 237 } 238 239 /** Compare hash table element with a key 240 * 241 * If mode is IRQ_HT_MODE_CLAIM, the result of the claim() function is used for 242 * the match. Otherwise the key does not match. 243 * 244 * This function assumes interrupts are already disabled. 245 * 246 * @param key Keys (i.e. inr and mode). 247 * @param keys This is 2. 248 * @param item The item to compare the key with. 249 * 250 * @return True on match 251 * @return False on no match 252 * 253 */ 254 bool irq_ht_compare(sysarg_t key[], size_t keys, link_t *item) 255 { 256 irq_t *irq = hash_table_get_instance(item, irq_t, link); 257 inr_t inr = (inr_t) key[IRQ_HT_KEY_INR]; 258 irq_ht_mode_t mode = (irq_ht_mode_t) key[IRQ_HT_KEY_MODE]; 259 260 bool rv; 261 262 irq_spinlock_lock(&irq->lock, false); 263 if (mode == IRQ_HT_MODE_CLAIM) { 264 /* Invoked by irq_dispatch_and_lock(). */ 265 rv = ((irq->inr == inr) && (irq->claim(irq) == IRQ_ACCEPT)); 266 } else { 267 /* Invoked by irq_find_and_lock(). */ 268 rv = false; 269 } 270 271 /* unlock only on non-match */ 272 if (!rv) 273 irq_spinlock_unlock(&irq->lock, false); 274 275 return rv; 276 } 277 278 /** Unlock IRQ structure after hash_table_remove() 279 * 280 * @param lnk Link in the removed and locked IRQ structure. 281 */ 282 void irq_ht_remove(link_t *lnk) 283 { 284 irq_t *irq __attribute__((unused)) 285 = hash_table_get_instance(lnk, irq_t, link); 286 irq_spinlock_unlock(&irq->lock, false); 197 return irq_dispatch_and_lock_table(&irq_kernel_hash_table, 198 &irq_kernel_hash_table_lock, inr); 199 } 200 201 /** Return the hash of the key stored in the item. */ 202 size_t irq_ht_hash(const ht_link_t *item) 203 { 204 irq_t *irq = hash_table_get_inst(item, irq_t, link); 205 return hash_mix(irq->inr); 206 } 207 208 /** Return the hash of the key. */ 209 size_t irq_ht_key_hash(void *key) 210 { 211 inr_t *inr = (inr_t *) key; 212 return hash_mix(*inr); 213 } 214 215 /** Return true if the items have the same lookup key. */ 216 bool irq_ht_equal(const ht_link_t *item1, const ht_link_t *item2) 217 { 218 irq_t *irq1 = hash_table_get_inst(item1, irq_t, link); 219 irq_t *irq2 = hash_table_get_inst(item2, irq_t, link); 220 return irq1->inr == irq2->inr; 221 } 222 223 /** Return true if the key is equal to the item's lookup key. */ 224 bool irq_ht_key_equal(void *key, const ht_link_t *item) 225 { 226 inr_t *inr = (inr_t *) key; 227 irq_t *irq = hash_table_get_inst(item, irq_t, link); 228 return irq->inr == *inr; 287 229 } 288 230 -
kernel/generic/src/ipc/irq.c
r81b9d3e r82cbf8c6 298 298 irq_code_t *ucode) 299 299 { 300 sysarg_t key[] = {301 [IRQ_HT_KEY_INR] = (sysarg_t) inr,302 [IRQ_HT_KEY_MODE] = (sysarg_t) IRQ_HT_MODE_NO_CLAIM303 };304 305 300 if ((inr < 0) || (inr > last_inr)) 306 301 return ELIMIT; … … 351 346 352 347 irq->notif_cfg.hashed_in = true; 353 hash_table_insert(&irq_uspace_hash_table, key,&irq->link);348 hash_table_insert(&irq_uspace_hash_table, &irq->link); 354 349 355 350 irq_spinlock_unlock(&irq->lock, false); … … 388 383 } 389 384 390 /* kobj->irq->lock unlocked by the hash table remove_callback */385 irq_spinlock_unlock(&kobj->irq->lock, false); 391 386 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 392 387 -
kernel/generic/src/lib/ra.c
r81b9d3e r82cbf8c6 50 50 #include <panic.h> 51 51 #include <adt/list.h> 52 #include <adt/hash.h> 52 53 #include <adt/hash_table.h> 53 54 #include <align.h> … … 57 58 static slab_cache_t *ra_segment_cache; 58 59 59 #define USED_BUCKETS 1024 60 61 static size_t used_hash(sysarg_t *key) 62 { 63 return ((*key >> 2) & (USED_BUCKETS - 1)); 64 } 65 66 static bool used_compare(sysarg_t *key, size_t keys, link_t *item) 67 { 68 ra_segment_t *seg; 69 70 seg = hash_table_get_instance(item, ra_segment_t, fu_link); 71 return seg->base == *key; 72 } 73 74 static hash_table_operations_t used_ops = { 60 /** Return the hash of the key stored in the item */ 61 static size_t used_hash(const ht_link_t *item) 62 { 63 ra_segment_t *seg = hash_table_get_inst(item, ra_segment_t, uh_link); 64 return hash_mix(seg->base); 65 } 66 67 /** Return the hash of the key */ 68 static size_t used_key_hash(void *key) 69 { 70 uintptr_t *base = (uintptr_t *) key; 71 return hash_mix(*base); 72 } 73 74 /** Return true if the key is equal to the item's lookup key */ 75 static bool used_key_equal(void *key, const ht_link_t *item) 76 { 77 uintptr_t *base = (sysarg_t *) key; 78 ra_segment_t *seg = hash_table_get_inst(item, ra_segment_t, uh_link); 79 return seg->base == *base; 80 } 81 82 static hash_table_ops_t used_ops = { 75 83 .hash = used_hash, 76 . compare = used_compare,77 . remove_callback = NULL,84 .key_hash = used_key_hash, 85 .key_equal = used_key_equal 78 86 }; 79 87 … … 97 105 98 106 link_initialize(&seg->segment_link); 99 link_initialize(&seg->f u_link);107 link_initialize(&seg->fl_link); 100 108 101 109 seg->base = base; … … 160 168 list_initialize(&span->segments); 161 169 162 hash_table_create(&span->used, USED_BUCKETS, 1, &used_ops);170 hash_table_create(&span->used, 0, 0, &used_ops); 163 171 164 172 for (i = 0; i <= span->max_order; i++) … … 171 179 172 180 /* Insert the first segment into the respective free list. */ 173 list_append(&seg->f u_link, &span->free[span->max_order]);181 list_append(&seg->fl_link, &span->free[span->max_order]); 174 182 175 183 return span; … … 232 240 /* Take the first segment from the free list. */ 233 241 seg = list_get_instance(list_first(&span->free[order]), 234 ra_segment_t, f u_link);242 ra_segment_t, fl_link); 235 243 236 244 assert(seg->flags & RA_SEGMENT_FREE); … … 274 282 &seg->segment_link); 275 283 pred_order = fnzb(ra_segment_size_get(pred)); 276 list_append(&pred->f u_link, &span->free[pred_order]);284 list_append(&pred->fl_link, &span->free[pred_order]); 277 285 } 278 286 if (succ) { … … 282 290 &seg->segment_link); 283 291 succ_order = fnzb(ra_segment_size_get(succ)); 284 list_append(&succ->f u_link, &span->free[succ_order]);292 list_append(&succ->fl_link, &span->free[succ_order]); 285 293 } 286 294 287 295 /* Now remove the found segment from the free list. */ 288 list_remove(&seg->f u_link);296 list_remove(&seg->fl_link); 289 297 seg->base = newbase; 290 298 seg->flags &= ~RA_SEGMENT_FREE; 291 299 292 300 /* Hash-in the segment into the used hash. */ 293 sysarg_t key = seg->base; 294 hash_table_insert(&span->used, &key, &seg->fu_link); 301 hash_table_insert(&span->used, &seg->uh_link); 295 302 296 303 *base = newbase; … … 304 311 { 305 312 sysarg_t key = base; 306 link_t *link;313 ht_link_t *link; 307 314 ra_segment_t *seg; 308 315 ra_segment_t *pred; … … 318 325 PRIxn ", size=%" PRIdn ").", base, size); 319 326 } 320 seg = hash_table_get_inst ance(link, ra_segment_t, fu_link);327 seg = hash_table_get_inst(link, ra_segment_t, uh_link); 321 328 322 329 /* 323 330 * Hash out the segment. 324 331 */ 325 hash_table_remove (&span->used, &key, 1);332 hash_table_remove_item(&span->used, link); 326 333 327 334 assert(!(seg->flags & RA_SEGMENT_FREE)); … … 333 340 */ 334 341 if (list_first(&span->segments) != &seg->segment_link) { 335 pred = hash_table_get_inst ance(seg->segment_link.prev,342 pred = hash_table_get_inst(seg->segment_link.prev, 336 343 ra_segment_t, segment_link); 337 344 … … 345 352 * away. 346 353 */ 347 list_remove(&pred->f u_link);354 list_remove(&pred->fl_link); 348 355 list_remove(&pred->segment_link); 349 356 seg->base = pred->base; … … 355 362 * Check whether the segment can be coalesced with its right neighbor. 356 363 */ 357 succ = hash_table_get_inst ance(seg->segment_link.next, ra_segment_t,364 succ = hash_table_get_inst(seg->segment_link.next, ra_segment_t, 358 365 segment_link); 359 366 assert(succ->base > seg->base); … … 364 371 * and throw it away. 365 372 */ 366 list_remove(&succ->f u_link);373 list_remove(&succ->fl_link); 367 374 list_remove(&succ->segment_link); 368 375 ra_segment_destroy(succ); … … 372 379 seg->flags |= RA_SEGMENT_FREE; 373 380 order = fnzb(ra_segment_size_get(seg)); 374 list_append(&seg->f u_link, &span->free[order]);381 list_append(&seg->fl_link, &span->free[order]); 375 382 } 376 383 -
kernel/generic/src/synch/futex.c
r81b9d3e r82cbf8c6 74 74 #include <genarch/mm/page_ht.h> 75 75 #include <adt/cht.h> 76 #include <adt/hash.h> 76 77 #include <adt/hash_table.h> 77 78 #include <adt/list.h> … … 80 81 #include <panic.h> 81 82 #include <errno.h> 82 83 #define FUTEX_HT_SIZE 1024 /* keep it a power of 2 */84 83 85 84 /** Task specific pointer to a global kernel futex object. */ … … 108 107 static bool find_futex_paddr(uintptr_t uaddr, uintptr_t *phys_addr); 109 108 110 static size_t futex_ht_hash(sysarg_t *key); 111 static bool futex_ht_compare(sysarg_t *key, size_t keys, link_t *item); 112 static void futex_ht_remove_callback(link_t *item); 109 static size_t futex_ht_hash(const ht_link_t *item); 110 static size_t futex_ht_key_hash(void *key); 111 static bool futex_ht_key_equal(void *key, const ht_link_t *item); 112 static void futex_ht_remove_callback(ht_link_t *item); 113 113 114 114 static size_t task_fut_ht_hash(const cht_link_t *link); … … 131 131 132 132 /** Global kernel futex hash table operations. */ 133 static hash_table_op erations_t futex_ht_ops = {133 static hash_table_ops_t futex_ht_ops = { 134 134 .hash = futex_ht_hash, 135 .compare = futex_ht_compare, 135 .key_hash = futex_ht_key_hash, 136 .key_equal = futex_ht_key_equal, 136 137 .remove_callback = futex_ht_remove_callback 137 138 }; … … 149 150 void futex_init(void) 150 151 { 151 hash_table_create(&futex_ht, FUTEX_HT_SIZE, 1, &futex_ht_ops);152 hash_table_create(&futex_ht, 0, 0, &futex_ht_ops); 152 153 } 153 154 … … 234 235 { 235 236 waitq_initialize(&futex->wq); 236 link_initialize(&futex->ht_link);237 237 futex->paddr = paddr; 238 238 futex->refcount = 1; … … 256 256 257 257 if (0 == futex->refcount) { 258 hash_table_remove(&futex_ht, &futex->paddr , 1);258 hash_table_remove(&futex_ht, &futex->paddr); 259 259 } 260 260 } … … 347 347 spinlock_lock(&futex_ht_lock); 348 348 349 link_t *fut_link = hash_table_find(&futex_ht, &phys_addr);349 ht_link_t *fut_link = hash_table_find(&futex_ht, &phys_addr); 350 350 351 351 if (fut_link) { … … 355 355 } else { 356 356 futex_initialize(futex, phys_addr); 357 hash_table_insert(&futex_ht, & phys_addr, &futex->ht_link);357 hash_table_insert(&futex_ht, &futex->ht_link); 358 358 } 359 359 … … 437 437 438 438 439 /** Compute hash index into futex hash table. 440 * 441 * @param key Address where the key (i.e. physical address of futex 442 * counter) is stored. 443 * 444 * @return Index into futex hash table. 445 */ 446 size_t futex_ht_hash(sysarg_t *key) 447 { 448 return (*key & (FUTEX_HT_SIZE - 1)); 449 } 450 451 /** Compare futex hash table item with a key. 452 * 453 * @param key Address where the key (i.e. physical address of futex 454 * counter) is stored. 455 * 456 * @return True if the item matches the key. False otherwise. 457 */ 458 bool futex_ht_compare(sysarg_t *key, size_t keys, link_t *item) 439 /** Return the hash of the key stored in the item */ 440 size_t futex_ht_hash(const ht_link_t *item) 441 { 442 futex_t *futex = hash_table_get_inst(item, futex_t, ht_link); 443 return hash_mix(futex->paddr); 444 } 445 446 /** Return the hash of the key */ 447 size_t futex_ht_key_hash(void *key) 448 { 449 uintptr_t *paddr = (uintptr_t *) key; 450 return hash_mix(*paddr); 451 } 452 453 /** Return true if the key is equal to the item's lookup key. */ 454 bool futex_ht_key_equal(void *key, const ht_link_t *item) 455 { 456 uintptr_t *paddr = (uintptr_t *) key; 457 futex_t *futex = hash_table_get_inst(item, futex_t, ht_link); 458 return *paddr == futex->paddr; 459 } 460 461 /** Callback for removal items from futex hash table. 462 * 463 * @param item Item removed from the hash table. 464 */ 465 void futex_ht_remove_callback(ht_link_t *item) 459 466 { 460 467 futex_t *futex; 461 468 462 assert(keys == 1); 463 464 futex = hash_table_get_instance(item, futex_t, ht_link); 465 return *key == futex->paddr; 466 } 467 468 /** Callback for removal items from futex hash table. 469 * 470 * @param item Item removed from the hash table. 471 */ 472 void futex_ht_remove_callback(link_t *item) 473 { 474 futex_t *futex; 475 476 futex = hash_table_get_instance(item, futex_t, ht_link); 469 futex = hash_table_get_inst(item, futex_t, ht_link); 477 470 free(futex); 478 471 }
Note:
See TracChangeset
for help on using the changeset viewer.