Background threads: fix an indexing bug.
We have a buffer overrun that manifests in the case where arena indices higher than the number of CPUs are accessed before arena indices lower than the number of CPUs. This fixes the bug and adds a test.
This commit is contained in:
parent
dd7e283b6f
commit
26b1c13982
@ -162,6 +162,7 @@ TESTS_UNIT := \
|
|||||||
$(srcroot)test/unit/arena_reset.c \
|
$(srcroot)test/unit/arena_reset.c \
|
||||||
$(srcroot)test/unit/atomic.c \
|
$(srcroot)test/unit/atomic.c \
|
||||||
$(srcroot)test/unit/background_thread.c \
|
$(srcroot)test/unit/background_thread.c \
|
||||||
|
$(srcroot)test/unit/background_thread_enable.c \
|
||||||
$(srcroot)test/unit/base.c \
|
$(srcroot)test/unit/base.c \
|
||||||
$(srcroot)test/unit/bitmap.c \
|
$(srcroot)test/unit/bitmap.c \
|
||||||
$(srcroot)test/unit/ckh.c \
|
$(srcroot)test/unit/ckh.c \
|
||||||
|
@ -600,7 +600,8 @@ background_threads_enable(tsd_t *tsd) {
|
|||||||
arena_get(tsd_tsdn(tsd), i, false) == NULL) {
|
arena_get(tsd_tsdn(tsd), i, false) == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
background_thread_info_t *info = &background_thread_info[i];
|
background_thread_info_t *info = &background_thread_info[
|
||||||
|
i % ncpus];
|
||||||
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
|
||||||
assert(info->state == background_thread_stopped);
|
assert(info->state == background_thread_stopped);
|
||||||
background_thread_init(tsd, info);
|
background_thread_init(tsd, info);
|
||||||
|
34
test/unit/background_thread_enable.c
Normal file
34
test/unit/background_thread_enable.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "test/jemalloc_test.h"
|
||||||
|
|
||||||
|
const char *malloc_conf = "background_thread:false,narenas:1";
|
||||||
|
|
||||||
|
TEST_BEGIN(test_deferred) {
|
||||||
|
test_skip_if(!have_background_thread);
|
||||||
|
|
||||||
|
unsigned id;
|
||||||
|
size_t sz_u = sizeof(unsigned);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 10 here is somewhat arbitrary, except insofar as we want to ensure
|
||||||
|
* that the number of background threads is smaller than the number of
|
||||||
|
* arenas. I'll ragequit long before we have to spin up 10 threads per
|
||||||
|
* cpu to handle background purging, so this is a conservative
|
||||||
|
* approximation.
|
||||||
|
*/
|
||||||
|
for (unsigned i = 0; i < 10 * ncpus; i++) {
|
||||||
|
assert_d_eq(mallctl("arenas.create", &id, &sz_u, NULL, 0), 0,
|
||||||
|
"Failed to create arena");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enable = true;
|
||||||
|
size_t sz_b = sizeof(bool);
|
||||||
|
assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0,
|
||||||
|
"Failed to enable background threads");
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void) {
|
||||||
|
return test_no_reentrancy(
|
||||||
|
test_deferred);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user