Changeset bc216a0 in mainline for uspace/lib
- Timestamp:
- 2012-08-07T22:13:44Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- da68871a
- Parents:
- b17518e
- Location:
- uspace/lib
- Files:
-
- 1 added
- 9 edited
-
block/libblock.c (modified) (11 diffs)
-
block/libblock.h (modified) (1 diff)
-
c/generic/adt/hash_table.c (modified) (14 diffs)
-
c/generic/async.c (modified) (12 diffs)
-
c/include/adt/hash.h (added)
-
c/include/adt/hash_table.h (modified) (3 diffs)
-
c/include/adt/list.h (modified) (1 diff)
-
nic/include/nic.h (modified) (2 diffs)
-
nic/src/nic_addr_db.c (modified) (12 diffs)
-
nic/src/nic_wol_virtues.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/block/libblock.c
rb17518e rbc216a0 254 254 } 255 255 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) 277 { 278 block_t *b = hash_table_get_instance(item, block_t, hash_link); 279 return b->lba == MERGE_LOUP32(key[0], key[1]); 256 static size_t cache_key_hash(void *key) 257 { 258 aoff64_t *lba = (aoff64_t*)key; 259 return *lba; 260 } 261 262 static size_t cache_hash(const ht_link_t *item) 263 { 264 block_t *b = hash_table_get_inst(item, block_t, hash_link); 265 return b->lba; 266 } 267 268 static bool cache_key_equal(void *key, const ht_link_t *item) 269 { 270 aoff64_t *lba = (aoff64_t*)key; 271 block_t *b = hash_table_get_inst(item, block_t, hash_link); 272 return b->lba == *lba; 280 273 } 281 274 … … 284 277 .hash = cache_hash, 285 278 .key_hash = cache_key_hash, 286 . match = cache_match,279 .key_equal = cache_key_equal, 287 280 .equal = 0, 288 281 .remove_callback = 0 … … 317 310 cache->blocks_cluster = cache->lblock_size / devcon->pblock_size; 318 311 319 if (!hash_table_create(&cache->block_hash, 0, 2, &cache_ops)) {312 if (!hash_table_create(&cache->block_hash, 0, 0, &cache_ops)) { 320 313 free(cache); 321 314 return ENOMEM; … … 355 348 } 356 349 357 unsigned long key[2] = { 358 LOWER32(b->lba), 359 UPPER32(b->lba) 360 }; 361 hash_table_remove(&cache->block_hash, key, 2); 350 hash_table_remove_item(&cache->block_hash, &b->hash_link); 362 351 363 352 free(b->data); … … 391 380 fibril_rwlock_initialize(&b->contents_lock); 392 381 link_initialize(&b->free_link); 393 link_initialize(&b->hash_link);394 382 } 395 383 … … 411 399 cache_t *cache; 412 400 block_t *b; 413 link_t *l; 414 unsigned long key[2] = { 415 LOWER32(ba), 416 UPPER32(ba) 417 }; 401 link_t *link; 418 402 419 403 int rc; … … 431 415 432 416 fibril_mutex_lock(&cache->lock); 433 l = hash_table_find(&cache->block_hash, key);434 if ( l) {417 ht_link_t *hlink = hash_table_find(&cache->block_hash, &ba); 418 if (hlink) { 435 419 found: 436 420 /* 437 421 * We found the block in the cache. 438 422 */ 439 b = hash_table_get_inst ance(l, block_t, hash_link);423 b = hash_table_get_inst(hlink, block_t, hash_link); 440 424 fibril_mutex_lock(&b->lock); 441 425 if (b->refcnt++ == 0) … … 475 459 goto out; 476 460 } 477 l = list_first(&cache->free_list);478 b = list_get_instance(l , block_t, free_link);461 link = list_first(&cache->free_list); 462 b = list_get_instance(link, block_t, free_link); 479 463 480 464 fibril_mutex_lock(&b->lock); … … 516 500 goto retry; 517 501 } 518 l = hash_table_find(&cache->block_hash, key);519 if ( l) {502 hlink = hash_table_find(&cache->block_hash, &ba); 503 if (hlink) { 520 504 /* 521 505 * Someone else must have already … … 539 523 */ 540 524 list_remove(&b->free_link); 541 unsigned long temp_key[2] = { 542 LOWER32(b->lba), 543 UPPER32(b->lba) 544 }; 545 hash_table_remove(&cache->block_hash, temp_key, 2); 525 hash_table_remove_item(&cache->block_hash, &b->hash_link); 546 526 } 547 527 … … 663 643 * Take the block out of the cache and free it. 664 644 */ 665 unsigned long key[2] = { 666 LOWER32(block->lba), 667 UPPER32(block->lba) 668 }; 669 hash_table_remove(&cache->block_hash, key, 2); 645 hash_table_remove_item(&cache->block_hash, &block->hash_link); 670 646 fibril_mutex_unlock(&block->lock); 671 647 free(block->data); -
uspace/lib/block/libblock.h
rb17518e rbc216a0 84 84 link_t free_link; 85 85 /** Link for placing the block into the block hash table. */ 86 link_t hash_link;86 ht_link_t hash_link; 87 87 /** Buffer with the block data. */ 88 88 void *data; -
uspace/lib/c/generic/adt/hash_table.c
rb17518e rbc216a0 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2012 Adam Hraska 4 * 3 5 * All rights reserved. 4 6 * … … 62 64 static size_t round_up_size(size_t size); 63 65 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); 66 static void clear_items(hash_table_t *h); 67 static void resize(hash_table_t *h, size_t new_bucket_cnt); 68 static void grow_if_needed(hash_table_t *h); 69 static void shrink_if_needed(hash_table_t *h); 69 70 70 71 /* Dummy do nothing callback to invoke in place of remove_callback == NULL. */ 71 static void nop_remove_callback( link_t *item)72 static void nop_remove_callback(ht_link_t *item) 72 73 { 73 74 /* no-op */ … … 90 91 * 91 92 */ 92 bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_ keys,93 bool hash_table_create(hash_table_t *h, size_t init_size, size_t max_load, 93 94 hash_table_ops_t *op) 94 95 { 95 96 assert(h); 96 assert(op && op->hash && op->key_hash && op->match); 97 assert(max_keys > 0); 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; 98 102 99 103 h->bucket_cnt = round_up_size(init_size); … … 102 106 return false; 103 107 104 h->max_ keys = max_keys;105 h->item s= 0;108 h->max_load = (max_load == 0) ? HT_MAX_LOAD : max_load; 109 h->item_cnt = 0; 106 110 h->op = op; 107 108 if (h->op->remove_callback == 0) 111 h->full_item_cnt = h->max_load * h->bucket_cnt; 112 h->apply_ongoing = false; 113 114 if (h->op->remove_callback == 0) { 109 115 h->op->remove_callback = nop_remove_callback; 116 } 110 117 111 118 return true; 112 119 } 113 120 121 /** Destroy a hash table instance. 122 * 123 * @param h Hash table to be destroyed. 124 * 125 */ 126 void hash_table_destroy(hash_table_t *h) 127 { 128 assert(h && h->bucket); 129 assert(!h->apply_ongoing); 130 131 clear_items(h); 132 133 free(h->bucket); 134 135 h->bucket = 0; 136 h->bucket_cnt = 0; 137 } 138 139 /** Returns true if there are no items in the table. */ 140 bool hash_table_empty(hash_table_t *h) 141 { 142 assert(h && h->bucket); 143 return h->item_cnt == 0; 144 } 145 146 /** Returns the number of items in the table. */ 147 size_t hash_table_size(hash_table_t *h) 148 { 149 assert(h && h->bucket); 150 return h->item_cnt; 151 } 152 114 153 /** Remove all elements from the hash table 115 154 * … … 118 157 void hash_table_clear(hash_table_t *h) 119 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 120 176 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 121 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 122 181 list_remove(cur); 123 h->op->remove_callback(cur); 124 } 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 } 138 } 139 140 /** Destroy a hash table instance. 141 * 142 * @param h Hash table to be destroyed. 143 * 144 */ 145 void hash_table_destroy(hash_table_t *h) 146 { 147 assert(h); 148 assert(h->bucket); 149 150 free(h->bucket); 151 152 h->bucket = 0; 153 h->bucket_cnt = 0; 182 h->op->remove_callback(cur_link); 183 } 184 } 185 186 h->item_cnt = 0; 154 187 } 155 188 … … 160 193 * @param item Item to be inserted into the hash table. 161 194 */ 162 void hash_table_insert(hash_table_t *h, link_t *item)195 void hash_table_insert(hash_table_t *h, ht_link_t *item) 163 196 { 164 197 assert(item); 165 198 assert(h && h->bucket); 166 assert( h->op && h->op->hash);199 assert(!h->apply_ongoing); 167 200 168 201 size_t idx = h->op->hash(item) % h->bucket_cnt; 169 202 170 assert(idx < h->bucket_cnt); 171 172 list_append(item, &h->bucket[idx]); 173 item_inserted(h); 203 list_append(&item->link, &h->bucket[idx]); 204 ++h->item_cnt; 205 grow_if_needed(h); 174 206 } 175 207 … … 184 216 * @return True if the inserted item was the only item with such a lookup key. 185 217 */ 186 bool hash_table_insert_unique(hash_table_t *h, link_t *item)218 bool hash_table_insert_unique(hash_table_t *h, ht_link_t *item) 187 219 { 188 220 assert(item); 189 221 assert(h && h->bucket && h->bucket_cnt); 190 222 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); 223 assert(!h->apply_ongoing); 224 225 size_t idx = h->op->hash(item) % h->bucket_cnt; 196 226 197 227 /* Check for duplicates. */ … … 201 231 * calling equal() might very well be just as fast. 202 232 */ 203 if (h->op->equal(cur, item)) 233 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 234 if (h->op->equal(cur_link, item)) 204 235 return false; 205 236 } 206 237 207 list_append(item, &h->bucket[idx]); 208 item_inserted(h); 238 list_append(&item->link, &h->bucket[idx]); 239 ++h->item_cnt; 240 grow_if_needed(h); 209 241 210 242 return true; … … 219 251 * 220 252 */ 221 link_t *hash_table_find(const hash_table_t *h, unsigned long key[]) 222 { 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 253 ht_link_t *hash_table_find(const hash_table_t *h, void *key) 254 { 255 assert(h && h->bucket); 256 257 size_t idx = h->op->key_hash(key) % h->bucket_cnt; 258 231 259 list_foreach(h->bucket[idx], cur) { 260 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 232 261 /* 233 262 * 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 be263 * checked if the hashes match but op->key_equal() may very well be 235 264 * just as fast as op->hash(). 236 265 */ 237 if (h->op-> match(key, h->max_keys, cur)) {238 return cur ;266 if (h->op->key_equal(key, cur_link)) { 267 return cur_link; 239 268 } 240 269 } … … 243 272 } 244 273 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!). 262 */ 263 if (!f(cur, arg)) 264 return; 265 } 266 } 274 /** Find the next item equal to item. */ 275 ht_link_t *hash_table_find_next(const hash_table_t *h, ht_link_t *item) 276 { 277 assert(item); 278 assert(h && h->bucket); 279 280 /* Traverse the circular list until we reach the starting item again. */ 281 for (link_t *cur = item->link.next; cur != &item->link; cur = cur->next) { 282 assert(cur); 283 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 284 /* 285 * Is this is the item we are looking for? We could have first 286 * checked if the hashes match but op->equal() may very well be 287 * just as fast as op->hash(). 288 */ 289 if (h->op->equal(cur_link, item)) { 290 return cur_link; 291 } 292 } 293 294 return NULL; 267 295 } 268 296 … … 278 306 * @return Returns the number of removed items. 279 307 */ 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 && 284 h->op->remove_callback); 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 { 291 /* 292 * Fewer keys were passed. 293 * Any partially matching entries are to be removed. 294 */ 295 return remove_matching(h, key, key_cnt); 296 } 308 size_t hash_table_remove(hash_table_t *h, void *key) 309 { 310 assert(h && h->bucket); 311 assert(!h->apply_ongoing); 312 313 size_t idx = h->op->key_hash(key) % h->bucket_cnt; 314 315 size_t removed = 0; 316 317 list_foreach_safe(h->bucket[idx], cur, next) { 318 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 319 320 if (h->op->key_equal(key, cur_link)) { 321 ++removed; 322 list_remove(cur); 323 h->op->remove_callback(cur_link); 324 } 325 } 326 327 h->item_cnt -= removed; 328 shrink_if_needed(h); 329 330 return removed; 297 331 } 298 332 299 333 /** 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)334 void hash_table_remove_item(hash_table_t *h, ht_link_t *item) 301 335 { 302 336 assert(item); 303 337 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); 338 assert(link_in_use(&item->link)); 339 340 list_remove(&item->link); 341 --h->item_cnt; 315 342 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; 349 /* 350 * Fewer keys were passed. 351 * Any partially matching entries are to be removed. 352 */ 343 shrink_if_needed(h); 344 } 345 346 /** Apply function to all items in hash table. 347 * 348 * @param h Hash table. 349 * @param f Function to be applied. Return false if no more items 350 * should be visited. The functor may only delete the supplied 351 * item. It must not delete the successor of the item passed 352 * in the first argument. 353 * @param arg Argument to be passed to the function. 354 */ 355 void hash_table_apply(hash_table_t *h, bool (*f)(ht_link_t *, void *), void *arg) 356 { 357 assert(f); 358 assert(h && h->bucket); 359 360 if (h->item_cnt == 0) 361 return; 362 363 h->apply_ongoing = true; 364 353 365 for (size_t idx = 0; idx < h->bucket_cnt; ++idx) { 354 366 list_foreach_safe(h->bucket[idx], cur, next) { 355 if (h->op->match(key, key_cnt, cur)) { 356 ++removed; 357 remove_item(h, cur); 358 } 359 } 360 } 361 362 return removed; 363 367 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 368 /* 369 * The next pointer had already been saved. f() may safely 370 * delete cur (but not next!). 371 */ 372 if (!f(cur_link, arg)) 373 return; 374 } 375 } 376 377 h->apply_ongoing = false; 378 379 shrink_if_needed(h); 380 grow_if_needed(h); 364 381 } 365 382 … … 392 409 } 393 410 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) { 411 412 /** Shrinks the table if the table is only sparely populated. */ 413 static inline void shrink_if_needed(hash_table_t *h) 414 { 415 if (h->item_cnt <= h->full_item_cnt / 4 && HT_MIN_BUCKETS < h->bucket_cnt) { 425 416 /* 426 417 * Keep the bucket_cnt odd (possibly also prime). … … 432 423 } 433 424 434 /** Grows the table if needed. */ 435 static void item_inserted(hash_table_t *h) 436 { 437 ++h->items; 438 425 /** Grows the table if table load exceeds the maximum allowed. */ 426 static inline void grow_if_needed(hash_table_t *h) 427 { 439 428 /* Grow the table if the average bucket load exceeds the maximum. */ 440 if ( HT_MAX_LOAD * h->bucket_cnt < h->items) {429 if (h->full_item_cnt < h->item_cnt) { 441 430 /* Keep the bucket_cnt odd (possibly also prime). */ 442 431 size_t new_bucket_cnt = 2 * h->bucket_cnt + 1; … … 445 434 } 446 435 436 /** Allocates and rehashes items to a new table. Frees the old table. */ 437 static void resize(hash_table_t *h, size_t new_bucket_cnt) 438 { 439 assert(h && h->bucket); 440 assert(HT_MIN_BUCKETS <= new_bucket_cnt); 441 442 /* We are traversing the table and resizing would mess up the buckets. */ 443 if (h->apply_ongoing) 444 return; 445 446 list_t *new_buckets; 447 448 /* Leave the table as is if we cannot resize. */ 449 if (!alloc_table(new_bucket_cnt, &new_buckets)) 450 return; 451 452 if (0 < h->item_cnt) { 453 /* Rehash all the items to the new table. */ 454 for (size_t old_idx = 0; old_idx < h->bucket_cnt; ++old_idx) { 455 list_foreach_safe(h->bucket[old_idx], cur, next) { 456 ht_link_t *cur_link = member_to_inst(cur, ht_link_t, link); 457 458 size_t new_idx = h->op->hash(cur_link) % new_bucket_cnt; 459 list_remove(cur); 460 list_append(cur, &new_buckets[new_idx]); 461 } 462 } 463 } 464 465 free(h->bucket); 466 h->bucket = new_buckets; 467 h->bucket_cnt = new_bucket_cnt; 468 h->full_item_cnt = h->max_load * h->bucket_cnt; 469 } 470 447 471 448 472 /** @} -
uspace/lib/c/generic/async.c
rb17518e rbc216a0 202 202 /* Client connection data */ 203 203 typedef struct { 204 link_t link;204 ht_link_t link; 205 205 206 206 task_id_t in_task_id; … … 214 214 215 215 /** Hash table link. */ 216 link_t link;216 ht_link_t link; 217 217 218 218 /** Incoming client task ID. */ … … 390 390 static LIST_INITIALIZE(timeout_list); 391 391 392 static size_t client_key_hash(unsigned long key[]) 393 { 394 assert(key); 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) 412 { 413 assert(key); 414 assert(keys == 2); 415 assert(item); 416 417 client_t *client = hash_table_get_instance(item, client_t, link); 418 return (key[0] == LOWER32(client->in_task_id) && 419 (key[1] == UPPER32(client->in_task_id))); 392 static size_t client_key_hash(void *k) 393 { 394 task_id_t key = *(task_id_t*)k; 395 return key; 396 } 397 398 static size_t client_hash(const ht_link_t *item) 399 { 400 client_t *client = hash_table_get_inst(item, client_t, link); 401 return client_key_hash(&client->in_task_id); 402 } 403 404 static bool client_key_equal(void *k, const ht_link_t *item) 405 { 406 task_id_t key = *(task_id_t*)k; 407 client_t *client = hash_table_get_inst(item, client_t, link); 408 return key == client->in_task_id; 420 409 } 421 410 … … 425 414 .hash = client_hash, 426 415 .key_hash = client_key_hash, 427 . match = client_match,416 .key_equal = client_key_equal, 428 417 .equal = 0, 429 418 .remove_callback = 0 … … 437 426 * 438 427 */ 439 static size_t conn_key_hash(unsigned long key[]) 440 { 441 assert(key); 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); 450 } 451 452 /** Compare hash table item with a key. 453 * 454 * @param key Array containing the source phone hash as the only item. 455 * @param keys Expected 1 but ignored. 456 * @param item Connection hash table item. 457 * 458 * @return True on match, false otherwise. 459 * 460 */ 461 static bool conn_match(unsigned long key[], size_t keys, const link_t *item) 462 { 463 assert(key); 464 assert(item); 465 466 connection_t *conn = hash_table_get_instance(item, connection_t, link); 467 return (key[0] == conn->in_phone_hash); 468 } 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 478 static void conn_remove(link_t *item) 479 { 480 } 428 static size_t conn_key_hash(void *key) 429 { 430 sysarg_t in_phone_hash = *(sysarg_t*)key; 431 return in_phone_hash ; 432 } 433 434 static size_t conn_hash(const ht_link_t *item) 435 { 436 connection_t *conn = hash_table_get_inst(item, connection_t, link); 437 return conn_key_hash(&conn->in_phone_hash); 438 } 439 440 static bool conn_key_equal(void *key, const ht_link_t *item) 441 { 442 sysarg_t in_phone_hash = *(sysarg_t*)key; 443 connection_t *conn = hash_table_get_inst(item, connection_t, link); 444 return (in_phone_hash == conn->in_phone_hash); 445 } 446 481 447 482 448 /** Operations for the connection hash table. */ … … 484 450 .hash = conn_hash, 485 451 .key_hash = conn_key_hash, 486 . match = conn_match,487 .equal = conn_equal,488 .remove_callback = conn_remove452 .key_equal = conn_key_equal, 453 .equal = 0, 454 .remove_callback = 0 489 455 }; 490 456 … … 534 500 futex_down(&async_futex); 535 501 536 unsigned long key = call->in_phone_hash; 537 link_t *hlp = hash_table_find(&conn_hash_table, &key); 502 ht_link_t *hlp = hash_table_find(&conn_hash_table, &call->in_phone_hash); 538 503 539 504 if (!hlp) { … … 542 507 } 543 508 544 connection_t *conn = hash_table_get_inst ance(hlp, connection_t, link);509 connection_t *conn = hash_table_get_inst(hlp, connection_t, link); 545 510 546 511 msg_t *msg = malloc(sizeof(*msg)); … … 722 687 static client_t *async_client_get(task_id_t client_id, bool create) 723 688 { 724 unsigned long key[2] = {725 LOWER32(client_id),726 UPPER32(client_id),727 };728 689 client_t *client = NULL; 729 690 730 691 futex_down(&async_futex); 731 link_t *lnk = hash_table_find(&client_hash_table, key);692 ht_link_t *lnk = hash_table_find(&client_hash_table, &client_id); 732 693 if (lnk) { 733 client = hash_table_get_inst ance(lnk, client_t, link);694 client = hash_table_get_inst(lnk, client_t, link); 734 695 atomic_inc(&client->refcnt); 735 696 } else if (create) { … … 751 712 { 752 713 bool destroy; 753 unsigned long key[2] = { 754 LOWER32(client->in_task_id), 755 UPPER32(client->in_task_id) 756 }; 757 714 758 715 futex_down(&async_futex); 759 716 760 717 if (atomic_predec(&client->refcnt) == 0) { 761 hash_table_remove(&client_hash_table, key, 2);718 hash_table_remove(&client_hash_table, &client->in_task_id); 762 719 destroy = true; 763 720 } else … … 855 812 */ 856 813 futex_down(&async_futex); 857 unsigned long key = fibril_connection->in_phone_hash; 858 hash_table_remove(&conn_hash_table, &key, 1); 814 hash_table_remove(&conn_hash_table, &fibril_connection->in_phone_hash); 859 815 futex_up(&async_futex); 860 816 … … 1134 1090 void __async_init(void) 1135 1091 { 1136 if (!hash_table_create(&client_hash_table, 0, 2, &client_hash_table_ops))1092 if (!hash_table_create(&client_hash_table, 0, 0, &client_hash_table_ops)) 1137 1093 abort(); 1138 1094 1139 if (!hash_table_create(&conn_hash_table, 0, 1, &conn_hash_table_ops))1095 if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops)) 1140 1096 abort(); 1141 1097 -
uspace/lib/c/include/adt/hash_table.h
rb17518e rbc216a0 1 1 /* 2 2 * Copyright (c) 2006 Jakub Jermar 3 * Copyright (c) 2012 Adam Hraska 4 * 3 5 * All rights reserved. 4 6 * … … 39 41 #include <unistd.h> 40 42 #include <bool.h> 43 #include <macros.h> 41 44 45 /** Opaque hash table link type. */ 46 typedef struct ht_link { 47 link_t link; 48 } ht_link_t; 42 49 43 50 /** Set of operations for hash table. */ 44 51 typedef struct { 45 /** Returns the hash of the key stored in the item. 46 */ 47 size_t (*hash)(const link_t *item); 52 /** Returns the hash of the key stored in the item (ie its lookup key). */ 53 size_t (*hash)(const ht_link_t *item); 48 54 49 /** Returns the hash of the key. 50 */ 51 size_t (*key_hash)(unsigned long key[]); 55 /** Returns the hash of the key. */ 56 size_t (*key_hash)(void *key); 52 57 53 /** Hash table item match function. 54 * 55 * @param key Array of keys that will be compared with item. It is 56 * not necessary to pass all keys. 57 * 58 * @return True if the keys match, false otherwise. 59 * 60 */ 61 bool (*match)(unsigned long key[], size_t keys, const link_t *item); 58 /** True if the items are equal (have the same lookup keys). */ 59 bool (*equal)(const ht_link_t *item1, const ht_link_t *item2); 62 60 63 /** 64 */ 65 bool (*equal)(const link_t *item1, const link_t *item2); 66 61 /** Returns true if the key is equal to the item's lookup key. */ 62 bool (*key_equal)(void *key, const ht_link_t *item); 63 67 64 /** Hash table item removal callback. 68 65 * … … 71 68 * @param item Item that was removed from the hash table. 72 69 */ 73 void (*remove_callback)( link_t *item);70 void (*remove_callback)(ht_link_t *item); 74 71 } hash_table_ops_t; 75 72 76 73 /** Hash table structure. */ 77 74 typedef struct { 75 hash_table_ops_t *op; 78 76 list_t *bucket; 79 77 size_t bucket_cnt; 80 size_t max_keys; 81 size_t items; 82 hash_table_ops_t *op; 78 size_t full_item_cnt; 79 size_t item_cnt; 80 size_t max_load; 81 bool apply_ongoing; 83 82 } hash_table_t; 84 83 85 #define hash_table_get_inst ance(item, type, member) \86 list_get_instance((item), type, member)84 #define hash_table_get_inst(item, type, member) \ 85 member_to_inst((item), type, member) 87 86 88 87 extern bool hash_table_create(hash_table_t *, size_t, size_t, 89 88 hash_table_ops_t *); 89 extern void hash_table_destroy(hash_table_t *); 90 91 extern bool hash_table_empty(hash_table_t *); 92 extern size_t hash_table_size(hash_table_t *); 93 90 94 extern void hash_table_clear(hash_table_t *); 91 extern void hash_table_insert(hash_table_t *, link_t *);92 extern bool hash_table_insert_unique(hash_table_t *, link_t *);93 extern link_t *hash_table_find(const hash_table_t *, unsigned long []);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*);96 extern void hash_table_ destroy(hash_table_t *);97 extern void hash_table_apply(hash_table_t *, bool (*)( link_t *, void *),95 extern void hash_table_insert(hash_table_t *, ht_link_t *); 96 extern bool hash_table_insert_unique(hash_table_t *, ht_link_t *); 97 extern ht_link_t *hash_table_find(const hash_table_t *, void *); 98 extern ht_link_t *hash_table_find_next(const hash_table_t *, ht_link_t *); 99 extern size_t hash_table_remove(hash_table_t *, void *); 100 extern void hash_table_remove_item(hash_table_t *, ht_link_t *); 101 extern void hash_table_apply(hash_table_t *, bool (*)(ht_link_t *, void *), 98 102 void *); 99 103 -
uspace/lib/c/include/adt/list.h
rb17518e rbc216a0 105 105 assert(((link)->prev == NULL) && ((link)->next == NULL)) 106 106 107 /** Returns true if the link is definitely part of a list. False if not sure. */ 108 static inline int link_in_use(link_t *link) 109 { 110 return link->prev != NULL && link->next != NULL; 111 } 112 107 113 /** Initialize doubly-linked circular list link 108 114 * -
uspace/lib/nic/include/nic.h
rb17518e rbc216a0 40 40 41 41 #include <adt/list.h> 42 #include <adt/hash_table.h> 42 43 #include <ddf/driver.h> 43 44 #include <device/hw_res_parsed.h> … … 53 54 */ 54 55 typedef struct nic_wol_virtue { 55 link_t item;56 ht_link_t item; 56 57 nic_wv_id_t id; 57 58 nic_wv_type_t type; -
uspace/lib/nic/src/nic_addr_db.c
rb17518e rbc216a0 36 36 */ 37 37 #include "nic_addr_db.h" 38 #include "libarch/common.h" 38 39 #include <assert.h> 39 40 #include <stdlib.h> … … 43 44 #include <adt/hash_table.h> 44 45 #include <macros.h> 45 46 /* The key count hash table field is not used. Use this dummy value. */ 47 #define KEY_CNT 1 48 49 /** 50 * Maximal length of addresses in the DB (in bytes). 51 */ 52 #define NIC_ADDR_MAX_LENGTH 16 46 #include <stdint.h> 47 53 48 54 49 /** … … 56 51 */ 57 52 typedef struct nic_addr_entry { 58 link_t link; 59 uint8_t addr[NIC_ADDR_MAX_LENGTH]; 53 ht_link_t link; 54 uint8_t len; 55 uint8_t addr[1]; 60 56 } nic_addr_entry_t; 61 57 … … 64 60 * Hash table helper functions 65 61 */ 66 67 static bool nic_addr_match(unsigned long *key, size_t key_cnt, 68 const link_t *item) 69 { 70 uint8_t *addr = (uint8_t*)key; 71 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link); 72 73 return 0 == bcmp(entry->addr, addr, NIC_ADDR_MAX_LENGTH); 74 } 75 76 static size_t nic_addr_key_hash(unsigned long *key) 77 { 78 uint8_t *addr = (uint8_t*)key; 62 typedef struct { 63 size_t len; 64 const uint8_t *addr; 65 } addr_key_t; 66 67 static bool nic_addr_key_equal(void *key_arg, const ht_link_t *item) 68 { 69 addr_key_t *key = (addr_key_t*)key_arg; 70 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link); 71 72 return 0 == bcmp(entry->addr, key->addr, entry->len); 73 } 74 75 static size_t addr_hash(size_t len, const uint8_t *addr) 76 { 79 77 size_t hash = 0; 80 81 for ( int i = NIC_ADDR_MAX_LENGTH - 1; i >= 0; --i) {82 hash = (hash << 8) ^ (hash >> 24) ^ addr[i];78 79 for (size_t i = 0; i < len; ++i) { 80 hash = (hash << 5) ^ addr[i]; 83 81 } 84 82 … … 86 84 } 87 85 88 static size_t nic_addr_hash(const link_t *item) 89 { 90 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link); 91 92 unsigned long *key = (unsigned long*)entry->addr; 93 return nic_addr_key_hash(key); 94 } 95 96 static void nic_addr_removed(link_t *item) 86 static size_t nic_addr_key_hash(void *k) 87 { 88 addr_key_t *key = (addr_key_t*)k; 89 return addr_hash(key->len, key->addr); 90 } 91 92 static size_t nic_addr_hash(const ht_link_t *item) 93 { 94 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link); 95 return addr_hash(entry->len, entry->addr); 96 } 97 98 static void nic_addr_removed(ht_link_t *item) 97 99 { 98 100 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link); … … 104 106 .hash = nic_addr_hash, 105 107 .key_hash = nic_addr_key_hash, 106 . match = nic_addr_match,108 .key_equal = nic_addr_key_equal, 107 109 .equal = 0, 108 110 .remove_callback = nic_addr_removed … … 122 124 { 123 125 assert(db); 124 if (addr_len > NIC_ADDR_MAX_LENGTH) { 126 127 if (addr_len > UCHAR_MAX) 125 128 return EINVAL; 126 } 127 128 if (!hash_table_create(&db->set, 0, KEY_CNT, &set_ops)) 129 130 if (!hash_table_create(&db->set, 0, 0, &set_ops)) 129 131 return ENOMEM; 130 132 … … 152 154 { 153 155 assert(db); 154 nic_addr_db_clear(db);155 156 hash_table_destroy(&db->set); 156 157 } … … 171 172 { 172 173 assert(db && addr); 173 /* Ugly type-punning hack. */ 174 unsigned long *key = (unsigned long*)addr; 175 176 if (hash_table_find(&db->set, key)) 174 175 addr_key_t key = { 176 .len = db->addr_len, 177 .addr = addr 178 }; 179 180 if (hash_table_find(&db->set, &key)) 177 181 return EEXIST; 178 182 179 nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t) );183 nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t) + db->addr_len - 1); 180 184 if (entry == NULL) 181 185 return ENOMEM; 182 183 link_initialize(&entry->link); 184 185 bzero(entry->addr, NIC_ADDR_MAX_LENGTH); 186 187 entry->len = (uint8_t) db->addr_len; 186 188 memcpy(entry->addr, addr, db->addr_len); 187 189 … … 202 204 { 203 205 assert(db && addr); 204 unsigned long *key = (unsigned long*)addr; 205 206 link_t *item = hash_table_find(&db->set, key); 207 208 if (item) { 209 hash_table_remove_item(&db->set, item); 206 207 addr_key_t key = { 208 .len = db->addr_len, 209 .addr = addr 210 }; 211 212 if (hash_table_remove(&db->set, &key)) 210 213 return EOK; 211 } else {214 else 212 215 return ENOENT; 213 }214 216 } 215 217 … … 225 227 { 226 228 assert(db && addr); 227 unsigned long *key = (unsigned long*)addr; 228 229 return 0 != hash_table_find(&db->set, key); 229 230 addr_key_t key = { 231 .len = db->addr_len, 232 .addr = addr 233 }; 234 235 return 0 != hash_table_find(&db->set, &key); 230 236 } 231 237 … … 241 247 * Helper function for nic_addr_db_foreach 242 248 */ 243 static bool nic_addr_db_fe_helper( link_t *item, void *arg)249 static bool nic_addr_db_fe_helper(ht_link_t *item, void *arg) 244 250 { 245 251 nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg; -
uspace/lib/nic/src/nic_wol_virtues.c
rb17518e rbc216a0 37 37 38 38 #include "nic_wol_virtues.h" 39 #include "nic.h" 39 40 #include <assert.h> 40 41 #include <errno.h> … … 45 46 */ 46 47 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)48 static size_t nic_wv_key_hash(void *key) 49 { 50 return *(nic_wv_id_t*) key; 51 } 52 53 static size_t nic_wv_hash(const ht_link_t *item) 53 54 { 54 55 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) 56 return virtue->id; 57 } 58 59 static bool nic_wv_key_equal(void *key, const ht_link_t *item) 60 60 { 61 61 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item; 62 return (virtue->id == (nic_wv_id_t) key[0]);62 return (virtue->id == *(nic_wv_id_t*) key); 63 63 } 64 64 … … 76 76 wvs->table_operations.hash = nic_wv_hash; 77 77 wvs->table_operations.key_hash = nic_wv_key_hash; 78 wvs->table_operations. match = nic_wv_match;78 wvs->table_operations.key_equal = nic_wv_key_equal; 79 79 wvs->table_operations.equal = 0; 80 80 wvs->table_operations.remove_callback = 0; 81 81 82 if (!hash_table_create(&wvs->table, 0, 1, &wvs->table_operations)) {82 if (!hash_table_create(&wvs->table, 0, 0, &wvs->table_operations)) { 83 83 return ENOMEM; 84 84 } … … 168 168 do { 169 169 virtue->id = wvs->next_id++; 170 } while (NULL != 171 hash_table_find(&wvs->table, (unsigned long *) &virtue->id)); 170 } while (NULL != hash_table_find(&wvs->table, &virtue->id)); 172 171 hash_table_insert(&wvs->table, &virtue->item); 173 172 virtue->next = wvs->lists[virtue->type]; … … 188 187 nic_wol_virtue_t *nic_wol_virtues_remove(nic_wol_virtues_t *wvs, nic_wv_id_t id) 189 188 { 190 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *)191 hash_table_find(&wvs->table, (unsigned long *)&id);189 nic_wol_virtue_t *virtue = 190 (nic_wol_virtue_t *) hash_table_find(&wvs->table, &id); 192 191 if (virtue == NULL) { 193 192 return NULL; … … 195 194 196 195 /* Remove from filter_table */ 197 hash_table_remove (&wvs->table, (unsigned long *) &id, 1);196 hash_table_remove_item(&wvs->table, &virtue->item); 198 197 199 198 /* Remove from filter_types */ … … 232 231 * constant virtue the retyping is correct. 233 232 */ 234 link_t *virtue = hash_table_find( 235 &((nic_wol_virtues_t *) wvs)->table, (unsigned long *) &id); 233 ht_link_t *virtue = hash_table_find(&((nic_wol_virtues_t *) wvs)->table, &id); 236 234 return (const nic_wol_virtue_t *) virtue; 237 235 }
Note:
See TracChangeset
for help on using the changeset viewer.
