static void memory_init(void) { memtypes_size = 1024; memtypes = malloc(memtypes_size * sizeof(*memtypes)); if (!memtypes) { memory_panic("failed to allocate memtypes array"); } memory_scope = ph_counter_scope_define(NULL, "memory", 16); if (!memory_scope) { memory_panic("failed to define memory scope"); } }
ph_memtype_t ph_memtype_register(const ph_memtype_def_t *def) { ph_memtype_t mt; ph_counter_scope_t *scope, *fac_scope; struct mem_type *mem_type; const char **names; int num_slots; fac_scope = resolve_facility(def->facility); if (!fac_scope) { return PH_MEMTYPE_INVALID; } scope = ph_counter_scope_define(fac_scope, def->name, MEM_COUNTER_SLOTS); ph_counter_scope_delref(fac_scope); if (!scope) { return PH_MEMTYPE_INVALID; } mt = ck_pr_faa_int(&next_memtype, 1); if ((uint32_t)mt >= memtypes_size) { memory_panic("You need to recompile libphenom with memtypes_size = %d", 2 * memtypes_size); } mem_type = &memtypes[mt]; memset(mem_type, 0, sizeof(*mem_type)); mem_type->def = *def; mem_type->def.facility = strdup(def->facility); mem_type->def.name = strdup(def->name); mem_type->scope = scope; if (mem_type->def.item_size == 0) { names = vsize_counter_names; num_slots = MEM_COUNTER_SLOTS; } else { names = sized_counter_names; num_slots = MEM_COUNTER_SLOTS - 1; } if (!ph_counter_scope_register_counter_block( scope, num_slots, 0, names)) { memory_panic("failed to register counter block for memory scope %s", def->name); } return mt; }
static struct mem_type *resolve_mt(ph_memtype_t mt) { if (ph_unlikely(mt < PH_MEMTYPE_FIRST || mt >= next_memtype)) { memory_panic( "resolve_mt: mt(%d) < PH_MEMTYPE_FIRST || mt(%d) >= next_memtype(%d)", mt, mt, next_memtype); } return &memtypes[mt]; }
char *jsonnet_realloc(JsonnetVm *vm, char *str, size_t sz) { (void)vm; if (str == nullptr) { if (sz == 0) return nullptr; auto *r = static_cast<char *>(::malloc(sz)); if (r == nullptr) memory_panic(); return r; } else { if (sz == 0) { ::free(str); return nullptr; } else { auto *r = static_cast<char *>(::realloc(str, sz)); if (r == nullptr) memory_panic(); return r; } } }
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; }
void ph_mem_free(ph_memtype_t mt, void *ptr) { struct mem_type *mem_type; ph_counter_block_t *block; static const uint8_t slots[2] = { SLOT_BYTES, SLOT_FREES }; int64_t values[2]; uint64_t size; if (!ptr) { return; } mem_type = resolve_mt(mt); if (mem_type->def.item_size) { size = mem_type->def.item_size; } else { struct sized_header *hdr = ptr; hdr--; ptr = hdr; size = hdr->size; if (hdr->mt != mt) { memory_panic("ph_mem_free: hdr->mt %d != caller provided mt %d %s", hdr->mt, mt, mem_type->def.name); } } free(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); }
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; }
ph_memtype_t ph_memtype_register_block( uint8_t num_types, const ph_memtype_def_t *defs, ph_memtype_t *types) { int i; ph_counter_scope_t *fac_scope, *scope = NULL; ph_memtype_t mt; struct mem_type *mem_type; const char **names; uint32_t num_slots; /* must all be same facility */ for (i = 0; i < num_types; i++) { if (strcmp(defs[0].facility, defs[i].facility)) { return PH_MEMTYPE_INVALID; } } fac_scope = resolve_facility(defs[0].facility); if (!fac_scope) { return PH_MEMTYPE_INVALID; } mt = ck_pr_faa_int(&next_memtype, num_types); if ((uint32_t)mt >= memtypes_size) { memory_panic("You need to recompile libphenom with memtypes_size = %d", 2 * memtypes_size); } for (i = 0; i < num_types; i++) { mem_type = &memtypes[mt + i]; memset(mem_type, 0, sizeof(*mem_type)); mem_type->def = defs[i]; if (i == 0) { mem_type->def.facility = strdup(defs[0].facility); } else { mem_type->def.facility = memtypes[mt].def.facility; } mem_type->def.name = strdup(defs[i].name); scope = ph_counter_scope_define(fac_scope, mem_type->def.name, MEM_COUNTER_SLOTS); if (!scope) { // FIXME: cleaner error handling return PH_MEMTYPE_INVALID; } mem_type->scope = scope; if (mem_type->def.item_size == 0) { names = vsize_counter_names; num_slots = MEM_COUNTER_SLOTS; } else { names = sized_counter_names; num_slots = MEM_COUNTER_SLOTS - 1; } mem_type->first_slot = ph_counter_scope_get_num_slots(scope); if (!ph_counter_scope_register_counter_block( scope, num_slots, 0, names)) { memory_panic("failed to register counter block for memory scope %s", mem_type->def.name); } } if (types) { for (i = 0; i < num_types; i++) { types[i] = mt + i; } } ph_counter_scope_delref(fac_scope); return mt; }