Changeset 0ca7286 in mainline
- Timestamp:
- 2012-07-21T11:19:27Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2732c94
- Parents:
- 1c1da4b
- Location:
- uspace
- Files:
-
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/trace/ipcp.c
r1c1da4b r0ca7286 38 38 #include <sys/typefmt.h> 39 39 #include <abi/ipc/methods.h> 40 #include <macros.h> 40 41 #include "ipc_desc.h" 41 42 #include "proto.h" … … 64 65 int have_conn[MAX_PHONE]; 65 66 66 #define PCALL_TABLE_CHAINS 32 67 hash_table_t pending_calls; 67 static hash_table_t pending_calls; 68 68 69 69 /* … … 73 73 proto_t *proto_unknown; /**< Protocol with no known methods. */ 74 74 75 static hash_index_t pending_call_hash(unsigned long key[]);76 static int pending_call_compare(unsigned long key[], hash_count_t keys,77 link_t *item); 78 static void pending_call_remove_callback(link_t *item);79 80 hash_table_operations_t pending_call_ops = {75 static size_t pending_call_key_hash(unsigned long key[]); 76 static size_t pending_call_hash(const link_t *item); 77 static bool pending_call_match(unsigned long key[], size_t keys, 78 const link_t *item); 79 80 static hash_table_ops_t pending_call_ops = { 81 81 .hash = pending_call_hash, 82 .compare = pending_call_compare, 83 .remove_callback = pending_call_remove_callback 82 .key_hash = pending_call_key_hash, 83 .match = pending_call_match, 84 .equal = 0, 85 .remove_callback = 0 84 86 }; 85 87 86 88 87 static hash_index_t pending_call_hash(unsigned long key[]) 88 { 89 // printf("pending_call_hash\n"); 90 return key[0] % PCALL_TABLE_CHAINS; 91 } 92 93 static int pending_call_compare(unsigned long key[], hash_count_t keys, 94 link_t *item) 95 { 96 pending_call_t *hs; 97 98 // printf("pending_call_compare\n"); 99 hs = hash_table_get_instance(item, pending_call_t, link); 100 101 // FIXME: this will fail if sizeof(long) < sizeof(void *). 102 return key[0] == hs->call_hash; 103 } 104 105 static void pending_call_remove_callback(link_t *item) 106 { 107 // printf("pending_call_remove_callback\n"); 108 } 89 static size_t pending_call_key_hash(unsigned long key[]) 90 { 91 size_t hash = 17; 92 hash = 31 * hash + key[1]; 93 hash = 31 * hash + key[0]; 94 return hash; 95 } 96 97 static size_t pending_call_hash(const link_t *item) 98 { 99 pending_call_t *hs = hash_table_get_instance(item, pending_call_t, link); 100 unsigned long key[] = { 101 LOWER32(hs->call_hash), 102 UPPER32(hs->call_hash) 103 }; 104 return pending_call_key_hash(key); 105 } 106 107 static bool pending_call_match(unsigned long key[], size_t keys, 108 const link_t *item) 109 { 110 assert(keys == 2); 111 pending_call_t *hs = hash_table_get_instance(item, pending_call_t, link); 112 113 return MERGE_LOUP32(key[0], key[1]) == hs->call_hash; 114 } 115 109 116 110 117 … … 177 184 } 178 185 179 hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);186 hash_table_create(&pending_calls, 0, 2, &pending_call_ops); 180 187 } 181 188 … … 190 197 pending_call_t *pcall; 191 198 proto_t *proto; 192 unsigned long key[1];193 199 oper_t *oper; 194 200 sysarg_t *args; … … 254 260 pcall->oper = oper; 255 261 256 key[0] = hash; 257 258 hash_table_insert(&pending_calls, key, &pcall->link); 262 hash_table_insert(&pending_calls, &pcall->link); 259 263 } 260 264 … … 336 340 link_t *item; 337 341 pending_call_t *pcall; 338 unsigned long key[1];339 342 340 343 if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) { … … 347 350 348 351 hash = hash & ~IPC_CALLID_ANSWERED; 349 key[0] = hash; 352 unsigned long key[] = { 353 LOWER32(hash), 354 UPPER32(hash) 355 }; 350 356 351 357 item = hash_table_find(&pending_calls, key); … … 358 364 359 365 pcall = hash_table_get_instance(item, pending_call_t, link); 360 hash_table_remove(&pending_calls, key, 1);366 hash_table_remove(&pending_calls, key, 2); 361 367 362 368 parse_answer(hash, pcall, call); -
uspace/app/trace/proto.c
r1c1da4b r0ca7286 40 40 #include "proto.h" 41 41 42 #define SRV_PROTO_TABLE_CHAINS 32 43 #define METHOD_OPER_TABLE_CHAINS 32 44 45 hash_table_t srv_proto; 42 43 /* Maps service number to protocol */ 44 static hash_table_t srv_proto; 46 45 47 46 typedef struct { … … 57 56 } method_oper_t; 58 57 59 static hash_index_t srv_proto_hash(unsigned long key[]); 60 static int srv_proto_compare(unsigned long key[], hash_count_t keys, 61 link_t *item); 62 static void srv_proto_remove_callback(link_t *item); 63 64 hash_table_operations_t srv_proto_ops = { 58 59 60 61 static size_t srv_proto_key_hash(unsigned long key[]) 62 { 63 return key[0]; 64 } 65 66 static size_t srv_proto_hash(const link_t *item) 67 { 68 srv_proto_t *sp = hash_table_get_instance(item, srv_proto_t, link); 69 unsigned long key = sp->srv; 70 return srv_proto_key_hash(&key); 71 } 72 73 static bool srv_proto_match(unsigned long key[], size_t keys, const link_t *item) 74 { 75 srv_proto_t *sp = hash_table_get_instance(item, srv_proto_t, link); 76 77 return key[0] == sp->srv; 78 } 79 80 static hash_table_ops_t srv_proto_ops = { 65 81 .hash = srv_proto_hash, 66 .compare = srv_proto_compare, 67 .remove_callback = srv_proto_remove_callback 82 .key_hash = srv_proto_key_hash, 83 .match = srv_proto_match, 84 .equal = 0, 85 .remove_callback = 0 68 86 }; 69 87 70 static hash_index_t method_oper_hash(unsigned long key[]); 71 static int method_oper_compare(unsigned long key[], hash_count_t keys, 72 link_t *item); 73 static void method_oper_remove_callback(link_t *item); 74 75 hash_table_operations_t method_oper_ops = { 88 89 static size_t method_oper_key_hash(unsigned long key[]) 90 { 91 return key[0]; 92 } 93 94 static size_t method_oper_hash(const link_t *item) 95 { 96 method_oper_t *mo = hash_table_get_instance(item, method_oper_t, link); 97 unsigned long key = mo->method; 98 return method_oper_key_hash(&key); 99 } 100 101 static bool method_oper_match(unsigned long key[], size_t keys, 102 const link_t *item) 103 { 104 method_oper_t *mo = hash_table_get_instance(item, method_oper_t, link); 105 106 return key[0] == mo->method; 107 } 108 109 static hash_table_ops_t method_oper_ops = { 76 110 .hash = method_oper_hash, 77 .compare = method_oper_compare, 78 .remove_callback = method_oper_remove_callback 111 .key_hash = method_oper_key_hash, 112 .match = method_oper_match, 113 .equal = 0, 114 .remove_callback = 0 79 115 }; 80 116 81 static hash_index_t srv_proto_hash(unsigned long key[]) 82 { 83 return key[0] % SRV_PROTO_TABLE_CHAINS; 84 } 85 86 static int srv_proto_compare(unsigned long key[], hash_count_t keys, 87 link_t *item) 117 118 void proto_init(void) 119 { 120 hash_table_create(&srv_proto, 0, 1, &srv_proto_ops); 121 } 122 123 void proto_cleanup(void) 124 { 125 hash_table_destroy(&srv_proto); 126 } 127 128 void proto_register(int srv, proto_t *proto) 88 129 { 89 130 srv_proto_t *sp; 90 91 sp = hash_table_get_instance(item, srv_proto_t, link);92 93 return key[0] == sp->srv;94 }95 96 static void srv_proto_remove_callback(link_t *item)97 {98 }99 100 static hash_index_t method_oper_hash(unsigned long key[])101 {102 return key[0] % METHOD_OPER_TABLE_CHAINS;103 }104 105 static int method_oper_compare(unsigned long key[], hash_count_t keys,106 link_t *item)107 {108 method_oper_t *mo;109 110 mo = hash_table_get_instance(item, method_oper_t, link);111 112 return key[0] == mo->method;113 }114 115 static void method_oper_remove_callback(link_t *item)116 {117 }118 119 120 void proto_init(void)121 {122 hash_table_create(&srv_proto, SRV_PROTO_TABLE_CHAINS, 1,123 &srv_proto_ops);124 }125 126 void proto_cleanup(void)127 {128 hash_table_destroy(&srv_proto);129 }130 131 void proto_register(int srv, proto_t *proto)132 {133 srv_proto_t *sp;134 unsigned long key;135 131 136 132 sp = malloc(sizeof(srv_proto_t)); 137 133 sp->srv = srv; 138 134 sp->proto = proto; 139 key = srv; 140 141 hash_table_insert(&srv_proto, &key, &sp->link); 135 136 hash_table_insert(&srv_proto, &sp->link); 142 137 } 143 138 144 139 proto_t *proto_get_by_srv(int srv) 145 140 { 146 unsigned long key;147 141 link_t *item; 148 142 srv_proto_t *sp; 149 143 150 key = srv;144 unsigned long key = srv; 151 145 item = hash_table_find(&srv_proto, &key); 152 146 if (item == NULL) return NULL; … … 159 153 { 160 154 proto->name = name; 161 hash_table_create(&proto->method_oper, SRV_PROTO_TABLE_CHAINS, 1, 162 &method_oper_ops); 155 hash_table_create(&proto->method_oper, 0, 1, &method_oper_ops); 163 156 } 164 157 … … 181 174 { 182 175 method_oper_t *mo; 183 unsigned long key;184 176 185 177 mo = malloc(sizeof(method_oper_t)); 186 178 mo->method = method; 187 179 mo->oper = oper; 188 key = method; 189 190 hash_table_insert(&proto->method_oper, &key, &mo->link); 180 181 hash_table_insert(&proto->method_oper, &mo->link); 191 182 } 192 183 -
uspace/app/trace/proto.h
r1c1da4b r0ca7286 62 62 } proto_t; 63 63 64 /* Maps service number to protocol */65 extern hash_table_t srv_proto;66 64 67 65 extern void proto_init(void); -
uspace/lib/block/libblock.c
r1c1da4b r0ca7286 62 62 static LIST_INITIALIZE(dcl); 63 63 64 #define CACHE_BUCKETS_LOG2 1065 #define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)66 64 67 65 typedef struct { … … 256 254 } 257 255 258 static hash_index_t cache_hash(unsigned long *key) 259 { 260 return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1); 261 } 262 263 static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item) 256 static size_t cache_key_hash(unsigned long *key) 257 { 258 /* As recommended by Effective Java, 2nd Edition. */ 259 size_t hash = 17; 260 hash = 31 * hash + key[1]; 261 hash = 31 * hash + key[0]; 262 return hash; 263 } 264 265 static size_t cache_hash(const link_t *item) 266 { 267 block_t *b = hash_table_get_instance(item, block_t, hash_link); 268 unsigned long key[] = { 269 LOWER32(b->lba), 270 UPPER32(b->lba) 271 }; 272 273 return cache_key_hash(key); 274 } 275 276 static bool cache_match(unsigned long *key, size_t keys, const link_t *item) 264 277 { 265 278 block_t *b = hash_table_get_instance(item, block_t, hash_link); … … 267 280 } 268 281 269 static void cache_remove_callback(link_t *item) 270 { 271 } 272 273 static hash_table_operations_t cache_ops = { 282 283 static hash_table_ops_t cache_ops = { 274 284 .hash = cache_hash, 275 .compare = cache_compare, 276 .remove_callback = cache_remove_callback 285 .key_hash = cache_key_hash, 286 .match = cache_match, 287 .equal = 0, 288 .remove_callback = 0 277 289 }; 278 290 … … 305 317 cache->blocks_cluster = cache->lblock_size / devcon->pblock_size; 306 318 307 if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2, 308 &cache_ops)) { 319 if (!hash_table_create(&cache->block_hash, 0, 2, &cache_ops)) { 309 320 free(cache); 310 321 return ENOMEM; … … 540 551 b->lba = ba; 541 552 b->pba = ba_ltop(devcon, b->lba); 542 hash_table_insert(&cache->block_hash, key,&b->hash_link);553 hash_table_insert(&cache->block_hash, &b->hash_link); 543 554 544 555 /* -
uspace/lib/c/generic/adt/hash_table.c
r1c1da4b r0ca7286 34 34 35 35 /* 36 * This is an implementation of generic chained hash table. 36 * This is an implementation of a generic resizable chained hash table. 37 * 38 * The table grows to 2*n+1 buckets each time, starting at n == 89, 39 * per Thomas Wang's recommendation: 40 * http://www.concentric.net/~Ttwang/tech/hashsize.htm 41 * 42 * This policy produces prime table sizes for the first five resizes 43 * and generally produces table sizes which are either prime or 44 * have fairly large (prime/odd) divisors. Having a prime table size 45 * mitigates the use of suboptimal hash functions and distributes 46 * items over the whole table. 37 47 */ 38 48 … … 44 54 #include <str.h> 45 55 56 /* Optimal initial bucket count. See comment above. */ 57 #define HT_MIN_BUCKETS 89 58 /* The table is resized when the average load per bucket exceeds this number. */ 59 #define HT_MAX_LOAD 2 60 61 62 static size_t round_up_size(size_t size); 63 static bool alloc_table(size_t bucket_cnt, list_t **pbuckets); 64 static void item_inserted(hash_table_t *h); 65 static void item_removed(hash_table_t *h); 66 static inline void remove_item(hash_table_t *h, link_t *item); 67 static size_t remove_duplicates(hash_table_t *h, unsigned long key[]); 68 static size_t remove_matching(hash_table_t *h, unsigned long key[], size_t key_cnt); 69 70 /* Dummy do nothing callback to invoke in place of remove_callback == NULL. */ 71 static void nop_remove_callback(link_t *item) 72 { 73 /* no-op */ 74 } 75 76 46 77 /** Create chained hash table. 47 78 * 48 79 * @param h Hash table structure. Will be initialized by this call. 49 * @param m Number of hash table buckets. 80 * @param init_size Initial desired number of hash table buckets. Pass zero 81 * if you want the default initial size. 50 82 * @param max_keys Maximal number of keys needed to identify an item. 51 * @param op Hash table operations structure. 83 * @param op Hash table operations structure. remove_callback() 84 * is optional and can be NULL if no action is to be taken 85 * upon removal. equal() is optional if and only if 86 * hash_table_insert_unique() will never be invoked. 87 * All other operations are mandatory. 52 88 * 53 89 * @return True on success 54 90 * 55 91 */ 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)92 bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_keys, 93 hash_table_ops_t *op) 58 94 { 59 95 assert(h); 60 assert(op && op->hash && op-> compare);96 assert(op && op->hash && op->key_hash && op->match); 61 97 assert(max_keys > 0); 62 98 63 h->entry = malloc(m * sizeof(list_t)); 64 if (!h->entry) 99 h->bucket_cnt = round_up_size(init_size); 100 101 if (!alloc_table(h->bucket_cnt, &h->bucket)) 65 102 return false; 66 103 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 104 h->max_keys = max_keys; 105 h->items = 0; 75 106 h->op = op; 76 107 108 if (h->op->remove_callback == 0) 109 h->op->remove_callback = nop_remove_callback; 110 77 111 return true; 78 112 } … … 84 118 void hash_table_clear(hash_table_t *h) 85 119 { 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; 120 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 121 list_foreach_safe(h->bucket[idx], cur, next) { 94 122 list_remove(cur); 95 123 h->op->remove_callback(cur); 96 124 } 97 125 } 126 127 h->items = 0; 128 129 /* Shrink the table to its minimum size if possible. */ 130 if (HT_MIN_BUCKETS < h->bucket_cnt) { 131 list_t *new_buckets; 132 if (alloc_table(HT_MIN_BUCKETS, &new_buckets)) { 133 free(h->bucket); 134 h->bucket = new_buckets; 135 h->bucket_cnt = HT_MIN_BUCKETS; 136 } 137 } 98 138 } 99 139 … … 106 146 { 107 147 assert(h); 108 assert(h->entry); 109 110 free(h->entry); 148 assert(h->bucket); 149 150 free(h->bucket); 151 152 h->bucket = 0; 153 h->bucket_cnt = 0; 111 154 } 112 155 … … 117 160 * @param item Item to be inserted into the hash table. 118 161 */ 119 void hash_table_insert(hash_table_t *h, unsigned long key[],link_t *item)162 void hash_table_insert(hash_table_t *h, link_t *item) 120 163 { 121 164 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]); 165 assert(h && h->bucket); 166 assert(h->op && h->op->hash); 167 168 size_t idx = h->op->hash(item) % h->bucket_cnt; 169 170 assert(idx < h->bucket_cnt); 171 172 list_append(item, &h->bucket[idx]); 173 item_inserted(h); 174 } 175 176 177 /** Insert item into a hash table if not already present. 178 * 179 * @param h Hash table. 180 * @param key Array of all keys necessary to compute hash index. 181 * @param item Item to be inserted into the hash table. 182 * 183 * @return False if such an item had already been inserted. 184 * @return True if the inserted item was the only item with such a lookup key. 185 */ 186 bool hash_table_insert_unique(hash_table_t *h, link_t *item) 187 { 188 assert(item); 189 assert(h && h->bucket && h->bucket_cnt); 190 assert(h->op && h->op->hash && h->op->equal); 191 192 size_t item_hash = h->op->hash(item); 193 size_t idx = item_hash % h->bucket_cnt; 194 195 assert(idx < h->bucket_cnt); 196 197 /* Check for duplicates. */ 198 list_foreach(h->bucket[idx], cur) { 199 /* 200 * We could filter out items using their hashes first, but 201 * calling equal() might very well be just as fast. 202 */ 203 if (h->op->equal(cur, item)) 204 return false; 205 } 206 207 list_append(item, &h->bucket[idx]); 208 item_inserted(h); 209 210 return true; 128 211 } 129 212 … … 138 221 link_t *hash_table_find(hash_table_t *h, unsigned long key[]) 139 222 { 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. 223 assert(h && h->bucket); 224 assert(h->op && h->op->key_hash && h->op->match); 225 226 size_t key_hash = h->op->key_hash(key); 227 size_t idx = key_hash % h->bucket_cnt; 228 229 assert(idx < h->bucket_cnt); 230 231 list_foreach(h->bucket[idx], cur) { 232 /* 233 * Is this is the item we are looking for? We could have first 234 * checked if the hashes match but op->match() may very well be 235 * just as fast as op->hash(). 236 */ 237 if (h->op->match(key, h->max_keys, cur)) { 238 return cur; 239 } 240 } 241 242 return NULL; 243 } 244 245 246 /** Apply function to all items in hash table. 247 * 248 * @param h Hash table. 249 * @param f Function to be applied. Return false if no more items 250 * should be visited. The functor must not delete the successor 251 * of the item passed in the first argument. 252 * @param arg Argument to be passed to the function. 253 * 254 */ 255 void hash_table_apply(hash_table_t *h, bool (*f)(link_t *, void *), void *arg) 256 { 257 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 258 list_foreach_safe(h->bucket[idx], cur, next) { 259 /* 260 * The next pointer had already been saved. f() may safely 261 * delete cur (but not next!). 149 262 */ 150 return cur; 151 } 152 } 153 154 return NULL; 263 if (!f(cur, arg)) 264 return; 265 } 266 } 155 267 } 156 268 … … 163 275 * the hash table. 164 276 * @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 && 277 * 278 * @return Returns the number of removed items. 279 */ 280 size_t hash_table_remove(hash_table_t *h, unsigned long key[], size_t key_cnt) 281 { 282 assert(h && h->bucket); 283 assert(h && h->op && h->op->hash && 170 284 h->op->remove_callback); 171 assert(keys <= h->max_keys); 172 173 if (keys == h->max_keys) { 285 assert(key_cnt <= h->max_keys); 286 287 /* All keys are known, remove from a specific bucket. */ 288 if (key_cnt == h->max_keys) { 289 return remove_duplicates(h, key); 290 } else { 174 291 /* 175 * All keys are known, hash_table_find() can be used to find the 176 * entry. 177 */ 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 185 return; 186 } 187 292 * Fewer keys were passed. 293 * Any partially matching entries are to be removed. 294 */ 295 return remove_matching(h, key, key_cnt); 296 } 297 } 298 299 /** Removes an item already present in the table. The item must be in the table.*/ 300 void hash_table_remove_item(hash_table_t *h, link_t *item) 301 { 302 assert(item); 303 assert(h && h->bucket); 304 305 remove_item(h, item); 306 } 307 308 /** Unlink the item from a bucket, update statistics and resize if needed. */ 309 static inline void remove_item(hash_table_t *h, link_t *item) 310 { 311 assert(item); 312 313 list_remove(item); 314 item_removed(h); 315 h->op->remove_callback(item); 316 } 317 318 /** Removes all items matching key in the bucket key hashes to. */ 319 static size_t remove_duplicates(hash_table_t *h, unsigned long key[]) 320 { 321 assert(h && h->bucket); 322 assert(h->op && h->op->key_hash && h->op->match); 323 324 size_t key_hash = h->op->key_hash(key); 325 size_t idx = key_hash % h->bucket_cnt; 326 327 assert(idx < h->bucket_cnt); 328 329 size_t removed = 0; 330 331 list_foreach_safe(h->bucket[idx], cur, next) { 332 if (h->op->match(key, h->max_keys, cur)) { 333 ++removed; 334 remove_item(h, cur); 335 } 336 } 337 338 return removed; 339 } 340 341 /** Removes all items in any bucket in the table that match the partial key. */ 342 static size_t remove_matching(hash_table_t *h, unsigned long key[], 343 size_t key_cnt) 344 { 345 assert(h && h->bucket); 346 assert(key_cnt < h->max_keys); 347 348 size_t removed = 0; 188 349 /* 189 350 * Fewer keys were passed. 190 351 * Any partially matching entries are to be removed. 191 352 */ 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; 353 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 354 list_foreach_safe(h->bucket[idx], cur, next) { 355 if (h->op->match(key, key_cnt, cur)) { 356 ++removed; 357 remove_item(h, cur); 207 358 } 208 359 } 209 360 } 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 } 361 362 return removed; 363 364 } 365 366 /** Rounds up size to the nearest suitable table size. */ 367 static size_t round_up_size(size_t size) 368 { 369 size_t rounded_size = HT_MIN_BUCKETS; 370 371 while (rounded_size < size) { 372 rounded_size = 2 * rounded_size + 1; 373 } 374 375 return rounded_size; 376 } 377 378 /** Allocates and initializes the desired number of buckets. True if successful.*/ 379 static bool alloc_table(size_t bucket_cnt, list_t **pbuckets) 380 { 381 assert(pbuckets && HT_MIN_BUCKETS <= bucket_cnt); 382 383 list_t *buckets = malloc(bucket_cnt * sizeof(list_t)); 384 if (!buckets) 385 return false; 386 387 for (size_t i = 0; i < bucket_cnt; i++) 388 list_initialize(&buckets[i]); 389 390 *pbuckets = buckets; 391 return true; 392 } 393 394 /** Allocates and rehashes items to a new table. Frees the old table. */ 395 static void resize(hash_table_t *h, size_t new_bucket_cnt) 396 { 397 assert(h && h->bucket); 398 399 list_t *new_buckets; 400 401 /* Leave the table as is if we cannot resize. */ 402 if (!alloc_table(new_bucket_cnt, &new_buckets)) 403 return; 404 405 /* Rehash all the items to the new table. */ 406 for (size_t old_idx = 0; old_idx < h->bucket_cnt; ++old_idx) { 407 list_foreach_safe(h->bucket[old_idx], cur, next) { 408 size_t new_idx = h->op->hash(cur) % new_bucket_cnt; 409 list_remove(cur); 410 list_append(cur, &new_buckets[new_idx]); 411 } 412 } 413 414 free(h->bucket); 415 h->bucket = new_buckets; 416 h->bucket_cnt = new_bucket_cnt; 417 } 418 419 /** Shrinks the table if needed. */ 420 static void item_removed(hash_table_t *h) 421 { 422 --h->items; 423 424 if (HT_MIN_BUCKETS < h->items && h->items <= HT_MAX_LOAD * h->bucket_cnt / 4) { 425 /* 426 * Keep the bucket_cnt odd (possibly also prime). 427 * Shrink from 2n + 1 to n. Integer division discards the +1. 428 */ 429 size_t new_bucket_cnt = h->bucket_cnt / 2; 430 resize(h, new_bucket_cnt); 431 } 432 } 433 434 /** Grows the table if needed. */ 435 static void item_inserted(hash_table_t *h) 436 { 437 ++h->items; 438 439 /* Grow the table if the average bucket load exceeds the maximum. */ 440 if (HT_MAX_LOAD * h->bucket_cnt < h->items) { 441 /* Keep the bucket_cnt odd (possibly also prime). */ 442 size_t new_bucket_cnt = 2 * h->bucket_cnt + 1; 443 resize(h, new_bucket_cnt); 444 } 445 } 446 237 447 238 448 /** @} -
uspace/lib/c/generic/async.c
r1c1da4b r0ca7286 115 115 #include <macros.h> 116 116 117 #define CLIENT_HASH_TABLE_BUCKETS 32118 #define CONN_HASH_TABLE_BUCKETS 32119 117 120 118 /** Session data */ … … 392 390 static LIST_INITIALIZE(timeout_list); 393 391 394 static hash_index_t client_hash(unsigned long key[])392 static size_t client_key_hash(unsigned long key[]) 395 393 { 396 394 assert(key); 397 398 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 399 } 400 401 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 395 /* LOWER32(in_task_id) */ 396 return key[0] >> 4; 397 } 398 399 static size_t client_hash(const link_t *item) 400 { 401 client_t *client = hash_table_get_instance(item, client_t, link); 402 403 unsigned long key[2] = { 404 LOWER32(client->in_task_id), 405 UPPER32(client->in_task_id), 406 }; 407 408 return client_key_hash(key); 409 } 410 411 static bool client_match(unsigned long key[], size_t keys, const link_t *item) 402 412 { 403 413 assert(key); … … 410 420 } 411 421 412 static void client_remove(link_t *item)413 {414 }415 422 416 423 /** Operations for the client hash table. */ 417 static hash_table_op erations_t client_hash_table_ops = {424 static hash_table_ops_t client_hash_table_ops = { 418 425 .hash = client_hash, 419 .compare = client_compare, 420 .remove_callback = client_remove 426 .key_hash = client_key_hash, 427 .match = client_match, 428 .equal = 0, 429 .remove_callback = 0 421 430 }; 422 431 … … 428 437 * 429 438 */ 430 static hash_index_t conn_hash(unsigned long key[])439 static size_t conn_key_hash(unsigned long key[]) 431 440 { 432 441 assert(key); 433 434 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 442 return key[0] >> 4; 443 } 444 445 static size_t conn_hash(const link_t *item) 446 { 447 connection_t *conn = hash_table_get_instance(item, connection_t, link); 448 unsigned long key = conn->in_phone_hash; 449 return conn_key_hash(&key); 435 450 } 436 451 … … 444 459 * 445 460 */ 446 static int conn_compare(unsigned long key[], hash_count_t keys,link_t *item)461 static bool conn_match(unsigned long key[], size_t keys, const link_t *item) 447 462 { 448 463 assert(key); … … 453 468 } 454 469 470 static bool conn_equal(const link_t *item1, const link_t *item2) 471 { 472 connection_t *c1 = hash_table_get_instance(item1, connection_t, link); 473 connection_t *c2 = hash_table_get_instance(item2, connection_t, link); 474 475 return c1->in_phone_hash == c2->in_phone_hash; 476 } 477 455 478 static void conn_remove(link_t *item) 456 479 { … … 458 481 459 482 /** Operations for the connection hash table. */ 460 static hash_table_op erations_t conn_hash_table_ops = {483 static hash_table_ops_t conn_hash_table_ops = { 461 484 .hash = conn_hash, 462 .compare = conn_compare, 485 .key_hash = conn_key_hash, 486 .match = conn_match, 487 .equal = conn_equal, 463 488 .remove_callback = conn_remove 464 489 }; … … 715 740 716 741 atomic_set(&client->refcnt, 1); 717 hash_table_insert(&client_hash_table, key,&client->link);742 hash_table_insert(&client_hash_table, &client->link); 718 743 } 719 744 } … … 915 940 916 941 /* Add connection to the connection hash table */ 917 unsigned long key = conn->in_phone_hash;918 942 919 943 futex_down(&async_futex); 920 hash_table_insert(&conn_hash_table, & key, &conn->link);944 hash_table_insert(&conn_hash_table, &conn->link); 921 945 futex_up(&async_futex); 922 946 … … 1110 1134 void __async_init(void) 1111 1135 { 1112 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1113 2, &client_hash_table_ops)) 1136 if (!hash_table_create(&client_hash_table, 0, 2, &client_hash_table_ops)) 1114 1137 abort(); 1115 1138 1116 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1117 1, &conn_hash_table_ops)) 1139 if (!hash_table_create(&conn_hash_table, 0, 1, &conn_hash_table_ops)) 1118 1140 abort(); 1119 1141 -
uspace/lib/c/include/adt/hash_table.h
r1c1da4b r0ca7286 40 40 #include <bool.h> 41 41 42 typedef unsigned long hash_count_t;43 typedef unsigned long hash_index_t;44 42 45 43 /** Set of operations for hash table. */ 46 44 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 * 45 /** Returns the hash of the key stored in the item. 54 46 */ 55 hash_index_t (*hash)(unsigned long key[]);47 size_t (*hash)(const link_t *item); 56 48 57 /** Hash table item comparison function. 49 /** Returns the hash of the key. 50 */ 51 size_t (*key_hash)(unsigned long key[]); 52 53 /** Hash table item match function. 58 54 * 59 55 * @param key Array of keys that will be compared with item. It is … … 63 59 * 64 60 */ 65 int (*compare)(unsigned long key[], hash_count_t keys, link_t *item); 61 bool (*match)(unsigned long key[], size_t keys, const link_t *item); 62 63 /** 64 */ 65 bool (*equal)(const link_t *item1, const link_t *item2); 66 66 67 67 /** Hash table item removal callback. 68 * 69 * Must not invoke any mutating functions of the hash table. 68 70 * 69 71 * @param item Item that was removed from the hash table. 70 *71 72 */ 72 73 void (*remove_callback)(link_t *item); 73 } hash_table_op erations_t;74 } hash_table_ops_t; 74 75 75 76 /** Hash table structure. */ 76 77 typedef struct { 77 list_t *entry; 78 hash_count_t entries; 79 hash_count_t max_keys; 80 hash_table_operations_t *op; 78 list_t *bucket; 79 size_t bucket_cnt; 80 size_t max_keys; 81 size_t items; 82 hash_table_ops_t *op; 81 83 } hash_table_t; 82 84 … … 84 86 list_get_instance((item), type, member) 85 87 86 extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,87 hash_table_operations_t *);88 extern bool hash_table_create(hash_table_t *, size_t, size_t, 89 hash_table_ops_t *); 88 90 extern void hash_table_clear(hash_table_t *); 89 extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *); 91 extern void hash_table_insert(hash_table_t *, link_t *); 92 extern bool hash_table_insert_unique(hash_table_t *, link_t *); 90 93 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); 94 extern size_t hash_table_remove(hash_table_t *, unsigned long [], size_t); 95 extern void hash_table_remove_item(hash_table_t *, link_t *); 92 96 extern void hash_table_destroy(hash_table_t *); 93 extern void hash_table_apply(hash_table_t *, void (*)(link_t *, void *),94 97 extern void hash_table_apply(hash_table_t *, bool (*)(link_t *, void *), 98 void *); 95 99 96 100 #endif -
uspace/lib/c/include/adt/list.h
r1c1da4b r0ca7286 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 104 73 105 #define assert_link_not_used(link) \ 74 106 assert(((link)->prev == NULL) && ((link)->next == NULL)) -
uspace/lib/nic/include/nic_wol_virtues.h
r1c1da4b r0ca7286 51 51 * Operations for table 52 52 */ 53 hash_table_op erations_t table_operations;53 hash_table_ops_t table_operations; 54 54 /** 55 55 * WOL virtues hashed by their ID's. -
uspace/lib/nic/src/nic_wol_virtues.c
r1c1da4b r0ca7286 40 40 #include <errno.h> 41 41 42 #define NIC_WV_HASH_COUNT 32 43 44 /** 45 * Hash table helper function 46 */ 47 static int nic_wv_compare(unsigned long key[], hash_count_t keys, 48 link_t *item) 42 43 /* 44 * Hash table helper functions 45 */ 46 47 static size_t nic_wv_key_hash(unsigned long keys[]) 48 { 49 return keys[0]; 50 } 51 52 static size_t nic_wv_hash(const link_t *item) 53 { 54 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item; 55 unsigned long key = virtue->id; 56 return nic_wv_key_hash(&key); 57 } 58 59 static bool nic_wv_match(unsigned long key[], size_t keys, const link_t *item) 49 60 { 50 61 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item; … … 53 64 54 65 /** 55 * Hash table helper function56 */57 static void nic_wv_rc(link_t *item)58 {59 }60 61 /**62 * Hash table helper function63 */64 static hash_index_t nic_wv_hash(unsigned long keys[])65 {66 return keys[0] % NIC_WV_HASH_COUNT;67 }68 69 /**70 66 * Initializes the WOL virtues structure 71 67 * … … 77 73 int nic_wol_virtues_init(nic_wol_virtues_t *wvs) 78 74 { 79 bzero(wvs, sizeof (nic_wol_virtues_t)); 80 wvs->table_operations.compare = nic_wv_compare; 75 bzero(wvs, sizeof(nic_wol_virtues_t)); 81 76 wvs->table_operations.hash = nic_wv_hash; 82 wvs->table_operations.remove_callback = nic_wv_rc; 83 if (!hash_table_create(&wvs->table, NIC_WV_HASH_COUNT, 1, 84 &wvs->table_operations)) { 77 wvs->table_operations.key_hash = nic_wv_key_hash; 78 wvs->table_operations.match = nic_wv_match; 79 wvs->table_operations.equal = 0; 80 wvs->table_operations.remove_callback = 0; 81 82 if (!hash_table_create(&wvs->table, 0, 1, &wvs->table_operations)) { 85 83 return ENOMEM; 86 84 } … … 172 170 } while (NULL != 173 171 hash_table_find(&wvs->table, (unsigned long *) &virtue->id)); 174 hash_table_insert(&wvs->table, 175 (unsigned long *) &virtue->id, &virtue->item); 172 hash_table_insert(&wvs->table, &virtue->item); 176 173 virtue->next = wvs->lists[virtue->type]; 177 174 wvs->lists[virtue->type] = virtue; -
uspace/srv/devman/devman.c
r1c1da4b r0ca7286 66 66 /* hash table operations */ 67 67 68 static hash_index_t devices_hash(unsigned long key[]) 69 { 70 return key[0] % DEVICE_BUCKETS; 71 } 72 73 static int devman_devices_compare(unsigned long key[], hash_count_t keys, 74 link_t *item) 68 static size_t devices_key_hash(unsigned long key[]) 69 { 70 return key[0]; 71 } 72 73 static size_t devman_devices_hash(const link_t *item) 74 { 75 dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev); 76 unsigned long key = dev->handle; 77 return devices_key_hash(&key); 78 } 79 80 static size_t devman_functions_hash(const link_t *item) 81 { 82 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun); 83 unsigned long key = fun->handle; 84 return devices_key_hash(&key); 85 } 86 87 static size_t loc_functions_hash(const link_t *item) 88 { 89 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, loc_fun); 90 unsigned long key = fun->service_id; 91 return devices_key_hash(&key); 92 } 93 94 static bool devman_devices_match(unsigned long key[], size_t keys, 95 const link_t *item) 75 96 { 76 97 dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev); … … 78 99 } 79 100 80 static int devman_functions_compare(unsigned long key[], hash_count_t keys,81 link_t *item)101 static bool devman_functions_match(unsigned long key[], size_t keys, 102 const link_t *item) 82 103 { 83 104 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun); … … 85 106 } 86 107 87 static int loc_functions_compare(unsigned long key[], hash_count_t keys,88 link_t *item)108 static bool loc_functions_match(unsigned long key[], size_t keys, 109 const link_t *item) 89 110 { 90 111 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, loc_fun); … … 92 113 } 93 114 94 static void devices_remove_callback(link_t *item) 95 { 96 } 97 98 static hash_table_operations_t devman_devices_ops = { 99 .hash = devices_hash, 100 .compare = devman_devices_compare, 101 .remove_callback = devices_remove_callback 115 116 static hash_table_ops_t devman_devices_ops = { 117 .hash = devman_devices_hash, 118 .key_hash = devices_key_hash, 119 .match = devman_devices_match, 120 .equal = 0, 121 .remove_callback = 0 102 122 }; 103 123 104 static hash_table_operations_t devman_functions_ops = { 105 .hash = devices_hash, 106 .compare = devman_functions_compare, 107 .remove_callback = devices_remove_callback 124 static hash_table_ops_t devman_functions_ops = { 125 .hash = devman_functions_hash, 126 .key_hash = devices_key_hash, 127 .match = devman_functions_match, 128 .equal = 0, 129 .remove_callback = 0 108 130 }; 109 131 110 static hash_table_operations_t loc_devices_ops = { 111 .hash = devices_hash, 112 .compare = loc_functions_compare, 113 .remove_callback = devices_remove_callback 132 static hash_table_ops_t loc_devices_ops = { 133 .hash = loc_functions_hash, 134 .key_hash = devices_key_hash, 135 .match = loc_functions_match, 136 .equal = 0, 137 .remove_callback = 0 114 138 }; 115 139 … … 974 998 tree->current_handle = 0; 975 999 976 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, 977 &devman_devices_ops); 978 hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1, 979 &devman_functions_ops); 980 hash_table_create(&tree->loc_functions, DEVICE_BUCKETS, 1, 981 &loc_devices_ops); 1000 hash_table_create(&tree->devman_devices, 0, 1, &devman_devices_ops); 1001 hash_table_create(&tree->devman_functions, 0, 1, &devman_functions_ops); 1002 hash_table_create(&tree->loc_functions, 0, 1, &loc_devices_ops); 982 1003 983 1004 fibril_rwlock_initialize(&tree->rwlock); … … 1282 1303 /* Add the node to the handle-to-node map. */ 1283 1304 dev->handle = ++tree->current_handle; 1284 unsigned long key = dev->handle; 1285 hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev); 1305 hash_table_insert(&tree->devman_devices, &dev->devman_dev); 1286 1306 1287 1307 /* Add the node to the list of its parent's children. */ … … 1346 1366 /* Add the node to the handle-to-node map. */ 1347 1367 fun->handle = ++tree->current_handle; 1348 unsigned long key = fun->handle; 1349 hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun); 1368 hash_table_insert(&tree->devman_functions, &fun->devman_fun); 1350 1369 1351 1370 /* Add the node to the list of its parent's children. */ … … 1499 1518 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1500 1519 1501 unsigned long key = (unsigned long) fun->service_id; 1502 hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun); 1520 hash_table_insert(&tree->loc_functions, &fun->loc_fun); 1503 1521 } 1504 1522 -
uspace/srv/devman/devman.h
r1c1da4b r0ca7286 52 52 53 53 #define MATCH_EXT ".ma" 54 #define DEVICE_BUCKETS 25655 54 56 55 #define LOC_DEVICE_NAMESPACE "devices" -
uspace/srv/fs/cdfs/cdfs_ops.c
r1c1da4b r0ca7286 63 63 #define NODE_CACHE_SIZE 200 64 64 65 #define NODES_BUCKETS 25666 67 65 #define NODES_KEY_SRVC 0 68 66 #define NODES_KEY_INDEX 1 … … 226 224 static hash_table_t nodes; 227 225 228 static hash_index_t nodes_hash(unsigned long key[]) 229 { 230 return key[NODES_KEY_INDEX] % NODES_BUCKETS; 231 } 232 233 static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item) 234 { 235 cdfs_node_t *node = 236 hash_table_get_instance(item, cdfs_node_t, nh_link); 237 238 switch (keys) { 239 case 1: 226 static size_t nodes_key_hash(unsigned long key[]) 227 { 228 return key[NODES_KEY_INDEX]; 229 } 230 231 static size_t nodes_hash(const link_t *item) 232 { 233 cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link); 234 235 unsigned long key[] = { 236 [NODES_KEY_INDEX] = node->index 237 }; 238 239 return nodes_key_hash(key); 240 } 241 242 static bool nodes_match(unsigned long key[], size_t keys, const link_t *item) 243 { 244 cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link); 245 246 if (keys == 1) { 240 247 return (node->service_id == key[NODES_KEY_SRVC]); 241 case 2: 248 } else { 249 assert(keys == 2); 242 250 return ((node->service_id == key[NODES_KEY_SRVC]) && 243 251 (node->index == key[NODES_KEY_INDEX])); 244 default: 245 assert((keys == 1) || (keys == 2)); 246 } 247 248 return 0; 252 } 253 } 254 255 static bool nodes_equal(const link_t *item1, const link_t *item2) 256 { 257 cdfs_node_t *node1 = hash_table_get_instance(item1, cdfs_node_t, nh_link); 258 cdfs_node_t *node2 = hash_table_get_instance(item2, cdfs_node_t, nh_link); 259 260 return node1->service_id == node2->service_id 261 && node1->index == node2->index; 249 262 } 250 263 251 264 static void nodes_remove_callback(link_t *item) 252 265 { 253 cdfs_node_t *node = 254 hash_table_get_instance(item, cdfs_node_t, nh_link); 266 cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link); 255 267 256 268 assert(node->type == CDFS_DIRECTORY); … … 268 280 269 281 /** Nodes hash table operations */ 270 static hash_table_op erations_t nodes_ops = {282 static hash_table_ops_t nodes_ops = { 271 283 .hash = nodes_hash, 272 .compare = nodes_compare, 284 .key_hash = nodes_key_hash, 285 .match = nodes_match, 286 .equal = nodes_equal, 273 287 .remove_callback = nodes_remove_callback 274 288 }; … … 353 367 354 368 /* Insert the new node into the nodes hash table. */ 355 unsigned long key[] = { 356 [NODES_KEY_SRVC] = node->service_id, 357 [NODES_KEY_INDEX] = node->index 358 }; 359 360 hash_table_insert(&nodes, key, &node->nh_link); 369 hash_table_insert(&nodes, &node->nh_link); 361 370 362 371 *rfn = FS_NODE(node); … … 912 921 } 913 922 923 static bool cache_remove_closed(link_t *item, void *arg) 924 { 925 size_t *premove_cnt = (size_t*)arg; 926 927 /* Some nodes were requested to be removed from the cache. */ 928 if (0 < *premove_cnt) { 929 cdfs_node_t *node = hash_table_get_instance(item, cdfs_node_t, nh_link); 930 931 if (!node->opened) { 932 hash_table_remove_item(&nodes, item); 933 934 --nodes_cached; 935 --*premove_cnt; 936 } 937 } 938 939 /* Only continue if more nodes were requested to be removed. */ 940 return 0 < *premove_cnt; 941 } 942 914 943 static void cleanup_cache(service_id_t service_id) 915 944 { 916 945 if (nodes_cached > NODE_CACHE_SIZE) { 917 size_t remove = nodes_cached - NODE_CACHE_SIZE; 918 919 // FIXME: this accesses the internals of the hash table 920 // and should be rewritten in a clean way 921 922 for (hash_index_t chain = 0; chain < nodes.entries; chain++) { 923 for (link_t *link = nodes.entry[chain].head.next; 924 link != &nodes.entry[chain].head; 925 link = link->next) { 926 if (remove == 0) 927 return; 928 929 cdfs_node_t *node = 930 hash_table_get_instance(link, cdfs_node_t, nh_link); 931 if (node->opened == 0) { 932 link_t *tmp = link; 933 link = link->prev; 934 935 list_remove(tmp); 936 nodes.op->remove_callback(tmp); 937 nodes_cached--; 938 remove--; 939 940 continue; 941 } 942 } 943 } 946 size_t remove_cnt = nodes_cached - NODE_CACHE_SIZE; 947 948 if (0 < remove_cnt) 949 hash_table_apply(&nodes, cache_remove_closed, &remove_cnt); 944 950 } 945 951 } … … 1007 1013 bool cdfs_init(void) 1008 1014 { 1009 if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))1015 if (!hash_table_create(&nodes, 0, 2, &nodes_ops)) 1010 1016 return false; 1011 1017 -
uspace/srv/fs/exfat/exfat_idx.c
r1c1da4b r0ca7286 112 112 static hash_table_t up_hash; 113 113 114 #define UPH_BUCKETS_LOG 12115 #define UPH_BUCKETS (1 << UPH_BUCKETS_LOG)116 117 114 #define UPH_SID_KEY 0 118 115 #define UPH_PFC_KEY 1 119 116 #define UPH_PDI_KEY 2 120 117 121 static hash_index_t pos_hash(unsigned long key[]) 122 { 123 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; 124 exfat_cluster_t pfc = (exfat_cluster_t)key[UPH_PFC_KEY]; 125 unsigned pdi = (unsigned)key[UPH_PDI_KEY]; 126 127 hash_index_t h; 128 129 /* 130 * The least significant half of all bits are the least significant bits 131 * of the parent node's first cluster. 132 * 133 * The least significant half of the most significant half of all bits 134 * are the least significant bits of the node's dentry index within the 135 * parent directory node. 136 * 137 * The most significant half of the most significant half of all bits 138 * are the least significant bits of the device handle. 139 */ 140 h = pfc & ((1 << (UPH_BUCKETS_LOG / 2)) - 1); 141 h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << 142 (UPH_BUCKETS_LOG / 2); 143 h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << 144 (3 * (UPH_BUCKETS_LOG / 4)); 145 146 return h; 147 } 148 149 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item) 118 static size_t pos_key_hash(unsigned long key[]) 119 { 120 /* Inspired by Effective Java, 2nd edition. */ 121 size_t hash = 17; 122 123 hash = 31 * hash + key[UPH_PFC_KEY]; 124 hash = 31 * hash + key[UPH_PDI_KEY]; 125 hash = 31 * hash + key[UPH_SID_KEY]; 126 127 return hash; 128 } 129 130 static size_t pos_hash(const link_t *item) 131 { 132 exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uph_link); 133 134 unsigned long pkey[] = { 135 [UPH_SID_KEY] = fidx->service_id, 136 [UPH_PFC_KEY] = fidx->pfc, 137 [UPH_PDI_KEY] = fidx->pdi, 138 }; 139 140 return pos_key_hash(pkey); 141 } 142 143 static bool pos_match(unsigned long key[], size_t keys, const link_t *item) 150 144 { 151 145 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; … … 169 163 } 170 164 171 static void pos_remove_callback(link_t *item) 172 { 173 /* nothing to do */ 174 } 175 176 static hash_table_operations_t uph_ops = { 165 static hash_table_ops_t uph_ops = { 177 166 .hash = pos_hash, 178 .compare = pos_compare, 179 .remove_callback = pos_remove_callback, 167 .key_hash = pos_key_hash, 168 .match = pos_match, 169 .equal = 0, 170 .remove_callback = 0, 180 171 }; 181 172 … … 186 177 static hash_table_t ui_hash; 187 178 188 #define UIH_BUCKETS_LOG 12189 #define UIH_BUCKETS (1 << UIH_BUCKETS_LOG)190 191 179 #define UIH_SID_KEY 0 192 180 #define UIH_INDEX_KEY 1 193 181 194 static hash_index_t idx_hash(unsigned long key[])182 static size_t idx_key_hash(unsigned long key[]) 195 183 { 196 184 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; 197 185 fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; 198 186 199 hash_index_t h; 200 201 h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1); 202 h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) << 203 (UIH_BUCKETS_LOG / 2); 204 205 return h; 206 } 207 208 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item) 187 /* 188 * Compute a simple hash unlimited by specific table size as per: 189 * Effective Java, 2nd edition. 190 */ 191 size_t hash = 17; 192 hash = 31 * hash + (size_t)service_id; 193 hash = 31 * hash + (size_t)index; 194 return hash; 195 } 196 197 static size_t idx_hash(const link_t *item) 198 { 199 exfat_idx_t *fidx = list_get_instance(item, exfat_idx_t, uih_link); 200 201 unsigned long ikey[] = { 202 [UIH_SID_KEY] = fidx->service_id, 203 [UIH_INDEX_KEY] = fidx->index, 204 }; 205 206 return idx_key_hash(ikey); 207 } 208 209 static bool idx_match(unsigned long key[], size_t keys, const link_t *item) 209 210 { 210 211 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; … … 233 234 } 234 235 235 static hash_table_op erations_t uih_ops = {236 static hash_table_ops_t uih_ops = { 236 237 .hash = idx_hash, 237 .compare = idx_compare, 238 .key_hash = idx_key_hash, 239 .match = idx_match, 240 .equal = 0, 238 241 .remove_callback = idx_remove_callback, 239 242 }; … … 400 403 } 401 404 402 unsigned long ikey[] = { 403 [UIH_SID_KEY] = service_id, 404 [UIH_INDEX_KEY] = fidx->index, 405 }; 406 407 hash_table_insert(&ui_hash, ikey, &fidx->uih_link); 405 hash_table_insert(&ui_hash, &fidx->uih_link); 408 406 fibril_mutex_lock(&fidx->lock); 409 407 fibril_mutex_unlock(&used_lock); … … 437 435 } 438 436 439 unsigned long ikey[] = {440 [UIH_SID_KEY] = service_id,441 [UIH_INDEX_KEY] = fidx->index,442 };443 444 437 fidx->pfc = pfc; 445 438 fidx->pdi = pdi; 446 439 447 hash_table_insert(&up_hash, pkey,&fidx->uph_link);448 hash_table_insert(&ui_hash, ikey,&fidx->uih_link);440 hash_table_insert(&up_hash, &fidx->uph_link); 441 hash_table_insert(&ui_hash, &fidx->uih_link); 449 442 } 450 443 fibril_mutex_lock(&fidx->lock); … … 456 449 void exfat_idx_hashin(exfat_idx_t *idx) 457 450 { 458 unsigned long pkey[] = { 459 [UPH_SID_KEY] = idx->service_id, 460 [UPH_PFC_KEY] = idx->pfc, 461 [UPH_PDI_KEY] = idx->pdi, 462 }; 463 464 fibril_mutex_lock(&used_lock); 465 hash_table_insert(&up_hash, pkey, &idx->uph_link); 451 fibril_mutex_lock(&used_lock); 452 hash_table_insert(&up_hash, &idx->uph_link); 466 453 fibril_mutex_unlock(&used_lock); 467 454 } … … 532 519 int exfat_idx_init(void) 533 520 { 534 if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops))521 if (!hash_table_create(&up_hash, 0, 3, &uph_ops)) 535 522 return ENOMEM; 536 if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) {523 if (!hash_table_create(&ui_hash, 0, 2, &uih_ops)) { 537 524 hash_table_destroy(&up_hash); 538 525 return ENOMEM; -
uspace/srv/fs/ext2fs/ext2fs_ops.c
r1c1da4b r0ca7286 65 65 #define OPEN_NODES_DEV_HANDLE_KEY 0 66 66 #define OPEN_NODES_INODE_KEY 1 67 #define OPEN_NODES_BUCKETS 25668 67 69 68 typedef struct ext2fs_instance { … … 123 122 124 123 /* Hash table interface for open nodes hash table */ 125 static hash_index_t open_nodes_hash(unsigned long key[]) 126 { 127 /* TODO: This is very simple and probably can be improved */ 128 return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS; 129 } 130 131 static int open_nodes_compare(unsigned long key[], hash_count_t keys, 132 link_t *item) 124 static size_t open_nodes_key_hash(unsigned long key[]) 125 { 126 /* Hash construction recommended in Effective Java, 2nd Edition. */ 127 size_t hash = 17; 128 hash = 31 * hash + key[OPEN_NODES_DEV_HANDLE_KEY]; 129 hash = 31 * hash + key[OPEN_NODES_INODE_KEY]; 130 return hash; 131 } 132 133 static size_t open_nodes_hash(const link_t *item) 134 { 135 ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link); 136 137 assert(enode->instance); 138 assert(enode->inode_ref); 139 140 unsigned long key[] = { 141 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id, 142 [OPEN_NODES_INODE_KEY] = enode->inode_ref->index, 143 }; 144 145 return open_nodes_key_hash(key); 146 } 147 148 static bool open_nodes_match(unsigned long key[], size_t keys, 149 const link_t *item) 133 150 { 134 151 ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link); … … 145 162 } 146 163 147 static void open_nodes_remove_cb(link_t *link) 148 { 149 /* We don't use remove callback for this hash table */ 150 } 151 152 static hash_table_operations_t open_nodes_ops = { 164 static hash_table_ops_t open_nodes_ops = { 153 165 .hash = open_nodes_hash, 154 .compare = open_nodes_compare, 155 .remove_callback = open_nodes_remove_cb, 166 .key_hash = open_nodes_key_hash, 167 .match = open_nodes_match, 168 .equal = 0, 169 .remove_callback = 0, 156 170 }; 157 171 … … 161 175 int ext2fs_global_init(void) 162 176 { 163 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 164 OPEN_NODES_KEYS, &open_nodes_ops)) { 177 if (!hash_table_create(&open_nodes, 0, OPEN_NODES_KEYS, &open_nodes_ops)) { 165 178 return ENOMEM; 166 179 } … … 362 375 *rfn = node; 363 376 364 hash_table_insert(&open_nodes, key,&enode->link);377 hash_table_insert(&open_nodes, &enode->link); 365 378 inst->open_nodes_count++; 366 379 -
uspace/srv/fs/fat/fat_idx.c
r1c1da4b r0ca7286 46 46 #include <malloc.h> 47 47 48 48 49 /** Each instance of this type describes one interval of freed VFS indices. */ 49 50 typedef struct { … … 113 114 static hash_table_t up_hash; 114 115 115 #define UPH_BUCKETS_LOG 12116 #define UPH_BUCKETS (1 << UPH_BUCKETS_LOG)117 118 116 #define UPH_SID_KEY 0 119 117 #define UPH_PFC_KEY 1 120 118 #define UPH_PDI_KEY 2 121 119 122 static hash_index_t pos_hash(unsigned long key[]) 123 { 124 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; 125 fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY]; 126 unsigned pdi = (unsigned)key[UPH_PDI_KEY]; 127 128 hash_index_t h; 129 130 /* 131 * The least significant half of all bits are the least significant bits 132 * of the parent node's first cluster. 133 * 134 * The least significant half of the most significant half of all bits 135 * are the least significant bits of the node's dentry index within the 136 * parent directory node. 137 * 138 * The most significant half of the most significant half of all bits 139 * are the least significant bits of the device handle. 140 */ 141 h = pfc & ((1 << (UPH_BUCKETS_LOG / 2)) - 1); 142 h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << 143 (UPH_BUCKETS_LOG / 2); 144 h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) << 145 (3 * (UPH_BUCKETS_LOG / 4)); 146 147 return h; 148 } 149 150 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item) 120 static size_t pos_key_hash(unsigned long key[]) 121 { 122 /* Inspired by Effective Java, 2nd edition. */ 123 size_t hash = 17; 124 125 hash = 31 * hash + key[UPH_PFC_KEY]; 126 hash = 31 * hash + key[UPH_PDI_KEY]; 127 hash = 31 * hash + key[UPH_SID_KEY]; 128 129 return hash; 130 } 131 132 static size_t pos_hash(const link_t *item) 133 { 134 fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uph_link); 135 136 unsigned long pkey[] = { 137 [UPH_SID_KEY] = fidx->service_id, 138 [UPH_PFC_KEY] = fidx->pfc, 139 [UPH_PDI_KEY] = fidx->pdi, 140 }; 141 142 return pos_key_hash(pkey); 143 } 144 145 static bool pos_match(unsigned long key[], size_t keys, const link_t *item) 151 146 { 152 147 service_id_t service_id = (service_id_t)key[UPH_SID_KEY]; … … 170 165 } 171 166 172 static void pos_remove_callback(link_t *item) 173 { 174 /* nothing to do */ 175 } 176 177 static hash_table_operations_t uph_ops = { 167 static hash_table_ops_t uph_ops = { 178 168 .hash = pos_hash, 179 .compare = pos_compare, 180 .remove_callback = pos_remove_callback, 169 .key_hash = pos_key_hash, 170 .match = pos_match, 171 .equal = 0, 172 .remove_callback = 0, 181 173 }; 182 174 … … 187 179 static hash_table_t ui_hash; 188 180 189 #define UIH_BUCKETS_LOG 12190 #define UIH_BUCKETS (1 << UIH_BUCKETS_LOG)191 192 181 #define UIH_SID_KEY 0 193 182 #define UIH_INDEX_KEY 1 194 183 195 static hash_index_t idx_hash(unsigned long key[]) 196 { 197 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; 198 fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY]; 199 200 hash_index_t h; 201 202 h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1); 203 h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) << 204 (UIH_BUCKETS_LOG / 2); 205 206 return h; 207 } 208 209 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item) 184 static size_t idx_key_hash(unsigned long key[]) 185 { 186 /* 187 * Compute a simple hash unlimited by specific table size as per: 188 * Effective Java, 2nd edition. 189 */ 190 size_t hash = 17; 191 hash = 31 * hash + key[UIH_SID_KEY]; 192 hash = 31 * hash + key[UIH_INDEX_KEY]; 193 return hash; 194 } 195 196 static size_t idx_hash(const link_t *item) 197 { 198 fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link); 199 200 unsigned long ikey[] = { 201 [UIH_SID_KEY] = fidx->service_id, 202 [UIH_INDEX_KEY] = fidx->index, 203 }; 204 205 return idx_key_hash(ikey); 206 } 207 208 static bool idx_match(unsigned long key[], size_t keys, const link_t *item) 210 209 { 211 210 service_id_t service_id = (service_id_t)key[UIH_SID_KEY]; … … 234 233 } 235 234 236 static hash_table_op erations_t uih_ops = {235 static hash_table_ops_t uih_ops = { 237 236 .hash = idx_hash, 238 .compare = idx_compare, 237 .key_hash = idx_key_hash, 238 .match = idx_match, 239 .equal = 0, 239 240 .remove_callback = idx_remove_callback, 240 241 }; … … 401 402 } 402 403 403 unsigned long ikey[] = { 404 [UIH_SID_KEY] = service_id, 405 [UIH_INDEX_KEY] = fidx->index, 406 }; 407 408 hash_table_insert(&ui_hash, ikey, &fidx->uih_link); 404 hash_table_insert(&ui_hash, &fidx->uih_link); 409 405 fibril_mutex_lock(&fidx->lock); 410 406 fibril_mutex_unlock(&used_lock); … … 438 434 } 439 435 440 unsigned long ikey[] = {441 [UIH_SID_KEY] = service_id,442 [UIH_INDEX_KEY] = fidx->index,443 };444 445 436 fidx->pfc = pfc; 446 437 fidx->pdi = pdi; 447 438 448 hash_table_insert(&up_hash, pkey,&fidx->uph_link);449 hash_table_insert(&ui_hash, ikey,&fidx->uih_link);439 hash_table_insert(&up_hash, &fidx->uph_link); 440 hash_table_insert(&ui_hash, &fidx->uih_link); 450 441 } 451 442 fibril_mutex_lock(&fidx->lock); … … 457 448 void fat_idx_hashin(fat_idx_t *idx) 458 449 { 459 unsigned long pkey[] = { 460 [UPH_SID_KEY] = idx->service_id, 461 [UPH_PFC_KEY] = idx->pfc, 462 [UPH_PDI_KEY] = idx->pdi, 463 }; 464 465 fibril_mutex_lock(&used_lock); 466 hash_table_insert(&up_hash, pkey, &idx->uph_link); 450 fibril_mutex_lock(&used_lock); 451 hash_table_insert(&up_hash, &idx->uph_link); 467 452 fibril_mutex_unlock(&used_lock); 468 453 } … … 470 455 void fat_idx_hashout(fat_idx_t *idx) 471 456 { 472 unsigned long pkey[] = { 473 [UPH_SID_KEY] = idx->service_id, 474 [UPH_PFC_KEY] = idx->pfc, 475 [UPH_PDI_KEY] = idx->pdi, 476 }; 477 478 fibril_mutex_lock(&used_lock); 479 hash_table_remove(&up_hash, pkey, 3); 457 fibril_mutex_lock(&used_lock); 458 hash_table_remove_item(&up_hash, &idx->uph_link); 480 459 fibril_mutex_unlock(&used_lock); 481 460 } … … 532 511 int fat_idx_init(void) 533 512 { 534 if (!hash_table_create(&up_hash, UPH_BUCKETS, 3, &uph_ops))513 if (!hash_table_create(&up_hash, 0, 3, &uph_ops)) 535 514 return ENOMEM; 536 if (!hash_table_create(&ui_hash, UIH_BUCKETS, 2, &uih_ops)) {515 if (!hash_table_create(&ui_hash, 0, 2, &uih_ops)) { 537 516 hash_table_destroy(&up_hash); 538 517 return ENOMEM; -
uspace/srv/fs/locfs/locfs_ops.c
r1c1da4b r0ca7286 73 73 #define SERVICES_KEYS 1 74 74 #define SERVICES_KEY_HANDLE 0 75 #define SERVICES_BUCKETS 25676 75 77 76 /* Implementation of hash table interface for the nodes hash table. */ 78 static hash_index_t services_hash(unsigned long key[]) 79 { 80 return key[SERVICES_KEY_HANDLE] % SERVICES_BUCKETS; 81 } 82 83 static int services_compare(unsigned long key[], hash_count_t keys, link_t *item) 84 { 77 78 static size_t services_key_hash(unsigned long key[]) 79 { 80 return key[SERVICES_KEY_HANDLE]; 81 } 82 83 static size_t services_hash(const link_t *item) 84 { 85 service_t *dev = hash_table_get_instance(item, service_t, link); 86 unsigned long key[] = { 87 [SERVICES_KEY_HANDLE] = dev->service_id 88 }; 89 90 return services_key_hash(key); 91 } 92 93 static bool services_match(unsigned long key[], size_t keys, const link_t *item) 94 { 95 assert(keys == 1); 85 96 service_t *dev = hash_table_get_instance(item, service_t, link); 86 97 return (dev->service_id == (service_id_t) key[SERVICES_KEY_HANDLE]); … … 92 103 } 93 104 94 static hash_table_op erations_t services_ops = {105 static hash_table_ops_t services_ops = { 95 106 .hash = services_hash, 96 .compare = services_compare, 107 .key_hash = services_key_hash, 108 .match = services_match, 109 .equal = 0, 97 110 .remove_callback = services_remove_callback 98 111 }; … … 256 269 * below. 257 270 */ 258 hash_table_insert(&services, key,&dev->link);271 hash_table_insert(&services, &dev->link); 259 272 260 273 /* … … 450 463 bool locfs_init(void) 451 464 { 452 if (!hash_table_create(&services, SERVICES_BUCKETS, 453 SERVICES_KEYS, &services_ops)) 465 if (!hash_table_create(&services, 0, SERVICES_KEYS, &services_ops)) 454 466 return false; 455 467 -
uspace/srv/fs/mfs/mfs_ops.c
r1c1da4b r0ca7286 40 40 #define OPEN_NODES_SERVICE_KEY 0 41 41 #define OPEN_NODES_INODE_KEY 1 42 #define OPEN_NODES_BUCKETS 25643 42 44 43 static bool check_magic_number(uint16_t magic, bool *native, … … 61 60 static int mfs_unlink(fs_node_t *, fs_node_t *, const char *name); 62 61 static int mfs_destroy_node(fs_node_t *fn); 63 static hash_index_t open_nodes_hash(unsigned long key[]);64 static int open_nodes_compare(unsigned long key[], hash_count_t keys,65 link_t *item); 66 static void open_nodes_remove_cb(link_t *link);62 static size_t open_nodes_hash(const link_t *item); 63 static size_t open_nodes_key_hash(unsigned long key[]); 64 static bool open_nodes_match(unsigned long key[], size_t keys, 65 const link_t *item); 67 66 static int mfs_node_get(fs_node_t **rfn, service_id_t service_id, 68 67 fs_index_t index); … … 95 94 96 95 /* Hash table interface for open nodes hash table */ 97 static hash_index_t 98 open_nodes_hash(unsigned long key[]) 99 { 100 /* TODO: This is very simple and probably can be improved */ 101 return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS; 102 } 103 104 static int 105 open_nodes_compare(unsigned long key[], hash_count_t keys, 106 link_t *item) 107 { 96 97 static size_t 98 open_nodes_key_hash(unsigned long key[]) 99 { 100 /* As recommended by Effective Java, 2nd Edition. */ 101 size_t hash = 17; 102 hash = 37 * hash + key[OPEN_NODES_SERVICE_KEY]; 103 hash = 37 * hash + key[OPEN_NODES_INODE_KEY]; 104 return hash; 105 } 106 107 static size_t 108 open_nodes_hash(const link_t *item) 109 { 110 struct mfs_node *m = hash_table_get_instance(item, struct mfs_node, link); 111 112 unsigned long key[] = { 113 [OPEN_NODES_SERVICE_KEY] = m->instance->service_id, 114 [OPEN_NODES_INODE_KEY] = m->ino_i->index, 115 }; 116 117 return open_nodes_key_hash(key); 118 } 119 120 static bool 121 open_nodes_match(unsigned long key[], size_t keys, const link_t *item) 122 { 123 assert(keys == 2); 108 124 struct mfs_node *mnode = hash_table_get_instance(item, struct mfs_node, link); 109 assert(keys > 0); 110 if (mnode->instance->service_id != 111 ((service_id_t) key[OPEN_NODES_SERVICE_KEY])) { 112 return false; 113 } 114 if (keys == 1) { 115 return true; 116 } 117 assert(keys == 2); 118 return (mnode->ino_i->index == key[OPEN_NODES_INODE_KEY]); 119 } 120 121 static void 122 open_nodes_remove_cb(link_t *link) 123 { 124 /* We don't use remove callback for this hash table */ 125 } 126 127 static hash_table_operations_t open_nodes_ops = { 125 126 service_id_t service_id = ((service_id_t) key[OPEN_NODES_SERVICE_KEY]); 127 128 return mnode->instance->service_id == service_id 129 && mnode->ino_i->index == key[OPEN_NODES_INODE_KEY]; 130 } 131 132 133 static hash_table_ops_t open_nodes_ops = { 128 134 .hash = open_nodes_hash, 129 .compare = open_nodes_compare, 130 .remove_callback = open_nodes_remove_cb, 135 .key_hash = open_nodes_key_hash, 136 .match = open_nodes_match, 137 .equal = 0, 138 .remove_callback = 0, 131 139 }; 132 140 … … 134 142 mfs_global_init(void) 135 143 { 136 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 137 OPEN_NODES_KEYS, &open_nodes_ops)) { 144 if (!hash_table_create(&open_nodes, 0, OPEN_NODES_KEYS, &open_nodes_ops)) { 138 145 return ENOMEM; 139 146 } … … 408 415 link_initialize(&mnode->link); 409 416 410 unsigned long key[] = {411 [OPEN_NODES_SERVICE_KEY] = inst->service_id,412 [OPEN_NODES_INODE_KEY] = inum,413 };414 415 417 fibril_mutex_lock(&open_nodes_lock); 416 hash_table_insert(&open_nodes, key,&mnode->link);418 hash_table_insert(&open_nodes, &mnode->link); 417 419 fibril_mutex_unlock(&open_nodes_lock); 418 420 inst->open_nodes_cnt++; … … 621 623 *rfn = node; 622 624 623 hash_table_insert(&open_nodes, key,&mnode->link);625 hash_table_insert(&open_nodes, &mnode->link); 624 626 inst->open_nodes_cnt++; 625 627 -
uspace/srv/fs/tmpfs/tmpfs_ops.c
r1c1da4b r0ca7286 56 56 #define max(a, b) ((a) > (b) ? (a) : (b)) 57 57 58 #define NODES_BUCKETS 25659 60 58 /** All root nodes have index 0. */ 61 59 #define TMPFS_SOME_ROOT 0 … … 146 144 147 145 /* Implementation of hash table interface for the nodes hash table. */ 148 static hash_index_t nodes_hash(unsigned long key[]) 149 { 150 return key[NODES_KEY_INDEX] % NODES_BUCKETS; 151 } 152 153 static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item) 146 static size_t nodes_key_hash(unsigned long key[]) 147 { 148 /* Based on Effective Java, 2nd Edition. */ 149 size_t hash = 17; 150 hash = 37 * hash + key[NODES_KEY_DEV]; 151 hash = 37 * hash + key[NODES_KEY_INDEX]; 152 return hash; 153 } 154 155 static size_t nodes_hash(const link_t *item) 156 { 157 tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t, nh_link); 158 159 unsigned long key[] = { 160 [NODES_KEY_DEV] = nodep->service_id, 161 [NODES_KEY_INDEX] = nodep->index 162 }; 163 164 return nodes_key_hash(key); 165 } 166 167 static bool nodes_match(unsigned long key[], size_t keys, const link_t *item) 154 168 { 155 169 tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t, … … 192 206 193 207 /** TMPFS nodes hash table operations. */ 194 hash_table_op erations_t nodes_ops = {208 hash_table_ops_t nodes_ops = { 195 209 .hash = nodes_hash, 196 .compare = nodes_compare, 210 .key_hash = nodes_key_hash, 211 .match = nodes_match, 212 .equal = 0, 197 213 .remove_callback = nodes_remove_callback 198 214 }; … … 220 236 bool tmpfs_init(void) 221 237 { 222 if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))238 if (!hash_table_create(&nodes, 0, 2, &nodes_ops)) 223 239 return false; 224 240 … … 331 347 332 348 /* Insert the new node into the nodes hash table. */ 333 unsigned long key[] = { 334 [NODES_KEY_DEV] = nodep->service_id, 335 [NODES_KEY_INDEX] = nodep->index 336 }; 337 hash_table_insert(&nodes, key, &nodep->nh_link); 349 hash_table_insert(&nodes, &nodep->nh_link); 338 350 *rfn = FS_NODE(nodep); 339 351 return EOK; -
uspace/srv/hid/input/generic/gsp.c
r1c1da4b r0ca7286 54 54 #include <stdio.h> 55 55 56 #define TRANS_TABLE_CHAINS 25657 58 56 /* 59 57 * Hash table operations for the transition function. 60 58 */ 61 59 62 static hash_index_t trans_op_hash(unsigned long key[]); 63 static int trans_op_compare(unsigned long key[], hash_count_t keys, 64 link_t *item); 65 static void trans_op_remove_callback(link_t *item); 66 67 static hash_table_operations_t trans_ops = { 60 static size_t trans_op_hash(const link_t *item); 61 static size_t trans_op_key_hash(unsigned long key[]); 62 static bool trans_op_match(unsigned long key[], size_t keys, const link_t *item); 63 64 static hash_table_ops_t trans_ops = { 68 65 .hash = trans_op_hash, 69 .compare = trans_op_compare, 70 .remove_callback = trans_op_remove_callback 66 .key_hash = trans_op_key_hash, 67 .match = trans_op_match, 68 .equal = 0, 69 .remove_callback = 0 71 70 }; 72 71 … … 75 74 static gsp_trans_t *trans_new(void); 76 75 77 /** Initiali se scancode parser. */76 /** Initialize scancode parser. */ 78 77 void gsp_init(gsp_t *p) 79 78 { 80 79 p->states = 1; 81 hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);80 hash_table_create(&p->trans, 0, 2, &trans_ops); 82 81 } 83 82 … … 242 241 static void trans_insert(gsp_t *p, gsp_trans_t *t) 243 242 { 244 unsigned long key[2]; 245 246 key[0] = t->old_state; 247 key[1] = t->input; 248 249 hash_table_insert(&p->trans, key, &t->link); 243 hash_table_insert(&p->trans, &t->link); 250 244 } 251 245 … … 268 262 */ 269 263 270 static hash_index_t trans_op_hash(unsigned long key[]) 271 { 272 return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS; 273 } 274 275 static int trans_op_compare(unsigned long key[], hash_count_t keys, 276 link_t *item) 277 { 278 gsp_trans_t *t; 279 280 t = hash_table_get_instance(item, gsp_trans_t, link); 264 static size_t trans_op_key_hash(unsigned long key[]) 265 { 266 return (key[0] * 17 + key[1]); 267 } 268 269 static size_t trans_op_hash(const link_t *item) 270 { 271 gsp_trans_t *t = hash_table_get_instance(item, gsp_trans_t, link); 272 unsigned long key[] = { 273 t->old_state, 274 t->input 275 }; 276 277 return trans_op_key_hash(key); 278 } 279 280 static bool trans_op_match(unsigned long key[], size_t keys, const link_t *item) 281 { 282 gsp_trans_t *t = hash_table_get_instance(item, gsp_trans_t, link); 281 283 return ((key[0] == (unsigned long) t->old_state) 282 284 && (key[1] == (unsigned long) t->input)); 283 }284 285 static void trans_op_remove_callback(link_t *item)286 {287 285 } 288 286 -
uspace/srv/ns/service.c
r1c1da4b r0ca7286 40 40 #include "ns.h" 41 41 42 #define SERVICE_HASH_TABLE_CHAINS 2043 42 44 43 /** Service hash table item. */ … … 58 57 * 59 58 */ 60 static hash_index_t service_hash(unsigned long key[])59 static size_t service_key_hash(unsigned long key[]) 61 60 { 62 61 assert(key); 63 return (key[0] % SERVICE_HASH_TABLE_CHAINS); 62 return key[0]; 63 } 64 65 static size_t service_hash(const link_t *item) 66 { 67 hashed_service_t *hs = hash_table_get_instance(item, hashed_service_t, link); 68 unsigned long key = hs->service; 69 return service_key_hash(&key); 64 70 } 65 71 … … 79 85 * 80 86 */ 81 static int service_compare(unsigned long key[], hash_count_t keys,link_t *item)87 static bool service_match(unsigned long key[], size_t keys, const link_t *item) 82 88 { 83 89 assert(key); … … 105 111 106 112 /** Operations for service hash table. */ 107 static hash_table_op erations_t service_hash_table_ops = {113 static hash_table_ops_t service_hash_table_ops = { 108 114 .hash = service_hash, 109 .compare = service_compare, 115 .key_hash = service_key_hash, 116 .match = service_match, 117 .equal = 0, 110 118 .remove_callback = service_remove 111 119 }; … … 127 135 int service_init(void) 128 136 { 129 if (!hash_table_create(&service_hash_table, SERVICE_HASH_TABLE_CHAINS, 130 3, &service_hash_table_ops)) { 137 if (!hash_table_create(&service_hash_table, 0, 3, &service_hash_table_ops)) { 131 138 printf(NAME ": No memory available for services\n"); 132 139 return ENOMEM; … … 193 200 hs->phone = phone; 194 201 hs->in_phone_hash = call->in_phone_hash; 195 hash_table_insert(&service_hash_table, keys,&hs->link);202 hash_table_insert(&service_hash_table, &hs->link); 196 203 197 204 return EOK; -
uspace/srv/ns/task.c
r1c1da4b r0ca7286 43 43 #include "ns.h" 44 44 45 #define TASK_HASH_TABLE_CHAINS 25646 #define P2I_HASH_TABLE_CHAINS 25647 45 48 46 /* TODO: … … 71 69 * 72 70 */ 73 static hash_index_t task_hash(unsigned long key[]) 74 { 75 assert(key); 76 return (LOWER32(key[0]) % TASK_HASH_TABLE_CHAINS); 71 static size_t task_key_hash(unsigned long key[]) 72 { 73 size_t hash = 17; 74 hash = 37 * hash + key[1]; 75 hash = 37 * hash + key[0]; 76 return hash; 77 } 78 79 static size_t task_hash(const link_t *item) 80 { 81 hashed_task_t *ht = hash_table_get_instance(item, hashed_task_t, link); 82 83 unsigned long key[] = { 84 LOWER32(ht->id), 85 UPPER32(ht->id) 86 }; 87 88 return task_key_hash(key); 77 89 } 78 90 … … 86 98 * 87 99 */ 88 static int task_compare(unsigned long key[], hash_count_t keys,link_t *item)100 static bool task_match(unsigned long key[], size_t keys, const link_t *item) 89 101 { 90 102 assert(key); 91 assert(keys <= 2);103 assert(keys == 2); 92 104 assert(item); 93 105 94 106 hashed_task_t *ht = hash_table_get_instance(item, hashed_task_t, link); 95 107 96 if (keys == 2) 97 return ((LOWER32(key[1]) == UPPER32(ht->id)) 98 && (LOWER32(key[0]) == LOWER32(ht->id))); 99 else 100 return (LOWER32(key[0]) == LOWER32(ht->id)); 108 return (key[0] == LOWER32(ht->id)) 109 && (key[1] == UPPER32(ht->id)); 101 110 } 102 111 … … 113 122 114 123 /** Operations for task hash table. */ 115 static hash_table_op erations_t task_hash_table_ops = {124 static hash_table_ops_t task_hash_table_ops = { 116 125 .hash = task_hash, 117 .compare = task_compare, 126 .key_hash = task_key_hash, 127 .match = task_match, 128 .equal = 0, 118 129 .remove_callback = task_remove 119 130 }; … … 135 146 * 136 147 */ 137 static hash_index_t p2i_hash(unsigned long key[])148 static size_t p2i_key_hash(unsigned long key[]) 138 149 { 139 150 assert(key); 140 return (key[0] % TASK_HASH_TABLE_CHAINS); 151 return key[0]; 152 } 153 154 static size_t p2i_hash(const link_t *item) 155 { 156 p2i_entry_t *entry = hash_table_get_instance(item, p2i_entry_t, link); 157 unsigned long key = entry->in_phone_hash; 158 return p2i_key_hash(&key); 141 159 } 142 160 … … 150 168 * 151 169 */ 152 static int p2i_compare(unsigned long key[], hash_count_t keys,link_t *item)170 static bool p2i_match(unsigned long key[], size_t keys, const link_t *item) 153 171 { 154 172 assert(key); … … 173 191 174 192 /** Operations for task hash table. */ 175 static hash_table_op erations_t p2i_ops = {193 static hash_table_ops_t p2i_ops = { 176 194 .hash = p2i_hash, 177 .compare = p2i_compare, 195 .key_hash = p2i_key_hash, 196 .match = p2i_match, 197 .equal = 0, 178 198 .remove_callback = p2i_remove 179 199 }; … … 193 213 int task_init(void) 194 214 { 195 if (!hash_table_create(&task_hash_table, TASK_HASH_TABLE_CHAINS, 196 2, &task_hash_table_ops)) { 215 if (!hash_table_create(&task_hash_table, 0, 2, &task_hash_table_ops)) { 197 216 printf(NAME ": No memory available for tasks\n"); 198 217 return ENOMEM; 199 218 } 200 219 201 if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS, 202 1, &p2i_ops)) { 220 if (!hash_table_create(&phone_to_id, 0, 1, &p2i_ops)) { 203 221 printf(NAME ": No memory available for tasks\n"); 204 222 return ENOMEM; … … 293 311 int ns_task_id_intro(ipc_call_t *call) 294 312 { 295 unsigned long keys[2];296 313 297 314 task_id_t id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call)); 298 keys[0] = call->in_phone_hash; 315 316 unsigned long keys[] = { call->in_phone_hash }; 299 317 300 318 link_t *link = hash_table_find(&phone_to_id, keys); … … 317 335 entry->in_phone_hash = call->in_phone_hash; 318 336 entry->id = id; 319 hash_table_insert(&phone_to_id, keys,&entry->link);337 hash_table_insert(&phone_to_id, &entry->link); 320 338 321 339 /* 322 340 * Insert into the main table. 323 341 */ 324 325 keys[0] = LOWER32(id);326 keys[1] = UPPER32(id);327 342 328 343 link_initialize(&ht->link); … … 331 346 ht->have_rval = false; 332 347 ht->retval = -1; 333 hash_table_insert(&task_hash_table, keys,&ht->link);348 hash_table_insert(&task_hash_table, &ht->link); 334 349 335 350 return EOK; -
uspace/srv/vfs/vfs_node.c
r1c1da4b r0ca7286 58 58 #define KEY_INDEX 2 59 59 60 static hash_index_t nodes_hash(unsigned long []);61 static int nodes_compare(unsigned long [], hash_count_t,link_t *);62 static void nodes_remove_callback(link_t *);60 static size_t nodes_key_hash(unsigned long []); 61 static size_t nodes_hash(const link_t *); 62 static bool nodes_match(unsigned long [], size_t, const link_t *); 63 63 64 64 /** VFS node hash table operations. */ 65 hash_table_op erations_t nodes_ops = {65 hash_table_ops_t nodes_ops = { 66 66 .hash = nodes_hash, 67 .compare = nodes_compare, 68 .remove_callback = nodes_remove_callback 67 .key_hash = nodes_key_hash, 68 .match = nodes_match, 69 .equal = 0, 70 .remove_callback = 0, 69 71 }; 70 72 … … 75 77 bool vfs_nodes_init(void) 76 78 { 77 return hash_table_create(&nodes, NODES_BUCKETS, 3, &nodes_ops);79 return hash_table_create(&nodes, 0, 3, &nodes_ops); 78 80 } 79 81 … … 207 209 link_initialize(&node->nh_link); 208 210 fibril_rwlock_initialize(&node->contents_rwlock); 209 hash_table_insert(&nodes, key,&node->nh_link);211 hash_table_insert(&nodes, &node->nh_link); 210 212 } else { 211 213 node = hash_table_get_instance(tmp, vfs_node_t, nh_link); … … 240 242 } 241 243 242 hash_index_t nodes_hash(unsigned long key[]) 243 { 244 hash_index_t a = key[KEY_FS_HANDLE] << (NODES_BUCKETS_LOG / 4); 245 hash_index_t b = (a | key[KEY_DEV_HANDLE]) << (NODES_BUCKETS_LOG / 2); 246 247 return (b | key[KEY_INDEX]) & (NODES_BUCKETS - 1); 248 } 249 250 int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item) 244 size_t nodes_key_hash(unsigned long key[]) 245 { 246 /* Combine into a hash like they do in Effective Java, 2nd edition. */ 247 size_t hash = 17; 248 hash = 37 * hash + key[KEY_FS_HANDLE]; 249 hash = 37 * hash + key[KEY_DEV_HANDLE]; 250 hash = 37 * hash + key[KEY_INDEX]; 251 return hash; 252 } 253 254 size_t nodes_hash(const link_t *item) 255 { 256 vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link); 257 258 unsigned long key[] = { 259 [KEY_FS_HANDLE] = node->fs_handle, 260 [KEY_DEV_HANDLE] = node->service_id, 261 [KEY_INDEX] = node->index 262 }; 263 264 return nodes_key_hash(key); 265 } 266 267 268 bool nodes_match(unsigned long key[], size_t keys, const link_t *item) 251 269 { 252 270 vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link); … … 256 274 } 257 275 258 void nodes_remove_callback(link_t *item)259 {260 }261 276 262 277 struct refcnt_data { … … 267 282 }; 268 283 269 static voidrefcnt_visitor(link_t *item, void *arg)284 static bool refcnt_visitor(link_t *item, void *arg) 270 285 { 271 286 vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link); … … 275 290 (node->service_id == rd->service_id)) 276 291 rd->refcnt += node->refcnt; 292 293 return true; 277 294 } 278 295
Note:
See TracChangeset
for help on using the changeset viewer.