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; }
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; }
static void * test_spmc(void *c) { unsigned int observed = 0; unsigned long previous = 0; unsigned int seed; int i, k, j, tid; struct context *context = c; ck_ring_buffer_t *buffer; buffer = context->buffer; if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } tid = ck_pr_faa_int(&eb, 1); ck_pr_fence_memory(); while (ck_pr_load_int(&eb) != nthr - 1); for (i = 0; i < ITERATIONS; i++) { for (j = 0; j < size; j++) { struct entry *o; int spin; /* Keep trying until we encounter at least one node. */ if (j & 1) { while (ck_ring_dequeue_spmc(&ring_spmc, buffer, &o) == false); } else { while (ck_ring_trydequeue_spmc(&ring_spmc, buffer, &o) == false); } observed++; if (o->value < 0 || o->value != o->tid || o->magic != 0xdead || (previous != 0 && previous >= o->value_long)) { ck_error("[0x%p] (%x) (%d, %d) >< (0, %d)\n", (void *)o, o->magic, o->tid, o->value, size); } o->magic = 0xbeef; o->value = -31337; o->tid = -31338; previous = o->value_long; if (ck_pr_faa_uint(&o->ref, 1) != 0) { ck_error("[%p] We dequeued twice.\n", (void *)o); } if ((i % 4) == 0) { spin = common_rand_r(&seed) % 16384; for (k = 0; k < spin; k++) { ck_pr_stall(); } } free(o); } } fprintf(stderr, "[%d] Observed %u\n", tid, observed); return NULL; }