Skip to content

Commit 112a80c

Browse files
committed
prevent from deadlock in DP bucket_can_pool()
1 parent fcf0a37 commit 112a80c

File tree

1 file changed

+22
-25
lines changed

1 file changed

+22
-25
lines changed

src/pool/pool_disjoint.c

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
// Forward declarations
3737
static void bucket_update_stats(bucket_t *bucket, int in_use, int in_pool);
3838
static bool bucket_can_pool(bucket_t *bucket);
39-
static void bucket_decrement_pool(bucket_t *bucket);
4039
static slab_list_item_t *bucket_get_avail_slab(bucket_t *bucket,
4140
bool *from_pool);
4241

@@ -318,6 +317,7 @@ static void bucket_free_chunk(bucket_t *bucket, void *ptr, slab_t *slab,
318317
assert(slab_it->val != NULL);
319318
pool_unregister_slab(bucket->pool, slab_it->val);
320319
DL_DELETE(bucket->available_slabs, slab_it);
320+
assert(bucket->available_slabs_num > 0);
321321
bucket->available_slabs_num--;
322322
destroy_slab(slab_it->val);
323323
}
@@ -383,10 +383,16 @@ static slab_list_item_t *bucket_get_avail_slab(bucket_t *bucket,
383383
// Allocation from existing slab is treated as from pool for statistics.
384384
*from_pool = true;
385385
if (slab->num_chunks_allocated == 0) {
386+
assert(bucket->chunked_slabs_in_pool > 0);
386387
// If this was an empty slab, it was in the pool.
387388
// Now it is no longer in the pool, so update count.
388389
--bucket->chunked_slabs_in_pool;
389-
bucket_decrement_pool(bucket);
390+
uint64_t size_to_sub = bucket_slab_alloc_size(bucket);
391+
uint64_t old_size = utils_fetch_and_sub_u64(
392+
&bucket->shared_limits->total_size, size_to_sub);
393+
(void)old_size;
394+
assert(old_size >= size_to_sub);
395+
bucket_update_stats(bucket, 1, -1);
390396
}
391397
}
392398

@@ -422,36 +428,27 @@ static void bucket_update_stats(bucket_t *bucket, int in_use, int in_pool) {
422428
in_pool * bucket_slab_alloc_size(bucket);
423429
}
424430

425-
static void bucket_decrement_pool(bucket_t *bucket) {
426-
bucket_update_stats(bucket, 1, -1);
427-
utils_fetch_and_add64(&bucket->shared_limits->total_size,
428-
-(long long)bucket_slab_alloc_size(bucket));
429-
}
430-
431431
static bool bucket_can_pool(bucket_t *bucket) {
432432
size_t new_free_slabs_in_bucket;
433433

434434
new_free_slabs_in_bucket = bucket->chunked_slabs_in_pool + 1;
435435

436436
// we keep at most params.capacity slabs in the pool
437437
if (bucket_max_pooled_slabs(bucket) >= new_free_slabs_in_bucket) {
438-
size_t pool_size = 0;
439-
utils_atomic_load_acquire(&bucket->shared_limits->total_size,
440-
&pool_size);
441-
while (true) {
442-
size_t new_pool_size = pool_size + bucket_slab_alloc_size(bucket);
443-
444-
if (bucket->shared_limits->max_size < new_pool_size) {
445-
break;
446-
}
447-
448-
if (utils_compare_exchange(&bucket->shared_limits->total_size,
449-
&pool_size, &new_pool_size)) {
450-
++bucket->chunked_slabs_in_pool;
451-
452-
bucket_update_stats(bucket, -1, 1);
453-
return true;
454-
}
438+
439+
uint64_t size_to_add = bucket_slab_alloc_size(bucket);
440+
size_t previous_size = utils_fetch_and_add_u64(
441+
&bucket->shared_limits->total_size, size_to_add);
442+
443+
if (previous_size + size_to_add <= bucket->shared_limits->max_size) {
444+
++bucket->chunked_slabs_in_pool;
445+
bucket_update_stats(bucket, -1, 1);
446+
return true;
447+
} else {
448+
uint64_t old = utils_fetch_and_sub_u64(
449+
&bucket->shared_limits->total_size, size_to_add);
450+
(void)old;
451+
assert(old >= size_to_add);
455452
}
456453
}
457454

0 commit comments

Comments
 (0)