*/
struct cds_lfht {
struct rcu_table t;
- unsigned long min_alloc_order;
- unsigned long min_alloc_size;
+ unsigned long min_alloc_buckets_order;
+ unsigned long min_nr_alloc_buckets;
+ unsigned long max_nr_buckets;
int flags;
/*
* We need to put the work threads offline (QSBR) when taking this
void cds_lfht_alloc_bucket_table(struct cds_lfht *ht, unsigned long order)
{
if (order == 0) {
- ht->t.tbl[0] = calloc(ht->min_alloc_size,
+ ht->t.tbl[0] = calloc(ht->min_nr_alloc_buckets,
sizeof(struct cds_lfht_node));
assert(ht->t.tbl[0]);
- } else if (order > ht->min_alloc_order) {
+ } else if (order > ht->min_alloc_buckets_order) {
ht->t.tbl[order] = calloc(1UL << (order -1),
sizeof(struct cds_lfht_node));
assert(ht->t.tbl[order]);
}
- /* Nothing to do for 0 < order && order <= ht->min_alloc_order */
+ /* Nothing to do for 0 < order && order <= ht->min_alloc_buckets_order */
}
/*
{
if (order == 0)
poison_free(ht->t.tbl[0]);
- else if (order > ht->min_alloc_order)
+ else if (order > ht->min_alloc_buckets_order)
poison_free(ht->t.tbl[order]);
- /* Nothing to do for 0 < order && order <= ht->min_alloc_order */
+ /* Nothing to do for 0 < order && order <= ht->min_alloc_buckets_order */
}
static inline
unsigned long order;
if ((__builtin_constant_p(index) && index == 0)
- || index < ht->min_alloc_size) {
+ || index < ht->min_nr_alloc_buckets) {
dbg_printf("bucket index %lu order 0 aridx 0\n", index);
return &ht->t.tbl[0][index];
}
}
struct cds_lfht *_cds_lfht_new(unsigned long init_size,
- unsigned long min_alloc_size,
+ unsigned long min_nr_alloc_buckets,
+ unsigned long max_nr_buckets,
int flags,
void (*cds_lfht_call_rcu)(struct rcu_head *head,
void (*func)(struct rcu_head *head)),
struct cds_lfht *ht;
unsigned long order;
- /* min_alloc_size must be power of two */
- if (!min_alloc_size || (min_alloc_size & (min_alloc_size - 1)))
+ /* min_nr_alloc_buckets must be power of two */
+ if (!min_nr_alloc_buckets || (min_nr_alloc_buckets & (min_nr_alloc_buckets - 1)))
return NULL;
+
/* init_size must be power of two */
if (!init_size || (init_size & (init_size - 1)))
return NULL;
- min_alloc_size = max(min_alloc_size, MIN_TABLE_SIZE);
+
+ if (!max_nr_buckets)
+ max_nr_buckets = 1UL << (MAX_TABLE_ORDER - 1);
+
+ /* max_nr_buckets must be power of two */
+ if (!max_nr_buckets || (max_nr_buckets & (max_nr_buckets - 1)))
+ return NULL;
+
+ min_nr_alloc_buckets = max(min_nr_alloc_buckets, MIN_TABLE_SIZE);
init_size = max(init_size, MIN_TABLE_SIZE);
+ max_nr_buckets = max(max_nr_buckets, min_nr_alloc_buckets);
+ init_size = min(init_size, max_nr_buckets);
ht = calloc(1, sizeof(struct cds_lfht));
assert(ht);
ht->flags = flags;
pthread_mutex_init(&ht->resize_mutex, NULL);
order = get_count_order_ulong(init_size);
ht->t.resize_target = 1UL << order;
- ht->min_alloc_size = min_alloc_size;
- ht->min_alloc_order = get_count_order_ulong(min_alloc_size);
+ ht->min_nr_alloc_buckets = min_nr_alloc_buckets;
+ ht->min_alloc_buckets_order = get_count_order_ulong(min_nr_alloc_buckets);
+ ht->max_nr_buckets = max_nr_buckets;
cds_lfht_create_bucket(ht, 1UL << order);
ht->t.size = 1UL << order;
return ht;
unsigned long count)
{
count = max(count, MIN_TABLE_SIZE);
+ count = min(count, ht->max_nr_buckets);
uatomic_set(&ht->t.resize_target, count);
}
{
unsigned long target_size = size << growth;
+ target_size = min(target_size, ht->max_nr_buckets);
if (resize_target_grow(ht, target_size) >= target_size)
return;
if (!(ht->flags & CDS_LFHT_AUTO_RESIZE))
return;
count = max(count, MIN_TABLE_SIZE);
+ count = min(count, ht->max_nr_buckets);
if (count == size)
return; /* Already the right size, no resize needed */
if (count > size) { /* lazy grow */