1a0698ed9Schristos #include "test/jemalloc_test.h" 2a0698ed9Schristos 3a0698ed9Schristos static const bool config_stats = 4a0698ed9Schristos #ifdef JEMALLOC_STATS 5a0698ed9Schristos true 6a0698ed9Schristos #else 7a0698ed9Schristos false 8a0698ed9Schristos #endif 9a0698ed9Schristos ; 10a0698ed9Schristos 11a0698ed9Schristos void * 12a0698ed9Schristos thd_start(void *arg) { 13a0698ed9Schristos int err; 14a0698ed9Schristos void *p; 15a0698ed9Schristos uint64_t a0, a1, d0, d1; 16a0698ed9Schristos uint64_t *ap0, *ap1, *dp0, *dp1; 17a0698ed9Schristos size_t sz, usize; 18a0698ed9Schristos 19a0698ed9Schristos sz = sizeof(a0); 20a0698ed9Schristos if ((err = mallctl("thread.allocated", (void *)&a0, &sz, NULL, 0))) { 21a0698ed9Schristos if (err == ENOENT) { 22a0698ed9Schristos goto label_ENOENT; 23a0698ed9Schristos } 24a0698ed9Schristos test_fail("%s(): Error in mallctl(): %s", __func__, 25a0698ed9Schristos strerror(err)); 26a0698ed9Schristos } 27a0698ed9Schristos sz = sizeof(ap0); 28a0698ed9Schristos if ((err = mallctl("thread.allocatedp", (void *)&ap0, &sz, NULL, 0))) { 29a0698ed9Schristos if (err == ENOENT) { 30a0698ed9Schristos goto label_ENOENT; 31a0698ed9Schristos } 32a0698ed9Schristos test_fail("%s(): Error in mallctl(): %s", __func__, 33a0698ed9Schristos strerror(err)); 34a0698ed9Schristos } 35*7bdf38e5Schristos expect_u64_eq(*ap0, a0, 36a0698ed9Schristos "\"thread.allocatedp\" should provide a pointer to internal " 37a0698ed9Schristos "storage"); 38a0698ed9Schristos 39a0698ed9Schristos sz = sizeof(d0); 40a0698ed9Schristos if ((err = mallctl("thread.deallocated", (void *)&d0, &sz, NULL, 0))) { 41a0698ed9Schristos if (err == ENOENT) { 42a0698ed9Schristos goto label_ENOENT; 43a0698ed9Schristos } 44a0698ed9Schristos test_fail("%s(): Error in mallctl(): %s", __func__, 45a0698ed9Schristos strerror(err)); 46a0698ed9Schristos } 47a0698ed9Schristos sz = sizeof(dp0); 48a0698ed9Schristos if ((err = mallctl("thread.deallocatedp", (void *)&dp0, &sz, NULL, 49a0698ed9Schristos 0))) { 50a0698ed9Schristos if (err == ENOENT) { 51a0698ed9Schristos goto label_ENOENT; 52a0698ed9Schristos } 53a0698ed9Schristos test_fail("%s(): Error in mallctl(): %s", __func__, 54a0698ed9Schristos strerror(err)); 55a0698ed9Schristos } 56*7bdf38e5Schristos expect_u64_eq(*dp0, d0, 57a0698ed9Schristos "\"thread.deallocatedp\" should provide a pointer to internal " 58a0698ed9Schristos "storage"); 59a0698ed9Schristos 60a0698ed9Schristos p = malloc(1); 61*7bdf38e5Schristos expect_ptr_not_null(p, "Unexpected malloc() error"); 62a0698ed9Schristos 63a0698ed9Schristos sz = sizeof(a1); 64a0698ed9Schristos mallctl("thread.allocated", (void *)&a1, &sz, NULL, 0); 65a0698ed9Schristos sz = sizeof(ap1); 66a0698ed9Schristos mallctl("thread.allocatedp", (void *)&ap1, &sz, NULL, 0); 67*7bdf38e5Schristos expect_u64_eq(*ap1, a1, 68a0698ed9Schristos "Dereferenced \"thread.allocatedp\" value should equal " 69a0698ed9Schristos "\"thread.allocated\" value"); 70*7bdf38e5Schristos expect_ptr_eq(ap0, ap1, 71a0698ed9Schristos "Pointer returned by \"thread.allocatedp\" should not change"); 72a0698ed9Schristos 73*7bdf38e5Schristos usize = TEST_MALLOC_SIZE(p); 74*7bdf38e5Schristos expect_u64_le(a0 + usize, a1, 75a0698ed9Schristos "Allocated memory counter should increase by at least the amount " 76a0698ed9Schristos "explicitly allocated"); 77a0698ed9Schristos 78a0698ed9Schristos free(p); 79a0698ed9Schristos 80a0698ed9Schristos sz = sizeof(d1); 81a0698ed9Schristos mallctl("thread.deallocated", (void *)&d1, &sz, NULL, 0); 82a0698ed9Schristos sz = sizeof(dp1); 83a0698ed9Schristos mallctl("thread.deallocatedp", (void *)&dp1, &sz, NULL, 0); 84*7bdf38e5Schristos expect_u64_eq(*dp1, d1, 85a0698ed9Schristos "Dereferenced \"thread.deallocatedp\" value should equal " 86a0698ed9Schristos "\"thread.deallocated\" value"); 87*7bdf38e5Schristos expect_ptr_eq(dp0, dp1, 88a0698ed9Schristos "Pointer returned by \"thread.deallocatedp\" should not change"); 89a0698ed9Schristos 90*7bdf38e5Schristos expect_u64_le(d0 + usize, d1, 91a0698ed9Schristos "Deallocated memory counter should increase by at least the amount " 92a0698ed9Schristos "explicitly deallocated"); 93a0698ed9Schristos 94a0698ed9Schristos return NULL; 95a0698ed9Schristos label_ENOENT: 96*7bdf38e5Schristos expect_false(config_stats, 97a0698ed9Schristos "ENOENT should only be returned if stats are disabled"); 98a0698ed9Schristos test_skip("\"thread.allocated\" mallctl not available"); 99a0698ed9Schristos return NULL; 100a0698ed9Schristos } 101a0698ed9Schristos 102a0698ed9Schristos TEST_BEGIN(test_main_thread) { 103a0698ed9Schristos thd_start(NULL); 104a0698ed9Schristos } 105a0698ed9Schristos TEST_END 106a0698ed9Schristos 107a0698ed9Schristos TEST_BEGIN(test_subthread) { 108a0698ed9Schristos thd_t thd; 109a0698ed9Schristos 110a0698ed9Schristos thd_create(&thd, thd_start, NULL); 111a0698ed9Schristos thd_join(thd, NULL); 112a0698ed9Schristos } 113a0698ed9Schristos TEST_END 114a0698ed9Schristos 115a0698ed9Schristos int 116a0698ed9Schristos main(void) { 117a0698ed9Schristos /* Run tests multiple times to check for bad interactions. */ 118a0698ed9Schristos return test( 119a0698ed9Schristos test_main_thread, 120a0698ed9Schristos test_subthread, 121a0698ed9Schristos test_main_thread, 122a0698ed9Schristos test_subthread, 123a0698ed9Schristos test_main_thread); 124a0698ed9Schristos } 125