cache_bin: Separate out local and remote accesses.
This fixes an incorrect debug-mode assert: - T1 starts an arena stats update and reads stack_head from another thread's cache bin, when that cache bin has 1 item in it. - T2 allocates from that cache bin. The cache_bin's stack_head now points to a NULL pointer, since the cache bin is empty. - T1 Re-reads the cache_bin's stack_head to perform an assertion check (since it previously saw that the bin was empty, whatever stack_head points to should be non-NULL).
This commit is contained in:
committed by
David Goldblatt
parent
14d689c0f9
commit
a011c4c22d
@@ -6,14 +6,15 @@ do_fill_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
cache_bin_sz_t nfill_succeed) {
|
||||
bool success;
|
||||
void *ptr;
|
||||
assert_true(cache_bin_ncached_get(bin, info) == 0, "");
|
||||
assert_true(cache_bin_ncached_get_local(bin, info) == 0, "");
|
||||
CACHE_BIN_PTR_ARRAY_DECLARE(arr, nfill_attempt);
|
||||
cache_bin_init_ptr_array_for_fill(bin, info, &arr, nfill_attempt);
|
||||
for (cache_bin_sz_t i = 0; i < nfill_succeed; i++) {
|
||||
arr.ptr[i] = &ptrs[i];
|
||||
}
|
||||
cache_bin_finish_fill(bin, info, &arr, nfill_succeed);
|
||||
expect_true(cache_bin_ncached_get(bin, info) == nfill_succeed, "");
|
||||
expect_true(cache_bin_ncached_get_local(bin, info) == nfill_succeed,
|
||||
"");
|
||||
cache_bin_low_water_set(bin);
|
||||
|
||||
for (cache_bin_sz_t i = 0; i < nfill_succeed; i++) {
|
||||
@@ -24,7 +25,7 @@ do_fill_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
expect_true(cache_bin_low_water_get(bin, info)
|
||||
== nfill_succeed - i - 1, "");
|
||||
}
|
||||
expect_true(cache_bin_ncached_get(bin, info) == 0, "");
|
||||
expect_true(cache_bin_ncached_get_local(bin, info) == 0, "");
|
||||
expect_true(cache_bin_low_water_get(bin, info) == 0, "");
|
||||
}
|
||||
|
||||
@@ -32,7 +33,7 @@ static void
|
||||
do_flush_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
cache_bin_sz_t nfill, cache_bin_sz_t nflush) {
|
||||
bool success;
|
||||
assert_true(cache_bin_ncached_get(bin, info) == 0, "");
|
||||
assert_true(cache_bin_ncached_get_local(bin, info) == 0, "");
|
||||
|
||||
for (cache_bin_sz_t i = 0; i < nfill; i++) {
|
||||
success = cache_bin_dalloc_easy(bin, &ptrs[i]);
|
||||
@@ -46,8 +47,9 @@ do_flush_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
}
|
||||
cache_bin_finish_flush(bin, info, &arr, nflush);
|
||||
|
||||
expect_true(cache_bin_ncached_get(bin, info) == nfill - nflush, "");
|
||||
while (cache_bin_ncached_get(bin, info) > 0) {
|
||||
expect_true(cache_bin_ncached_get_local(bin, info) == nfill - nflush,
|
||||
"");
|
||||
while (cache_bin_ncached_get_local(bin, info) > 0) {
|
||||
cache_bin_alloc(bin, &success);
|
||||
}
|
||||
}
|
||||
@@ -55,14 +57,14 @@ do_flush_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
static void
|
||||
do_batch_alloc_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
cache_bin_sz_t nfill, size_t batch) {
|
||||
assert_true(cache_bin_ncached_get(bin, info) == 0, "");
|
||||
assert_true(cache_bin_ncached_get_local(bin, info) == 0, "");
|
||||
CACHE_BIN_PTR_ARRAY_DECLARE(arr, nfill);
|
||||
cache_bin_init_ptr_array_for_fill(bin, info, &arr, nfill);
|
||||
for (cache_bin_sz_t i = 0; i < nfill; i++) {
|
||||
arr.ptr[i] = &ptrs[i];
|
||||
}
|
||||
cache_bin_finish_fill(bin, info, &arr, nfill);
|
||||
assert_true(cache_bin_ncached_get(bin, info) == nfill, "");
|
||||
assert_true(cache_bin_ncached_get_local(bin, info) == nfill, "");
|
||||
cache_bin_low_water_set(bin);
|
||||
|
||||
void **out = malloc((batch + 1) * sizeof(void *));
|
||||
@@ -73,7 +75,7 @@ do_batch_alloc_test(cache_bin_t *bin, cache_bin_info_t *info, void **ptrs,
|
||||
}
|
||||
expect_true(cache_bin_low_water_get(bin, info) == nfill -
|
||||
(cache_bin_sz_t)n, "");
|
||||
while (cache_bin_ncached_get(bin, info) > 0) {
|
||||
while (cache_bin_ncached_get_local(bin, info) > 0) {
|
||||
bool success;
|
||||
cache_bin_alloc(bin, &success);
|
||||
}
|
||||
@@ -104,7 +106,7 @@ TEST_BEGIN(test_cache_bin) {
|
||||
|
||||
/* Initialize to empty; should then have 0 elements. */
|
||||
expect_d_eq(ncached_max, cache_bin_info_ncached_max(&info), "");
|
||||
expect_true(cache_bin_ncached_get(&bin, &info) == 0, "");
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info) == 0, "");
|
||||
expect_true(cache_bin_low_water_get(&bin, &info) == 0, "");
|
||||
|
||||
ptr = cache_bin_alloc_easy(&bin, &success);
|
||||
@@ -122,14 +124,15 @@ TEST_BEGIN(test_cache_bin) {
|
||||
void **ptrs = mallocx(sizeof(void *) * (ncached_max + 1), 0);
|
||||
assert_ptr_not_null(ptrs, "Unexpected mallocx failure");
|
||||
for (cache_bin_sz_t i = 0; i < ncached_max; i++) {
|
||||
expect_true(cache_bin_ncached_get(&bin, &info) == i, "");
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info) == i, "");
|
||||
success = cache_bin_dalloc_easy(&bin, &ptrs[i]);
|
||||
expect_true(success,
|
||||
"Should be able to dalloc into a non-full cache bin.");
|
||||
expect_true(cache_bin_low_water_get(&bin, &info) == 0,
|
||||
"Pushes and pops shouldn't change low water of zero.");
|
||||
}
|
||||
expect_true(cache_bin_ncached_get(&bin, &info) == ncached_max, "");
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info) == ncached_max,
|
||||
"");
|
||||
success = cache_bin_dalloc_easy(&bin, &ptrs[ncached_max]);
|
||||
expect_false(success, "Shouldn't be able to dalloc into a full bin.");
|
||||
|
||||
@@ -138,7 +141,7 @@ TEST_BEGIN(test_cache_bin) {
|
||||
for (cache_bin_sz_t i = 0; i < ncached_max; i++) {
|
||||
expect_true(cache_bin_low_water_get(&bin, &info)
|
||||
== ncached_max - i, "");
|
||||
expect_true(cache_bin_ncached_get(&bin, &info)
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info)
|
||||
== ncached_max - i, "");
|
||||
/*
|
||||
* This should fail -- the easy variant can't change the low
|
||||
@@ -149,7 +152,7 @@ TEST_BEGIN(test_cache_bin) {
|
||||
expect_false(success, "");
|
||||
expect_true(cache_bin_low_water_get(&bin, &info)
|
||||
== ncached_max - i, "");
|
||||
expect_true(cache_bin_ncached_get(&bin, &info)
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info)
|
||||
== ncached_max - i, "");
|
||||
|
||||
/* This should succeed, though. */
|
||||
@@ -159,11 +162,11 @@ TEST_BEGIN(test_cache_bin) {
|
||||
"Alloc should pop in stack order");
|
||||
expect_true(cache_bin_low_water_get(&bin, &info)
|
||||
== ncached_max - i - 1, "");
|
||||
expect_true(cache_bin_ncached_get(&bin, &info)
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info)
|
||||
== ncached_max - i - 1, "");
|
||||
}
|
||||
/* Now we're empty -- all alloc attempts should fail. */
|
||||
expect_true(cache_bin_ncached_get(&bin, &info) == 0, "");
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info) == 0, "");
|
||||
ptr = cache_bin_alloc_easy(&bin, &success);
|
||||
expect_ptr_null(ptr, "");
|
||||
expect_false(success, "");
|
||||
@@ -179,7 +182,8 @@ TEST_BEGIN(test_cache_bin) {
|
||||
for (cache_bin_sz_t i = ncached_max / 2; i < ncached_max; i++) {
|
||||
cache_bin_dalloc_easy(&bin, &ptrs[i]);
|
||||
}
|
||||
expect_true(cache_bin_ncached_get(&bin, &info) == ncached_max, "");
|
||||
expect_true(cache_bin_ncached_get_local(&bin, &info) == ncached_max,
|
||||
"");
|
||||
for (cache_bin_sz_t i = ncached_max - 1; i >= ncached_max / 2; i--) {
|
||||
/*
|
||||
* Size is bigger than low water -- the reduced version should
|
||||
@@ -195,7 +199,7 @@ TEST_BEGIN(test_cache_bin) {
|
||||
expect_ptr_null(ptr, "");
|
||||
|
||||
/* We're going to test filling -- we must be empty to start. */
|
||||
while (cache_bin_ncached_get(&bin, &info)) {
|
||||
while (cache_bin_ncached_get_local(&bin, &info)) {
|
||||
cache_bin_alloc(&bin, &success);
|
||||
expect_true(success, "");
|
||||
}
|
||||
|
Reference in New Issue
Block a user