Commit | Line | Data |
---|---|---|
acdb82a2 MJ |
1 | // SPDX-FileCopyrightText: 2011 Lai Jiangshan <laijs@cn.fujitsu.com> |
2 | // | |
3 | // SPDX-License-Identifier: LGPL-2.1-or-later | |
4 | ||
308d1cb3 | 5 | /* |
308d1cb3 | 6 | * Chunk based memory management for Lock-Free RCU Hash Table |
308d1cb3 LJ |
7 | */ |
8 | ||
9 | #include <stddef.h> | |
01477510 | 10 | #include <urcu/assert.h> |
0d0409b1 | 11 | #include "rculfhash-internal.h" |
308d1cb3 LJ |
12 | |
13 | static | |
14 | void cds_lfht_alloc_bucket_table(struct cds_lfht *ht, unsigned long order) | |
15 | { | |
16 | if (order == 0) { | |
ac735254 XF |
17 | ht->tbl_chunk[0] = ht->alloc->calloc(ht->alloc->state, |
18 | ht->min_nr_alloc_buckets, sizeof(struct cds_lfht_node)); | |
01477510 | 19 | urcu_posix_assert(ht->tbl_chunk[0]); |
308d1cb3 LJ |
20 | } else if (order > ht->min_alloc_buckets_order) { |
21 | unsigned long i, len = 1UL << (order - 1 - ht->min_alloc_buckets_order); | |
22 | ||
23 | for (i = len; i < 2 * len; i++) { | |
ac735254 XF |
24 | ht->tbl_chunk[i] = ht->alloc->calloc(ht->alloc->state, |
25 | ht->min_nr_alloc_buckets, sizeof(struct cds_lfht_node)); | |
01477510 | 26 | urcu_posix_assert(ht->tbl_chunk[i]); |
308d1cb3 LJ |
27 | } |
28 | } | |
29 | /* Nothing to do for 0 < order && order <= ht->min_alloc_buckets_order */ | |
30 | } | |
31 | ||
32 | /* | |
33 | * cds_lfht_free_bucket_table() should be called with decreasing order. | |
34 | * When cds_lfht_free_bucket_table(0) is called, it means the whole | |
35 | * lfht is destroyed. | |
36 | */ | |
37 | static | |
38 | void cds_lfht_free_bucket_table(struct cds_lfht *ht, unsigned long order) | |
39 | { | |
40 | if (order == 0) | |
ac735254 | 41 | poison_free(ht->alloc, ht->tbl_chunk[0]); |
308d1cb3 LJ |
42 | else if (order > ht->min_alloc_buckets_order) { |
43 | unsigned long i, len = 1UL << (order - 1 - ht->min_alloc_buckets_order); | |
44 | ||
45 | for (i = len; i < 2 * len; i++) | |
ac735254 | 46 | poison_free(ht->alloc, ht->tbl_chunk[i]); |
308d1cb3 LJ |
47 | } |
48 | /* Nothing to do for 0 < order && order <= ht->min_alloc_buckets_order */ | |
49 | } | |
50 | ||
51 | static | |
52 | struct cds_lfht_node *bucket_at(struct cds_lfht *ht, unsigned long index) | |
53 | { | |
54 | unsigned long chunk, offset; | |
55 | ||
56 | chunk = index >> ht->min_alloc_buckets_order; | |
57 | offset = index & (ht->min_nr_alloc_buckets - 1); | |
58 | return &ht->tbl_chunk[chunk][offset]; | |
59 | } | |
60 | ||
61 | static | |
62 | struct cds_lfht *alloc_cds_lfht(unsigned long min_nr_alloc_buckets, | |
ac735254 | 63 | unsigned long max_nr_buckets, const struct cds_lfht_alloc *alloc) |
308d1cb3 | 64 | { |
308d1cb3 LJ |
65 | unsigned long nr_chunks, cds_lfht_size; |
66 | ||
67 | min_nr_alloc_buckets = max(min_nr_alloc_buckets, | |
e4ea7f62 | 68 | max_nr_buckets / MAX_CHUNK_TABLE); |
308d1cb3 LJ |
69 | nr_chunks = max_nr_buckets / min_nr_alloc_buckets; |
70 | cds_lfht_size = offsetof(struct cds_lfht, tbl_chunk) + | |
1228af1c | 71 | sizeof(struct cds_lfht_node *) * nr_chunks; |
308d1cb3 | 72 | cds_lfht_size = max(cds_lfht_size, sizeof(struct cds_lfht)); |
308d1cb3 | 73 | |
1228af1c | 74 | return __default_alloc_cds_lfht( |
ac735254 | 75 | &cds_lfht_mm_chunk, alloc, cds_lfht_size, |
1228af1c | 76 | min_nr_alloc_buckets, max_nr_buckets); |
308d1cb3 LJ |
77 | } |
78 | ||
79 | const struct cds_lfht_mm_type cds_lfht_mm_chunk = { | |
80 | .alloc_cds_lfht = alloc_cds_lfht, | |
81 | .alloc_bucket_table = cds_lfht_alloc_bucket_table, | |
82 | .free_bucket_table = cds_lfht_free_bucket_table, | |
83 | .bucket_at = bucket_at, | |
84 | }; |