123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679 |
- #include "test/jemalloc_test.h"
- #include "jemalloc/internal/prof_recent.h"
- /* As specified in the shell script */
- #define OPT_ALLOC_MAX 3
- /* Invariant before and after every test (when config_prof is on) */
- static void
- confirm_prof_setup() {
- /* Options */
- assert_true(opt_prof, "opt_prof not on");
- assert_true(opt_prof_active, "opt_prof_active not on");
- assert_zd_eq(opt_prof_recent_alloc_max, OPT_ALLOC_MAX,
- "opt_prof_recent_alloc_max not set correctly");
- /* Dynamics */
- assert_true(prof_active_state, "prof_active not on");
- assert_zd_eq(prof_recent_alloc_max_ctl_read(), OPT_ALLOC_MAX,
- "prof_recent_alloc_max not set correctly");
- }
- TEST_BEGIN(test_confirm_setup) {
- test_skip_if(!config_prof);
- confirm_prof_setup();
- }
- TEST_END
- TEST_BEGIN(test_prof_recent_off) {
- test_skip_if(config_prof);
- const ssize_t past_ref = 0, future_ref = 0;
- const size_t len_ref = sizeof(ssize_t);
- ssize_t past = past_ref, future = future_ref;
- size_t len = len_ref;
- #define ASSERT_SHOULD_FAIL(opt, a, b, c, d) do { \
- assert_d_eq(mallctl("experimental.prof_recent." opt, a, b, c, \
- d), ENOENT, "Should return ENOENT when config_prof is off");\
- assert_zd_eq(past, past_ref, "output was touched"); \
- assert_zu_eq(len, len_ref, "output length was touched"); \
- assert_zd_eq(future, future_ref, "input was touched"); \
- } while (0)
- ASSERT_SHOULD_FAIL("alloc_max", NULL, NULL, NULL, 0);
- ASSERT_SHOULD_FAIL("alloc_max", &past, &len, NULL, 0);
- ASSERT_SHOULD_FAIL("alloc_max", NULL, NULL, &future, len);
- ASSERT_SHOULD_FAIL("alloc_max", &past, &len, &future, len);
- #undef ASSERT_SHOULD_FAIL
- }
- TEST_END
- TEST_BEGIN(test_prof_recent_on) {
- test_skip_if(!config_prof);
- ssize_t past, future;
- size_t len = sizeof(ssize_t);
- confirm_prof_setup();
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, NULL, 0), 0, "no-op mallctl should be allowed");
- confirm_prof_setup();
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- &past, &len, NULL, 0), 0, "Read error");
- expect_zd_eq(past, OPT_ALLOC_MAX, "Wrong read result");
- future = OPT_ALLOC_MAX + 1;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, len), 0, "Write error");
- future = -1;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- &past, &len, &future, len), 0, "Read/write error");
- expect_zd_eq(past, OPT_ALLOC_MAX + 1, "Wrong read result");
- future = -2;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- &past, &len, &future, len), EINVAL,
- "Invalid write should return EINVAL");
- expect_zd_eq(past, OPT_ALLOC_MAX + 1,
- "Output should not be touched given invalid write");
- future = OPT_ALLOC_MAX;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- &past, &len, &future, len), 0, "Read/write error");
- expect_zd_eq(past, -1, "Wrong read result");
- future = OPT_ALLOC_MAX + 2;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- &past, &len, &future, len * 2), EINVAL,
- "Invalid write should return EINVAL");
- expect_zd_eq(past, -1,
- "Output should not be touched given invalid write");
- confirm_prof_setup();
- }
- TEST_END
- /* Reproducible sequence of request sizes */
- #define NTH_REQ_SIZE(n) ((n) * 97 + 101)
- static void
- confirm_malloc(void *p) {
- assert_ptr_not_null(p, "malloc failed unexpectedly");
- edata_t *e = emap_edata_lookup(TSDN_NULL, &arena_emap_global, p);
- assert_ptr_not_null(e, "NULL edata for living pointer");
- prof_recent_t *n = edata_prof_recent_alloc_get_no_lock_test(e);
- assert_ptr_not_null(n, "Record in edata should not be NULL");
- expect_ptr_not_null(n->alloc_tctx,
- "alloc_tctx in record should not be NULL");
- expect_ptr_eq(e, prof_recent_alloc_edata_get_no_lock_test(n),
- "edata pointer in record is not correct");
- expect_ptr_null(n->dalloc_tctx, "dalloc_tctx in record should be NULL");
- }
- static void
- confirm_record_size(prof_recent_t *n, unsigned kth) {
- expect_zu_eq(n->size, NTH_REQ_SIZE(kth),
- "Recorded allocation size is wrong");
- }
- static void
- confirm_record_living(prof_recent_t *n) {
- expect_ptr_not_null(n->alloc_tctx,
- "alloc_tctx in record should not be NULL");
- edata_t *edata = prof_recent_alloc_edata_get_no_lock_test(n);
- assert_ptr_not_null(edata,
- "Recorded edata should not be NULL for living pointer");
- expect_ptr_eq(n, edata_prof_recent_alloc_get_no_lock_test(edata),
- "Record in edata is not correct");
- expect_ptr_null(n->dalloc_tctx, "dalloc_tctx in record should be NULL");
- }
- static void
- confirm_record_released(prof_recent_t *n) {
- expect_ptr_not_null(n->alloc_tctx,
- "alloc_tctx in record should not be NULL");
- expect_ptr_null(prof_recent_alloc_edata_get_no_lock_test(n),
- "Recorded edata should be NULL for released pointer");
- expect_ptr_not_null(n->dalloc_tctx,
- "dalloc_tctx in record should not be NULL for released pointer");
- }
- TEST_BEGIN(test_prof_recent_alloc) {
- test_skip_if(!config_prof);
- bool b;
- unsigned i, c;
- size_t req_size;
- void *p;
- prof_recent_t *n;
- ssize_t future;
- confirm_prof_setup();
- /*
- * First batch of 2 * OPT_ALLOC_MAX allocations. After the
- * (OPT_ALLOC_MAX - 1)'th allocation the recorded allocations should
- * always be the last OPT_ALLOC_MAX allocations coming from here.
- */
- for (i = 0; i < 2 * OPT_ALLOC_MAX; ++i) {
- req_size = NTH_REQ_SIZE(i);
- p = malloc(req_size);
- confirm_malloc(p);
- if (i < OPT_ALLOC_MAX - 1) {
- assert_false(ql_empty(&prof_recent_alloc_list),
- "Empty recent allocation");
- free(p);
- /*
- * The recorded allocations may still include some
- * other allocations before the test run started,
- * so keep allocating without checking anything.
- */
- continue;
- }
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- ++c;
- confirm_record_size(n, i + c - OPT_ALLOC_MAX);
- if (c == OPT_ALLOC_MAX) {
- confirm_record_living(n);
- } else {
- confirm_record_released(n);
- }
- }
- assert_u_eq(c, OPT_ALLOC_MAX,
- "Incorrect total number of allocations");
- free(p);
- }
- confirm_prof_setup();
- b = false;
- assert_d_eq(mallctl("prof.active", NULL, NULL, &b, sizeof(bool)), 0,
- "mallctl for turning off prof_active failed");
- /*
- * Second batch of OPT_ALLOC_MAX allocations. Since prof_active is
- * turned off, this batch shouldn't be recorded.
- */
- for (; i < 3 * OPT_ALLOC_MAX; ++i) {
- req_size = NTH_REQ_SIZE(i);
- p = malloc(req_size);
- assert_ptr_not_null(p, "malloc failed unexpectedly");
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- confirm_record_size(n, c + OPT_ALLOC_MAX);
- confirm_record_released(n);
- ++c;
- }
- assert_u_eq(c, OPT_ALLOC_MAX,
- "Incorrect total number of allocations");
- free(p);
- }
- b = true;
- assert_d_eq(mallctl("prof.active", NULL, NULL, &b, sizeof(bool)), 0,
- "mallctl for turning on prof_active failed");
- confirm_prof_setup();
- /*
- * Third batch of OPT_ALLOC_MAX allocations. Since prof_active is
- * turned back on, they should be recorded, and in the list of recorded
- * allocations they should follow the first batch rather than the
- * second batch.
- */
- for (; i < 4 * OPT_ALLOC_MAX; ++i) {
- req_size = NTH_REQ_SIZE(i);
- p = malloc(req_size);
- confirm_malloc(p);
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- ++c;
- confirm_record_size(n,
- /* Is the allocation from the third batch? */
- i + c - OPT_ALLOC_MAX >= 3 * OPT_ALLOC_MAX ?
- /* If yes, then it's just recorded. */
- i + c - OPT_ALLOC_MAX :
- /*
- * Otherwise, it should come from the first batch
- * instead of the second batch.
- */
- i + c - 2 * OPT_ALLOC_MAX);
- if (c == OPT_ALLOC_MAX) {
- confirm_record_living(n);
- } else {
- confirm_record_released(n);
- }
- }
- assert_u_eq(c, OPT_ALLOC_MAX,
- "Incorrect total number of allocations");
- free(p);
- }
- /* Increasing the limit shouldn't alter the list of records. */
- future = OPT_ALLOC_MAX + 1;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- confirm_record_size(n, c + 3 * OPT_ALLOC_MAX);
- confirm_record_released(n);
- ++c;
- }
- assert_u_eq(c, OPT_ALLOC_MAX,
- "Incorrect total number of allocations");
- /*
- * Decreasing the limit shouldn't alter the list of records as long as
- * the new limit is still no less than the length of the list.
- */
- future = OPT_ALLOC_MAX;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- confirm_record_size(n, c + 3 * OPT_ALLOC_MAX);
- confirm_record_released(n);
- ++c;
- }
- assert_u_eq(c, OPT_ALLOC_MAX,
- "Incorrect total number of allocations");
- /*
- * Decreasing the limit should shorten the list of records if the new
- * limit is less than the length of the list.
- */
- future = OPT_ALLOC_MAX - 1;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- ++c;
- confirm_record_size(n, c + 3 * OPT_ALLOC_MAX);
- confirm_record_released(n);
- }
- assert_u_eq(c, OPT_ALLOC_MAX - 1,
- "Incorrect total number of allocations");
- /* Setting to unlimited shouldn't alter the list of records. */
- future = -1;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- c = 0;
- ql_foreach(n, &prof_recent_alloc_list, link) {
- ++c;
- confirm_record_size(n, c + 3 * OPT_ALLOC_MAX);
- confirm_record_released(n);
- }
- assert_u_eq(c, OPT_ALLOC_MAX - 1,
- "Incorrect total number of allocations");
- /* Downshift to only one record. */
- future = 1;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- assert_false(ql_empty(&prof_recent_alloc_list), "Recent list is empty");
- n = ql_first(&prof_recent_alloc_list);
- confirm_record_size(n, 4 * OPT_ALLOC_MAX - 1);
- confirm_record_released(n);
- n = ql_next(&prof_recent_alloc_list, n, link);
- assert_ptr_null(n, "Recent list should only contain one record");
- /* Completely turn off. */
- future = 0;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- assert_true(ql_empty(&prof_recent_alloc_list),
- "Recent list should be empty");
- /* Restore the settings. */
- future = OPT_ALLOC_MAX;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- assert_true(ql_empty(&prof_recent_alloc_list),
- "Recent list should be empty");
- confirm_prof_setup();
- }
- TEST_END
- #undef NTH_REQ_SIZE
- #define DUMP_OUT_SIZE 4096
- static char dump_out[DUMP_OUT_SIZE];
- static size_t dump_out_len = 0;
- static void
- test_dump_write_cb(void *not_used, const char *str) {
- size_t len = strlen(str);
- assert(dump_out_len + len < DUMP_OUT_SIZE);
- memcpy(dump_out + dump_out_len, str, len + 1);
- dump_out_len += len;
- }
- static void
- call_dump() {
- static void *in[2] = {test_dump_write_cb, NULL};
- dump_out_len = 0;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_dump",
- NULL, NULL, in, sizeof(in)), 0, "Dump mallctl raised error");
- }
- typedef struct {
- size_t size;
- size_t usize;
- bool released;
- } confirm_record_t;
- #define DUMP_ERROR "Dump output is wrong"
- static void
- confirm_record(const char *template, const confirm_record_t *records,
- const size_t n_records) {
- static const char *types[2] = {"alloc", "dalloc"};
- static char buf[64];
- /*
- * The template string would be in the form of:
- * "{...,\"recent_alloc\":[]}",
- * and dump_out would be in the form of:
- * "{...,\"recent_alloc\":[...]}".
- * Using "- 2" serves to cut right before the ending "]}".
- */
- assert_d_eq(memcmp(dump_out, template, strlen(template) - 2), 0,
- DUMP_ERROR);
- assert_d_eq(memcmp(dump_out + strlen(dump_out) - 2,
- template + strlen(template) - 2, 2), 0, DUMP_ERROR);
- const char *start = dump_out + strlen(template) - 2;
- const char *end = dump_out + strlen(dump_out) - 2;
- const confirm_record_t *record;
- for (record = records; record < records + n_records; ++record) {
- #define ASSERT_CHAR(c) do { \
- assert_true(start < end, DUMP_ERROR); \
- assert_c_eq(*start++, c, DUMP_ERROR); \
- } while (0)
- #define ASSERT_STR(s) do { \
- const size_t len = strlen(s); \
- assert_true(start + len <= end, DUMP_ERROR); \
- assert_d_eq(memcmp(start, s, len), 0, DUMP_ERROR); \
- start += len; \
- } while (0)
- #define ASSERT_FORMATTED_STR(s, ...) do { \
- malloc_snprintf(buf, sizeof(buf), s, __VA_ARGS__); \
- ASSERT_STR(buf); \
- } while (0)
- if (record != records) {
- ASSERT_CHAR(',');
- }
- ASSERT_CHAR('{');
- ASSERT_STR("\"size\"");
- ASSERT_CHAR(':');
- ASSERT_FORMATTED_STR("%zu", record->size);
- ASSERT_CHAR(',');
- ASSERT_STR("\"usize\"");
- ASSERT_CHAR(':');
- ASSERT_FORMATTED_STR("%zu", record->usize);
- ASSERT_CHAR(',');
- ASSERT_STR("\"released\"");
- ASSERT_CHAR(':');
- ASSERT_STR(record->released ? "true" : "false");
- ASSERT_CHAR(',');
- const char **type = types;
- while (true) {
- ASSERT_FORMATTED_STR("\"%s_thread_uid\"", *type);
- ASSERT_CHAR(':');
- while (isdigit(*start)) {
- ++start;
- }
- ASSERT_CHAR(',');
- if (opt_prof_sys_thread_name) {
- ASSERT_FORMATTED_STR("\"%s_thread_name\"",
- *type);
- ASSERT_CHAR(':');
- ASSERT_CHAR('"');
- while (*start != '"') {
- ++start;
- }
- ASSERT_CHAR('"');
- ASSERT_CHAR(',');
- }
- ASSERT_FORMATTED_STR("\"%s_time\"", *type);
- ASSERT_CHAR(':');
- while (isdigit(*start)) {
- ++start;
- }
- ASSERT_CHAR(',');
- ASSERT_FORMATTED_STR("\"%s_trace\"", *type);
- ASSERT_CHAR(':');
- ASSERT_CHAR('[');
- while (isdigit(*start) || *start == 'x' ||
- (*start >= 'a' && *start <= 'f') ||
- *start == '\"' || *start == ',') {
- ++start;
- }
- ASSERT_CHAR(']');
- if (strcmp(*type, "dalloc") == 0) {
- break;
- }
- assert(strcmp(*type, "alloc") == 0);
- if (!record->released) {
- break;
- }
- ASSERT_CHAR(',');
- ++type;
- }
- ASSERT_CHAR('}');
- #undef ASSERT_FORMATTED_STR
- #undef ASSERT_STR
- #undef ASSERT_CHAR
- }
- assert_ptr_eq(record, records + n_records, DUMP_ERROR);
- assert_ptr_eq(start, end, DUMP_ERROR);
- }
- TEST_BEGIN(test_prof_recent_alloc_dump) {
- test_skip_if(!config_prof);
- confirm_prof_setup();
- ssize_t future;
- void *p, *q;
- confirm_record_t records[2];
- assert_zu_eq(lg_prof_sample, (size_t)0,
- "lg_prof_sample not set correctly");
- future = 0;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- call_dump();
- expect_str_eq(dump_out, "{\"sample_interval\":1,"
- "\"recent_alloc_max\":0,\"recent_alloc\":[]}", DUMP_ERROR);
- future = 2;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- call_dump();
- const char *template = "{\"sample_interval\":1,"
- "\"recent_alloc_max\":2,\"recent_alloc\":[]}";
- expect_str_eq(dump_out, template, DUMP_ERROR);
- p = malloc(7);
- call_dump();
- records[0].size = 7;
- records[0].usize = sz_s2u(7);
- records[0].released = false;
- confirm_record(template, records, 1);
- q = mallocx(17, MALLOCX_ALIGN(128));
- call_dump();
- records[1].size = 17;
- records[1].usize = sz_sa2u(17, 128);
- records[1].released = false;
- confirm_record(template, records, 2);
- free(q);
- call_dump();
- records[1].released = true;
- confirm_record(template, records, 2);
- free(p);
- call_dump();
- records[0].released = true;
- confirm_record(template, records, 2);
- future = OPT_ALLOC_MAX;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &future, sizeof(ssize_t)), 0, "Write error");
- confirm_prof_setup();
- }
- TEST_END
- #undef DUMP_ERROR
- #undef DUMP_OUT_SIZE
- #define N_THREADS 8
- #define N_PTRS 512
- #define N_CTLS 8
- #define N_ITERS 2048
- #define STRESS_ALLOC_MAX 4096
- typedef struct {
- thd_t thd;
- size_t id;
- void *ptrs[N_PTRS];
- size_t count;
- } thd_data_t;
- static thd_data_t thd_data[N_THREADS];
- static ssize_t test_max;
- static void
- test_write_cb(void *cbopaque, const char *str) {
- sleep_ns(1000 * 1000);
- }
- static void *
- f_thread(void *arg) {
- const size_t thd_id = *(size_t *)arg;
- thd_data_t *data_p = thd_data + thd_id;
- assert(data_p->id == thd_id);
- data_p->count = 0;
- uint64_t rand = (uint64_t)thd_id;
- tsd_t *tsd = tsd_fetch();
- assert(test_max > 1);
- ssize_t last_max = -1;
- for (int i = 0; i < N_ITERS; i++) {
- rand = prng_range_u64(&rand, N_PTRS + N_CTLS * 5);
- assert(data_p->count <= N_PTRS);
- if (rand < data_p->count) {
- assert(data_p->count > 0);
- if (rand != data_p->count - 1) {
- assert(data_p->count > 1);
- void *temp = data_p->ptrs[rand];
- data_p->ptrs[rand] =
- data_p->ptrs[data_p->count - 1];
- data_p->ptrs[data_p->count - 1] = temp;
- }
- free(data_p->ptrs[--data_p->count]);
- } else if (rand < N_PTRS) {
- assert(data_p->count < N_PTRS);
- data_p->ptrs[data_p->count++] = malloc(1);
- } else if (rand % 5 == 0) {
- prof_recent_alloc_dump(tsd, test_write_cb, NULL);
- } else if (rand % 5 == 1) {
- last_max = prof_recent_alloc_max_ctl_read();
- } else if (rand % 5 == 2) {
- last_max =
- prof_recent_alloc_max_ctl_write(tsd, test_max * 2);
- } else if (rand % 5 == 3) {
- last_max =
- prof_recent_alloc_max_ctl_write(tsd, test_max);
- } else {
- assert(rand % 5 == 4);
- last_max =
- prof_recent_alloc_max_ctl_write(tsd, test_max / 2);
- }
- assert_zd_ge(last_max, -1, "Illegal last-N max");
- }
- while (data_p->count > 0) {
- free(data_p->ptrs[--data_p->count]);
- }
- return NULL;
- }
- TEST_BEGIN(test_prof_recent_stress) {
- test_skip_if(!config_prof);
- confirm_prof_setup();
- test_max = OPT_ALLOC_MAX;
- for (size_t i = 0; i < N_THREADS; i++) {
- thd_data_t *data_p = thd_data + i;
- data_p->id = i;
- thd_create(&data_p->thd, &f_thread, &data_p->id);
- }
- for (size_t i = 0; i < N_THREADS; i++) {
- thd_data_t *data_p = thd_data + i;
- thd_join(data_p->thd, NULL);
- }
- test_max = STRESS_ALLOC_MAX;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &test_max, sizeof(ssize_t)), 0, "Write error");
- for (size_t i = 0; i < N_THREADS; i++) {
- thd_data_t *data_p = thd_data + i;
- data_p->id = i;
- thd_create(&data_p->thd, &f_thread, &data_p->id);
- }
- for (size_t i = 0; i < N_THREADS; i++) {
- thd_data_t *data_p = thd_data + i;
- thd_join(data_p->thd, NULL);
- }
- test_max = OPT_ALLOC_MAX;
- assert_d_eq(mallctl("experimental.prof_recent.alloc_max",
- NULL, NULL, &test_max, sizeof(ssize_t)), 0, "Write error");
- confirm_prof_setup();
- }
- TEST_END
- #undef STRESS_ALLOC_MAX
- #undef N_ITERS
- #undef N_PTRS
- #undef N_THREADS
- int
- main(void) {
- return test(
- test_confirm_setup,
- test_prof_recent_off,
- test_prof_recent_on,
- test_prof_recent_alloc,
- test_prof_recent_alloc_dump,
- test_prof_recent_stress);
- }
|