| #include "test/jemalloc_test.h" |
| |
| /* Threshold: 2 << 20 = 2097152. */ |
| const char *malloc_conf = "oversize_threshold:2097152"; |
| |
| #define HUGE_SZ (2 << 20) |
| #define SMALL_SZ (8) |
| |
| TEST_BEGIN(huge_bind_thread) { |
| unsigned arena1, arena2; |
| size_t sz = sizeof(unsigned); |
| |
| /* Bind to a manual arena. */ |
| expect_d_eq(mallctl("arenas.create", &arena1, &sz, NULL, 0), 0, |
| "Failed to create arena"); |
| expect_d_eq(mallctl("thread.arena", NULL, NULL, &arena1, |
| sizeof(arena1)), 0, "Fail to bind thread"); |
| |
| void *ptr = mallocx(HUGE_SZ, 0); |
| expect_ptr_not_null(ptr, "Fail to allocate huge size"); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, |
| sizeof(ptr)), 0, "Unexpected mallctl() failure"); |
| expect_u_eq(arena1, arena2, "Wrong arena used after binding"); |
| dallocx(ptr, 0); |
| |
| /* Switch back to arena 0. */ |
| test_skip_if(have_percpu_arena && |
| PERCPU_ARENA_ENABLED(opt_percpu_arena)); |
| arena2 = 0; |
| expect_d_eq(mallctl("thread.arena", NULL, NULL, &arena2, |
| sizeof(arena2)), 0, "Fail to bind thread"); |
| ptr = mallocx(SMALL_SZ, MALLOCX_TCACHE_NONE); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, |
| sizeof(ptr)), 0, "Unexpected mallctl() failure"); |
| expect_u_eq(arena2, 0, "Wrong arena used after binding"); |
| dallocx(ptr, MALLOCX_TCACHE_NONE); |
| |
| /* Then huge allocation should use the huge arena. */ |
| ptr = mallocx(HUGE_SZ, 0); |
| expect_ptr_not_null(ptr, "Fail to allocate huge size"); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, |
| sizeof(ptr)), 0, "Unexpected mallctl() failure"); |
| expect_u_ne(arena2, 0, "Wrong arena used after binding"); |
| expect_u_ne(arena1, arena2, "Wrong arena used after binding"); |
| dallocx(ptr, 0); |
| } |
| TEST_END |
| |
| TEST_BEGIN(huge_mallocx) { |
| unsigned arena1, arena2; |
| size_t sz = sizeof(unsigned); |
| |
| expect_d_eq(mallctl("arenas.create", &arena1, &sz, NULL, 0), 0, |
| "Failed to create arena"); |
| void *huge = mallocx(HUGE_SZ, MALLOCX_ARENA(arena1)); |
| expect_ptr_not_null(huge, "Fail to allocate huge size"); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &huge, |
| sizeof(huge)), 0, "Unexpected mallctl() failure"); |
| expect_u_eq(arena1, arena2, "Wrong arena used for mallocx"); |
| dallocx(huge, MALLOCX_ARENA(arena1)); |
| |
| void *huge2 = mallocx(HUGE_SZ, 0); |
| expect_ptr_not_null(huge, "Fail to allocate huge size"); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &huge2, |
| sizeof(huge2)), 0, "Unexpected mallctl() failure"); |
| expect_u_ne(arena1, arena2, |
| "Huge allocation should not come from the manual arena."); |
| expect_u_ne(arena2, 0, |
| "Huge allocation should not come from the arena 0."); |
| dallocx(huge2, 0); |
| } |
| TEST_END |
| |
| TEST_BEGIN(huge_allocation) { |
| unsigned arena1, arena2; |
| |
| void *ptr = mallocx(HUGE_SZ, 0); |
| expect_ptr_not_null(ptr, "Fail to allocate huge size"); |
| size_t sz = sizeof(unsigned); |
| expect_d_eq(mallctl("arenas.lookup", &arena1, &sz, &ptr, sizeof(ptr)), |
| 0, "Unexpected mallctl() failure"); |
| expect_u_gt(arena1, 0, "Huge allocation should not come from arena 0"); |
| dallocx(ptr, 0); |
| |
| ptr = mallocx(HUGE_SZ >> 1, 0); |
| expect_ptr_not_null(ptr, "Fail to allocate half huge size"); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, |
| sizeof(ptr)), 0, "Unexpected mallctl() failure"); |
| expect_u_ne(arena1, arena2, "Wrong arena used for half huge"); |
| dallocx(ptr, 0); |
| |
| ptr = mallocx(SMALL_SZ, MALLOCX_TCACHE_NONE); |
| expect_ptr_not_null(ptr, "Fail to allocate small size"); |
| expect_d_eq(mallctl("arenas.lookup", &arena2, &sz, &ptr, |
| sizeof(ptr)), 0, "Unexpected mallctl() failure"); |
| expect_u_ne(arena1, arena2, |
| "Huge and small should be from different arenas"); |
| dallocx(ptr, 0); |
| } |
| TEST_END |
| |
| int |
| main(void) { |
| return test( |
| huge_allocation, |
| huge_mallocx, |
| huge_bind_thread); |
| } |