void *ph_mem_alloc_size(ph_memtype_t mt, uint64_t size) { struct mem_type *mem_type = resolve_mt(mt); struct sized_header *ptr; ph_counter_block_t *block; static const uint8_t slots[2] = { SLOT_BYTES, SLOT_ALLOCS }; int64_t values[2]; if (mem_type->def.item_size) { memory_panic( "mem_type %s is not vsize, cannot be used with ph_mem_alloc_size", mem_type->def.name); return NULL; } if (size > INT64_MAX) { // we can't account for numbers this big return NULL; } ptr = malloc(size + HEADER_RESERVATION); if (!ptr) { ph_counter_scope_add(mem_type->scope, mem_type->first_slot + SLOT_OOM, 1); if (mem_type->def.flags & PH_MEM_FLAGS_PANIC) { ph_panic("OOM while allocating %" PRIu64 " bytes of %s/%s memory", size + HEADER_RESERVATION, mem_type->def.facility, mem_type->def.name); } return NULL; } ptr->size = size; ptr->mt = mt; ptr++; block = ph_counter_block_open(mem_type->scope); values[0] = size; values[1] = 1; ph_counter_block_bulk_add(block, 2, slots, values); ph_counter_block_delref(block); if (mem_type->def.flags & PH_MEM_FLAGS_ZERO) { memset(ptr, 0, size); } return ptr; }
void *ph_mem_alloc(ph_memtype_t mt) { struct mem_type *mem_type = resolve_mt(mt); void *ptr; ph_counter_block_t *block; int64_t values[3]; static const uint8_t slots[2] = { SLOT_BYTES, SLOT_ALLOCS }; if (mem_type->def.item_size == 0) { memory_panic("mem_type %s is vsize, cannot be used with ph_mem_alloc", mem_type->def.name); return NULL; } ptr = malloc(mem_type->def.item_size); if (!ptr) { ph_counter_scope_add(mem_type->scope, mem_type->first_slot + SLOT_OOM, 1); if (mem_type->def.flags & PH_MEM_FLAGS_PANIC) { ph_panic("OOM while allocating %" PRIu64 " bytes of %s/%s memory", mem_type->def.item_size, mem_type->def.facility, mem_type->def.name); } return NULL; } block = ph_counter_block_open(mem_type->scope); values[0] = mem_type->def.item_size; values[1] = 1; ph_counter_block_bulk_add(block, 2, slots, values); ph_counter_block_delref(block); if (mem_type->def.flags & PH_MEM_FLAGS_ZERO) { memset(ptr, 0, mem_type->def.item_size); } return ptr; }
static void basicCounterFunctionality(void) { ph_counter_scope_t *scope; scope = ph_counter_scope_define(NULL, "test1", 24); is_true(scope != NULL); is_string("test1", ph_counter_scope_get_name(scope)); uint8_t slot = ph_counter_scope_register_counter(scope, "dummy"); is(0, slot); ph_counter_scope_add(scope, slot, 1); is(1, ph_counter_scope_get(scope, slot)); ph_counter_scope_add(scope, slot, 1); is(2, ph_counter_scope_get(scope, slot)); ph_counter_scope_add(scope, slot, 3); is(5, ph_counter_scope_get(scope, slot)); /* register some more slots */ const char *names[2] = {"sent", "recd"}; is_true(ph_counter_scope_register_counter_block( scope, 2, slot + 1, names)); ph_counter_block_t *block = ph_counter_block_open(scope); is_true(block != NULL); ph_counter_block_add(block, slot + 1, 3); is(3, ph_counter_scope_get(scope, slot + 1)); // C++, clogging up code with casts since the last century uint8_t bulk_slots[2] = { (uint8_t)(slot + 1), (uint8_t)(slot + 2) }; int64_t values[2] = { 1, 5 }; ph_counter_block_bulk_add(block, 2, bulk_slots, values); is(4, ph_counter_scope_get(scope, slot + 1)); is(5, ph_counter_scope_get(scope, slot + 2)); uint8_t num_slots; int64_t view_slots[10]; const char *view_names[10]; num_slots = ph_counter_scope_get_view(scope, 10, view_slots, view_names); is(3, num_slots); is(5, view_slots[0]); is(4, view_slots[1]); is(5, view_slots[2]); is_string("dummy", view_names[0]); is_string("sent", view_names[1]); is_string("recd", view_names[2]); ph_counter_scope_t *kid_scope; // Verify that attempting to define the same scope twice fails kid_scope = ph_counter_scope_define(NULL, "test1", 24); is_true(kid_scope == NULL); // Get ourselves a real child kid_scope = ph_counter_scope_define(scope, "child", 8); is_true(kid_scope != NULL); is_string("test1.child", ph_counter_scope_get_name(kid_scope)); ph_counter_scope_t *resolved; resolved = ph_counter_scope_resolve(NULL, "test1"); is(scope, resolved); resolved = ph_counter_scope_resolve(NULL, "test1.child"); is(kid_scope, resolved); ph_counter_scope_register_counter(kid_scope, "w00t"); // Test iteration struct counter_name_val counter_data[16]; int n_counters = 0; ph_counter_scope_iterator_t iter; // Collect all counter data; it is returned in an undefined order. // For the sake of testing we want to order it, so we collect the data // and then sort it ph_counter_scope_iterator_init(&iter); ph_counter_scope_t *iter_scope; while ((iter_scope = ph_counter_scope_iterator_next(&iter)) != NULL) { int i; if (strncmp(ph_counter_scope_get_name(iter_scope), "test1", 5)) { continue; } num_slots = ph_counter_scope_get_view(iter_scope, 10, view_slots, view_names); for (i = 0; i < num_slots; i++) { counter_data[n_counters].scope_name = ph_counter_scope_get_name(iter_scope); counter_data[n_counters].name = view_names[i]; counter_data[n_counters].val = view_slots[i]; n_counters++; } ph_counter_scope_delref(iter_scope); } qsort(counter_data, n_counters, sizeof(struct counter_name_val), compare_counter_name_val); struct counter_name_val expected_data[] = { { "test1", "dummy", 5 }, { "test1", "recd", 5 }, { "test1", "sent", 4 }, { "test1.child", "w00t", 0 }, }; int num_expected = sizeof(expected_data) / sizeof(expected_data[0]); is_int(num_expected, n_counters); for (int i = 0; i < n_counters; i++) { is_string(expected_data[i].scope_name, counter_data[i].scope_name); is_string(expected_data[i].name, counter_data[i].name); is(expected_data[i].val, counter_data[i].val); diag("%s.%s = %" PRIi64, counter_data[i].scope_name, counter_data[i].name, counter_data[i].val); } }
void *ph_mem_realloc(ph_memtype_t mt, void *ptr, uint64_t size) { struct mem_type *mem_type; ph_counter_block_t *block; static const uint8_t slots[2] = { SLOT_BYTES, SLOT_REALLOC }; int64_t values[3]; struct sized_header *hdr; uint64_t orig_size; void *new_ptr; if (size == 0) { ph_mem_free(mt, ptr); return NULL; } if (ptr == NULL) { return ph_mem_alloc_size(mt, size); } mem_type = resolve_mt(mt); if (mem_type->def.item_size) { memory_panic( "mem_type %s is not vsize and cannot be used with ph_mem_realloc", mem_type->def.name); return NULL; } hdr = ptr; hdr--; ptr = hdr; if (hdr->mt != mt) { memory_panic("ph_mem_realloc: hdr->mt %d != caller provided mt %d %s", hdr->mt, mt, mem_type->def.name); } orig_size = hdr->size; if (orig_size == size) { return ptr; } hdr = realloc(ptr, size + HEADER_RESERVATION); if (!hdr) { ph_counter_scope_add(mem_type->scope, mem_type->first_slot + SLOT_OOM, 1); if (mem_type->def.flags & PH_MEM_FLAGS_PANIC) { ph_panic("OOM while allocating %" PRIu64 " bytes of %s/%s memory", size + HEADER_RESERVATION, mem_type->def.facility, mem_type->def.name); } return NULL; } new_ptr = hdr + 1; hdr->size = size; block = ph_counter_block_open(mem_type->scope); values[0] = size - orig_size; values[1] = 1; ph_counter_block_bulk_add(block, 2, slots, values); ph_counter_block_delref(block); if (size > orig_size && mem_type->def.flags & PH_MEM_FLAGS_ZERO) { memset((char*)new_ptr + orig_size, 0, size - orig_size); } return new_ptr; }