Home | History | Annotate | Line # | Download | only in unit
      1  1.1  christos #include "test/jemalloc_test.h"
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Under percpu_arena, binding a thread to a manual arena (an index at or above
      5  1.1  christos  * the per-CPU auto range) is one-way: percpu never reclaims it (see
      6  1.1  christos  * arena_choose_impl). Setting thread.arena back to an index in the auto range
      7  1.1  christos  * resumes per-CPU selection instead of failing with EPERM.
      8  1.1  christos  */
      9  1.1  christos TEST_BEGIN(test_thread_arena_resume_percpu) {
     10  1.1  christos 	test_skip_if(!have_percpu_arena
     11  1.1  christos 	    || !PERCPU_ARENA_ENABLED(opt_percpu_arena));
     12  1.1  christos 
     13  1.1  christos 	unsigned limit = percpu_arena_ind_limit(opt_percpu_arena);
     14  1.1  christos 	/* Bypass the tcache so every allocation and free hits the arena. */
     15  1.1  christos 	const int flags = MALLOCX_TCACHE_NONE;
     16  1.1  christos 
     17  1.1  christos 	void *warm = mallocx(1, 0);
     18  1.1  christos 	expect_ptr_not_null(warm, "Unexpected mallocx() failure");
     19  1.1  christos 	dallocx(warm, 0);
     20  1.1  christos 
     21  1.1  christos 	unsigned cur;
     22  1.1  christos 	size_t sz = sizeof(cur);
     23  1.1  christos 	expect_d_eq(mallctl("thread.arena", (void *)&cur, &sz, NULL, 0), 0,
     24  1.1  christos 	    "Unexpected mallctl() failure");
     25  1.1  christos 	expect_u_lt(cur, limit, "Thread should start on a per-CPU arena");
     26  1.1  christos 
     27  1.1  christos 	unsigned manual;
     28  1.1  christos 	sz = sizeof(manual);
     29  1.1  christos 	expect_d_eq(mallctl("arenas.create", (void *)&manual, &sz, NULL, 0), 0,
     30  1.1  christos 	    "Unexpected arenas.create() failure");
     31  1.1  christos 	expect_u_ge(manual, limit, "A manual arena is outside the per-CPU range");
     32  1.1  christos 
     33  1.1  christos 	unsigned old;
     34  1.1  christos 	sz = sizeof(old);
     35  1.1  christos 	expect_d_eq(mallctl("thread.arena", (void *)&old, &sz, (void *)&manual,
     36  1.1  christos 	    sizeof(manual)), 0, "Binding to a manual arena should be allowed");
     37  1.1  christos 	sz = sizeof(cur);
     38  1.1  christos 	expect_d_eq(mallctl("thread.arena", (void *)&cur, &sz, NULL, 0), 0,
     39  1.1  christos 	    "Unexpected mallctl() failure");
     40  1.1  christos 	expect_u_eq(cur, manual, "Thread should be bound to the manual arena");
     41  1.1  christos 
     42  1.1  christos 	void *p_manual = mallocx(1024, flags);
     43  1.1  christos 	expect_ptr_not_null(p_manual, "Unexpected mallocx() failure");
     44  1.1  christos 	unsigned found;
     45  1.1  christos 	sz = sizeof(found);
     46  1.1  christos 	expect_d_eq(mallctl("arenas.lookup", (void *)&found, &sz,
     47  1.1  christos 	    (void *)&p_manual, sizeof(p_manual)), 0,
     48  1.1  christos 	    "Unexpected arenas.lookup() failure");
     49  1.1  christos 	expect_u_eq(found, manual, "Allocation should come from the manual arena");
     50  1.1  christos 
     51  1.1  christos 	void *scratch = mallocx(1024, flags);
     52  1.1  christos 	expect_ptr_not_null(scratch, "Unexpected mallocx() failure");
     53  1.1  christos 	dallocx(scratch, flags);
     54  1.1  christos 
     55  1.1  christos 	unsigned resume = 0;
     56  1.1  christos 	expect_d_eq(mallctl("thread.arena", NULL, NULL, (void *)&resume,
     57  1.1  christos 	    sizeof(resume)), 0, "Should resume per-CPU selection, not fail");
     58  1.1  christos 	sz = sizeof(cur);
     59  1.1  christos 	expect_d_eq(mallctl("thread.arena", (void *)&cur, &sz, NULL, 0), 0,
     60  1.1  christos 	    "Unexpected mallctl() failure");
     61  1.1  christos 	expect_u_lt(cur, limit, "Thread should be back on a per-CPU arena");
     62  1.1  christos 
     63  1.1  christos 	void *p_percpu = mallocx(1024, flags);
     64  1.1  christos 	expect_ptr_not_null(p_percpu, "Unexpected mallocx() failure");
     65  1.1  christos 	sz = sizeof(found);
     66  1.1  christos 	expect_d_eq(mallctl("arenas.lookup", (void *)&found, &sz,
     67  1.1  christos 	    (void *)&p_percpu, sizeof(p_percpu)), 0,
     68  1.1  christos 	    "Unexpected arenas.lookup() failure");
     69  1.1  christos 	expect_u_lt(found, limit, "Allocation should come from a per-CPU arena");
     70  1.1  christos 	dallocx(p_percpu, flags);
     71  1.1  christos 
     72  1.1  christos 	/* Free the manual-arena region while bound to a different arena. */
     73  1.1  christos 	dallocx(p_manual, flags);
     74  1.1  christos }
     75  1.1  christos TEST_END
     76  1.1  christos 
     77  1.1  christos int
     78  1.1  christos main(void) {
     79  1.1  christos 	return test(
     80  1.1  christos 	    test_thread_arena_resume_percpu);
     81  1.1  christos }
     82