return (value > 0) && (value & (value - 1)) == 0;
}
+static_inline int
+nextPowerOf2(int target)
+{
+ int next = 1;
+ /*
+ * Make sure we have a reasonable target and cannot overflow; callers
+ * should do their own range checks before we get here.
+ */
+ opr_Assert(target > 0 && target <= 0x40000000);
+ while (next < target) {
+ next *= 2;
+ }
+ return next;
+}
+
/**
* Create a new opr_cache.
*
opr_cache_init(struct opr_cache_opts *opts, struct opr_cache **a_cache)
{
struct opr_cache *cache;
+ int n_buckets = opts->n_buckets;
- if (opts->n_buckets < MIN_BUCKETS || opts->n_buckets > MAX_BUCKETS) {
- return EINVAL;
- }
- if (!isPowerOf2(opts->n_buckets)) {
+ if (n_buckets < MIN_BUCKETS || n_buckets > MAX_BUCKETS) {
return EINVAL;
}
if (opts->max_entries < MIN_ENTRIES || opts->max_entries > MAX_ENTRIES) {
return EINVAL;
}
+ n_buckets = nextPowerOf2(n_buckets);
+ opr_Assert(isPowerOf2(n_buckets));
+ opr_Assert(n_buckets >= MIN_BUCKETS);
+ opr_Assert(n_buckets <= MAX_BUCKETS);
+
cache = calloc(1, sizeof(*cache));
if (cache == NULL) {
return ENOMEM;
opr_mutex_init(&cache->lock);
cache->max_entries = opts->max_entries;
- cache->dict = opr_dict_Init(opts->n_buckets);
+ cache->dict = opr_dict_Init(n_buckets);
if (cache->dict == NULL) {
opr_cache_free(&cache);
return ENOMEM;
ok(opr_cache_init(&opts, &cache) != 0,
"Initializing a cache with a huge n_buckets fails");
- opts.n_buckets = 23;
+ opts.n_buckets = 1024*1024 + 1;
ok(opr_cache_init(&opts, &cache) != 0,
- "Initializing a cache with non-power-of-2 n_buckets fails");
+ "Initializing a cache with 1024*1024+1 n_buckets fails");
+
+ opts.n_buckets = 1024*1024;
+ code = opr_cache_init(&opts, &cache);
+ is_int(0, code,
+ "Initializing a cache with 1024*1024 n_buckets succeeds");
+ opr_cache_free(&cache);
+
+ opts.n_buckets = 1024*1024 - 1;
+ code = opr_cache_init(&opts, &cache);
+ is_int(0, code,
+ "Initializing a cache with 1024*1024-1 n_buckets succeeds");
+ opr_cache_free(&cache);
+
+ opts.n_buckets = 23;
+ code = opr_cache_init(&opts, &cache);
+ is_int(0, code,
+ "Initializing a cache with non-power-of-2 n_buckets succeeds");
+ opr_cache_free(&cache);
opts.n_buckets = 64;
opts.max_entries = 1;
{
int seed;
- plan(113 * 32);
+ plan(116 * 32);
for (seed = 0; seed < 32; seed++) {
run_seed(seed);