diff --git a/doc/ck_ht_init b/doc/ck_ht_init index e41ce12..4006f9b 100644 --- a/doc/ck_ht_init +++ b/doc/ck_ht_init @@ -36,7 +36,7 @@ Concurrency Kit (libck, \-lck) .Ft typedef void .Fn ck_ht_hash_cb_t "ck_ht_hash_t *h" "const void *key" "size_t key_length" "uint64_t seed" .Ft bool -.Fn ck_ht_init "ck_ht_t *ht" "enum ck_ht_mode mode" "ck_ht_hash_cb_t hash_function" "uint64_t capacity" "uint64_t seed" +.Fn ck_ht_init "ck_ht_t *ht" "enum ck_ht_mode mode" "ck_ht_hash_cb_t *hash_function" "struct ck_malloc *allocator" "uint64_t capacity" "uint64_t seed" .Sh DESCRIPTION The .Fn ck_ht_init @@ -63,7 +63,8 @@ to be interacted with using the .Xr ck_ht_entry_value 3 , and .Xr ck_ht_entry_set 3 -functions. +functions. Attempting a hash table operation with a key of value +NULL or (void *)UINTPTR_MAX will result in undefined behavior. .It CK_HT_MODE_DIRECT The hash table is meant to store key-value pointers where the key is of fixed width field compatible with the @@ -76,7 +77,8 @@ with using the .Xr ck_ht_entry_value_direct 3 and .Xr ck_entry_set_direct 3 -functions. +functions. Attempting a hash table operation with a key of value of 0 or +UINTPTR_MAX will result in undefined behavior. .El .Pp The argument @@ -106,6 +108,15 @@ argument is the initial seed associated with the hash table. This initial seed is specified by the user in .Xr ck_ht_init 3 . .Pp +The +.Fa allocator +argument is a pointer to a structure containing +.Fa malloc +and +.Fa free +function pointers which respectively define the memory allocation and +destruction functions to be used by the hash table being initialized. +.Pp The argument .Fa capacity represents the initial number of key-value pairs the hash diff --git a/include/ck_ht.h b/include/ck_ht.h index 7a7640b..ddd8f78 100644 --- a/include/ck_ht.h +++ b/include/ck_ht.h @@ -78,6 +78,7 @@ typedef void ck_ht_hash_cb_t(ck_ht_hash_t *, const void *, size_t, uint64_t); struct ck_ht_map; struct ck_ht { + struct ck_malloc *m; struct ck_ht_map *map; enum ck_ht_mode mode; uint64_t seed; @@ -219,7 +220,7 @@ bool ck_ht_next(ck_ht_t *, ck_ht_iterator_t *, ck_ht_entry_t **entry); void ck_ht_hash(ck_ht_hash_t *, ck_ht_t *, const void *, uint16_t); void ck_ht_hash_direct(ck_ht_hash_t *, ck_ht_t *, uintptr_t); bool ck_ht_allocator_set(struct ck_malloc *); -bool ck_ht_init(ck_ht_t *, enum ck_ht_mode, ck_ht_hash_cb_t *, uint64_t, uint64_t); +bool ck_ht_init(ck_ht_t *, enum ck_ht_mode, ck_ht_hash_cb_t *, struct ck_malloc *, uint64_t, uint64_t); void ck_ht_destroy(ck_ht_t *); bool ck_ht_set_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *); bool ck_ht_put_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *); diff --git a/regressions/ck_ht/benchmark/parallel_bytestring.c b/regressions/ck_ht/benchmark/parallel_bytestring.c index 6d19b35..ef60fa5 100644 --- a/regressions/ck_ht/benchmark/parallel_bytestring.c +++ b/regressions/ck_ht/benchmark/parallel_bytestring.c @@ -126,8 +126,7 @@ table_init(void) ck_epoch_init(&epoch_ht, 10); ck_epoch_register(&epoch_ht, &epoch_wr); srand48((long int)time(NULL)); - ck_ht_allocator_set(&my_allocator); - if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, 8, lrand48()) == false) { + if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, &my_allocator, 8, lrand48()) == false) { perror("ck_ht_init"); exit(EXIT_FAILURE); } diff --git a/regressions/ck_ht/benchmark/parallel_direct.c b/regressions/ck_ht/benchmark/parallel_direct.c index 5f05a8e..0f1b3e9 100644 --- a/regressions/ck_ht/benchmark/parallel_direct.c +++ b/regressions/ck_ht/benchmark/parallel_direct.c @@ -136,8 +136,7 @@ table_init(void) ck_epoch_init(&epoch_ht, 10); ck_epoch_register(&epoch_ht, &epoch_wr); srand48((long int)time(NULL)); - ck_ht_allocator_set(&my_allocator); - if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, hash_function, 8, lrand48()) == false) { + if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, hash_function, &my_allocator, 8, lrand48()) == false) { perror("ck_ht_init"); exit(EXIT_FAILURE); } diff --git a/regressions/ck_ht/benchmark/serial.c b/regressions/ck_ht/benchmark/serial.c index 7d0d487..a50b328 100644 --- a/regressions/ck_ht/benchmark/serial.c +++ b/regressions/ck_ht/benchmark/serial.c @@ -73,8 +73,7 @@ table_init(void) { srand48((long int)time(NULL)); - ck_ht_allocator_set(&my_allocator); - if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, 8, lrand48()) == false) { + if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, &my_allocator, 8, lrand48()) == false) { perror("ck_ht_init"); exit(EXIT_FAILURE); } diff --git a/regressions/ck_ht/validate/serial.c b/regressions/ck_ht/validate/serial.c index f3d0ae5..200dbc3 100644 --- a/regressions/ck_ht/validate/serial.c +++ b/regressions/ck_ht/validate/serial.c @@ -77,8 +77,7 @@ main(void) ck_ht_iterator_t iterator = CK_HT_ITERATOR_INITIALIZER; ck_ht_entry_t *cursor; - ck_ht_allocator_set(&my_allocator); - if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, 8, 6602834) == false) { + if (ck_ht_init(&ht, CK_HT_MODE_BYTESTRING, NULL, &my_allocator, 8, 6602834) == false) { perror("ck_ht_init"); exit(EXIT_FAILURE); } @@ -247,7 +246,7 @@ main(void) } ck_ht_destroy(&ht); - if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, NULL, 8, 6602834) == false) { + if (ck_ht_init(&ht, CK_HT_MODE_DIRECT, NULL, &my_allocator, 8, 6602834) == false) { perror("ck_ht_init"); exit(EXIT_FAILURE); } diff --git a/src/ck_ht.c b/src/ck_ht.c index cbcea08..8f71f42 100644 --- a/src/ck_ht.c +++ b/src/ck_ht.c @@ -74,8 +74,6 @@ struct ck_ht_map { struct ck_ht_entry *entries; }; -static struct ck_malloc allocator; - void ck_ht_hash(struct ck_ht_hash *h, struct ck_ht *table, @@ -108,21 +106,8 @@ ck_ht_hash_wrapper(struct ck_ht_hash *h, return; } -bool -ck_ht_allocator_set(struct ck_malloc *m) -{ - - if (m->malloc == NULL || m->free == NULL) - return false; - - allocator.malloc = m->malloc; - allocator.free = m->free; - - return true; -} - static struct ck_ht_map * -ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries) +ck_ht_map_create(struct ck_ht *table, uint64_t entries) { struct ck_ht_map *map; uint64_t size, n_entries; @@ -131,11 +116,11 @@ ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries) size = sizeof(struct ck_ht_map) + (sizeof(struct ck_ht_entry) * n_entries + CK_MD_CACHELINE - 1); - map = allocator.malloc(size); + map = table->m->malloc(size); if (map == NULL) return NULL; - map->mode = mode; + map->mode = table->mode; map->size = size; map->probe_limit = ck_internal_max_64(n_entries >> (CK_HT_BUCKET_SHIFT + 2), CK_HT_PROBE_DEFAULT); @@ -150,7 +135,7 @@ ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries) CK_MD_CACHELINE - 1) & ~(CK_MD_CACHELINE - 1)); if (map->entries == NULL) { - allocator.free(map, size, false); + table->m->free(map, size, false); return NULL; } @@ -159,10 +144,10 @@ ck_ht_map_create(enum ck_ht_mode mode, uint64_t entries) } static void -ck_ht_map_destroy(struct ck_ht_map *map, bool defer) +ck_ht_map_destroy(struct ck_malloc *m, struct ck_ht_map *map, bool defer) { - allocator.free(map, map->size, defer); + m->free(map, map->size, defer); return; } @@ -180,9 +165,18 @@ ck_ht_map_probe_next(struct ck_ht_map *map, size_t offset, ck_ht_hash_t h) } bool -ck_ht_init(ck_ht_t *table, enum ck_ht_mode mode, ck_ht_hash_cb_t *h, uint64_t entries, uint64_t seed) +ck_ht_init(ck_ht_t *table, + enum ck_ht_mode mode, + ck_ht_hash_cb_t *h, + struct ck_malloc *m, + uint64_t entries, + uint64_t seed) { + if (m == NULL || m->malloc == NULL || m->free == NULL) + return false; + + table->m = m; table->mode = mode; table->seed = seed; @@ -192,7 +186,7 @@ ck_ht_init(ck_ht_t *table, enum ck_ht_mode mode, ck_ht_hash_cb_t *h, uint64_t en table->h = h; } - table->map = ck_ht_map_create(mode, entries); + table->map = ck_ht_map_create(table, entries); return table->map != NULL; } @@ -369,12 +363,12 @@ ck_ht_reset_spmc(struct ck_ht *table) struct ck_ht_map *map, *update; map = table->map; - update = ck_ht_map_create(table->mode, map->capacity); + update = ck_ht_map_create(table, map->capacity); if (update == NULL) return false; ck_pr_store_ptr(&table->map, update); - ck_ht_map_destroy(map, true); + ck_ht_map_destroy(table->m, map, true); return true; } @@ -393,7 +387,7 @@ restart: if (map->capacity >= capacity) return false; - update = ck_ht_map_create(table->mode, capacity); + update = ck_ht_map_create(table, capacity); if (update == NULL) return false; @@ -447,7 +441,7 @@ restart: * We have hit the probe limit, the map needs to be even * larger. */ - ck_ht_map_destroy(update, false); + ck_ht_map_destroy(table->m, update, false); capacity <<= 1; goto restart; } @@ -455,7 +449,7 @@ restart: ck_pr_fence_store(); ck_pr_store_ptr(&table->map, update); - ck_ht_map_destroy(map, true); + ck_ht_map_destroy(table->m, map, true); return true; } @@ -720,7 +714,7 @@ void ck_ht_destroy(struct ck_ht *table) { - ck_ht_map_destroy(table->map, false); + ck_ht_map_destroy(table->m, table->map, false); return; }