aboutsummaryrefslogtreecommitdiff
path: root/core.c
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2026-03-21 01:36:24 +0100
committerPaul Oliver <contact@pauloliver.dev>2026-04-03 18:50:51 +0200
commitbda5ad2ec9fa333c8200451496d6c251abbeee19 (patch)
tree52e15344f239a023d298ee9635e8c7c0c4fdf614 /core.c
parent9f7e70904e6c0fa650323ac5e50ebf6003da333c (diff)
Adds data server (WIP)
Diffstat (limited to 'core.c')
-rw-r--r--core.c274
1 files changed, 271 insertions, 3 deletions
diff --git a/core.c b/core.c
index a4b57d8..79fc6f2 100644
--- a/core.c
+++ b/core.c
@@ -39,6 +39,20 @@ struct Core {
uint64_t *ivav;
uint8_t *iviv;
+#if defined(DATA_PUSH_PATH)
+ uint64_t emb0; // executions within mb0 counter
+ uint64_t emb1; // executions within mb1 counter
+ uint64_t eliv; // executions within not-owned live code counter (parasites)
+ uint64_t edea; // executions within dead code counter
+
+ uint64_t aeva[MVEC_SIZE]; // allocation events array
+ //uint64_t eeva[MVEC_SIZE]; // execution events array
+
+#define CORE_DATA_FIELD(type, name, suff) type name suff;
+ CORE_DATA_FIELDS
+#undef CORE_FIELD
+#endif
+
#define CORE_FIELD(type, name, suff) type name suff;
CORE_FIELDS
#undef CORE_FIELD
@@ -99,7 +113,9 @@ wchar_t arch_symbol(uint8_t inst);
const char *arch_mnemonic(uint8_t inst);
#if defined(DATA_PUSH_PATH)
+#if defined(COMMAND_NEW)
void arch_push_data_header();
+#endif
void arch_push_data_line();
#endif
@@ -132,9 +148,17 @@ void mvec_alloc(struct Core *core, uint64_t addr) {
#if defined(MVEC_LOOP)
core->mvec[mvec_loop(addr)] |= MALL_FLAG;
+#if defined(DATA_PUSH_PATH)
+ // Record deallocation event
+ ++core->aeva[mvec_loop(addr)];
+#endif
#else
assert(addr < MVEC_SIZE);
core->mvec[addr] |= MALL_FLAG;
+#if defined(DATA_PUSH_PATH)
+ // Record deallocation event
+ ++core->aeva[addr];
+#endif
#endif
core->mall++;
}
@@ -145,9 +169,17 @@ void mvec_free(struct Core *core, uint64_t addr) {
#if defined(MVEC_LOOP)
core->mvec[mvec_loop(addr)] ^= MALL_FLAG;
+#if defined(DATA_PUSH_PATH)
+ // Record deallocation event
+ ++core->aeva[mvec_loop(addr)];
+#endif
#else
assert(addr < MVEC_SIZE);
core->mvec[addr] ^= MALL_FLAG;
+#if defined(DATA_PUSH_PATH)
+ // Record deallocation event
+ ++core->aeva[addr];
+#endif
#endif
core->mall--;
}
@@ -373,11 +405,21 @@ void core_save(FILE *f, const struct Core *core) {
fwrite(&core->pcur, sizeof(uint64_t), 1, f);
fwrite(&core->psli, sizeof(uint64_t), 1, f);
fwrite(&core->ivpt, sizeof(uint64_t), 1, f);
+#if defined(DATA_PUSH_PATH)
+ fwrite(&core->emb0, sizeof(uint64_t), 1, f);
+ fwrite(&core->emb1, sizeof(uint64_t), 1, f);
+ fwrite(&core->eliv, sizeof(uint64_t), 1, f);
+ fwrite(&core->edea, sizeof(uint64_t), 1, f);
+#endif
fwrite(core->iviv, sizeof(uint8_t), SYNC_INTERVAL, f);
fwrite(core->ivav, sizeof(uint64_t), SYNC_INTERVAL, f);
fwrite(core->pvec, sizeof(struct Proc), core->pcap, f);
fwrite(core->mvec, sizeof(uint8_t), MVEC_SIZE, f);
+#if defined(DATA_PUSH_PATH)
+ fwrite(core->aeva, sizeof(uint64_t), MVEC_SIZE, f);
+ //fwrite(core->eeva, sizeof(uint64_t), MVEC_SIZE, f);
+#endif
arch_core_save(f, core);
}
@@ -451,6 +493,12 @@ void core_load(FILE *f, struct Core *core) {
fread(&core->pcur, sizeof(uint64_t), 1, f);
fread(&core->psli, sizeof(uint64_t), 1, f);
fread(&core->ivpt, sizeof(uint64_t), 1, f);
+#if defined(DATA_PUSH_PATH)
+ fread(&core->emb0, sizeof(uint64_t), 1, f);
+ fread(&core->emb1, sizeof(uint64_t), 1, f);
+ fread(&core->eliv, sizeof(uint64_t), 1, f);
+ fread(&core->edea, sizeof(uint64_t), 1, f);
+#endif
core->iviv = calloc(SYNC_INTERVAL, sizeof(uint8_t));
core->ivav = calloc(SYNC_INTERVAL, sizeof(uint64_t));
@@ -464,6 +512,10 @@ void core_load(FILE *f, struct Core *core) {
fread(core->ivav, sizeof(uint64_t), SYNC_INTERVAL, f);
fread(core->pvec, sizeof(struct Proc), core->pcap, f);
fread(core->mvec, sizeof(uint8_t), MVEC_SIZE, f);
+#if defined(DATA_PUSH_PATH)
+ fread(core->aeva, sizeof(uint64_t), MVEC_SIZE, f);
+ //fread(core->eeva, sizeof(uint64_t), MVEC_SIZE, f);
+#endif
arch_core_load(f, core);
}
@@ -507,6 +559,24 @@ void core_step(struct Core *core) {
if (core->psli != 0) {
core_pull_ipcm(core);
+
+#if defined(DATA_PUSH_PATH)
+ // Save execution event locations in database
+ assert(mvec_proc_is_live(core, core->pcur));
+
+ struct Proc *proc = proc_fetch(core, core->pcur);
+
+ if (mvec_is_in_mb0_of_proc(core, proc->ip, core->pcur)) {
+ ++core->emb0;
+ } else if (mvec_is_in_mb1_of_proc(core, proc->ip, core->pcur)) {
+ ++core->emb1;
+ } else if (mvec_is_alloc(core, proc->ip)) {
+ ++core->eliv;
+ } else {
+ ++core->edea;
+ }
+#endif
+
arch_proc_step(core, core->pcur);
core->psli--;
@@ -664,6 +734,203 @@ void salis_exec_sql(int blob_cnt, const void **blobs, const int *blob_sizes, con
}
#endif
+#if defined(DATA_PUSH_PATH)
+#if defined(COMMAND_NEW)
+void salis_push_data_header() {
+ assert(g_sim_data);
+
+ g_info("Creating 'general' table in SQLite database");
+ salis_exec_sql(
+ 0, NULL, NULL,
+ "create table general ("
+#define FOR_CORE(i) \
+ "cycl_" #i " int not null, " \
+ "mall_" #i " int not null, " \
+ "pnum_" #i " int not null, " \
+ "pfst_" #i " int not null, " \
+ "plst_" #i " int not null, " \
+ "amb0_" #i " real not null, " \
+ "amb1_" #i " real not null, " \
+ "emb0_" #i " int not null, " \
+ "emb1_" #i " int not null, " \
+ "eliv_" #i " int not null, " \
+ "edea_" #i " int not null, "
+ FOR_CORES
+#undef FOR_CORE
+ "step int not null"
+ ");"
+ );
+
+ // Memory events
+ char *eprefs[] = { "aev" /*, "eev" */ };
+ int eprefs_cnt = sizeof(eprefs) / sizeof(eprefs[0]);
+
+ for (int i = 0; i < CORES; ++i) {
+ for (int j = 0; j < eprefs_cnt; ++j) {
+ g_info("Creating '%s_%d' table in SQLite database", eprefs[j], i);
+ salis_exec_sql(
+ 0, NULL, NULL,
+ "create table %s_%d ("
+#define FOR_CORE(i) "cycl_" #i " int not null, "
+ FOR_CORES
+#undef FOR_CORE
+ "size int not null, "
+ "evts blob not null ,"
+ "step int not null"
+ ");",
+ eprefs[j], i
+ );
+ }
+ }
+
+ arch_push_data_header();
+}
+#endif
+
+void salis_push_data_line() {
+ assert(g_sim_data);
+
+ // Measure average membory block sizes
+ double amb0[CORES] = { 0 };
+ double amb1[CORES] = { 0 };
+
+ for (int i = 0; i < CORES; ++i) {
+ struct Core *core = &g_cores[i];
+
+ for (uint64_t j = core->pfst; j <= core->plst; ++j) {
+ const struct Proc *proc = proc_get(core, j);
+
+ amb0[i] += (double)proc->mb0s;
+ amb1[i] += (double)proc->mb1s;
+ }
+
+ amb0[i] /= core->pnum;
+ amb1[i] /= core->pnum;
+ }
+
+ g_info("Pushing row to 'general' table in SQLite database");
+ salis_exec_sql(
+ 0, NULL, NULL,
+ "insert into general ("
+#define FOR_CORE(i) \
+ "cycl_" #i ", " \
+ "mall_" #i ", " \
+ "pnum_" #i ", " \
+ "pfst_" #i ", " \
+ "plst_" #i ", " \
+ "amb0_" #i ", " \
+ "amb1_" #i ", " \
+ "emb0_" #i ", " \
+ "emb1_" #i ", " \
+ "eliv_" #i ", " \
+ "edea_" #i ", "
+ FOR_CORES
+#undef FOR_CORE
+ "step"
+ ") values ("
+#define FOR_CORE(i) "%ld, %ld, %ld, %ld, %ld, %f, %f, %ld, %ld, %ld, %ld, "
+ FOR_CORES
+#undef FOR_CORE
+ "%ld"
+ ");",
+#define FOR_CORE(i) \
+ g_cores[i].cycl, \
+ g_cores[i].mall, \
+ g_cores[i].pnum, \
+ g_cores[i].pfst, \
+ g_cores[i].plst, \
+ amb0[i], \
+ amb1[i], \
+ g_cores[i].emb0, \
+ g_cores[i].emb1, \
+ g_cores[i].eliv, \
+ g_cores[i].edea,
+ FOR_CORES
+#undef FOR_CORE
+ g_steps
+ );
+
+ // TODO: insert execute memory events
+ char *eprefs[] = { "aev" /*, "eev" */ };
+ int eprefs_cnt = sizeof(eprefs) / sizeof(eprefs[0]);
+
+ for (int i = 0; i < CORES; ++i) {
+ for (int j = 0; j < eprefs_cnt; ++j) {
+ uint64_t *in = NULL;
+
+ if (!strcmp("aev", eprefs[j])) {
+ in = g_cores[i].aeva;
+ } // else if (!strcmp("eev", eprefs[j])) {
+ // in = g_cores[i].eeva;
+ // }
+
+ // Compress event data
+ size_t size = sizeof(uint64_t) * MVEC_SIZE;
+ char *out = malloc(size);
+ assert(out);
+
+ z_stream strm = { 0 };
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+
+ deflateInit(&strm, Z_DEFAULT_COMPRESSION);
+
+ strm.avail_in = size;
+ strm.avail_out = size;
+ strm.next_in = (Bytef *)in;
+ strm.next_out = (Bytef *)out;
+
+ deflate(&strm, Z_FINISH);
+
+ // Insert blob
+ const void *blob = out;
+ int blob_size = strm.total_out;
+
+ g_info("Pushing row to '%s_%d' table in SQLite database", eprefs[j], i);
+ salis_exec_sql(
+ 1, &blob, &blob_size,
+ "insert into %s_%d ("
+#define FOR_CORE(i) "cycl_" #i ", "
+ FOR_CORES
+#undef FOR_CORE
+ "size, evts, step"
+ ") values ("
+#define FOR_CORE(i) "%ld, "
+ FOR_CORES
+#undef FOR_CORE
+ "%ld, ?, %ld"
+ ");",
+ eprefs[j], i,
+#define FOR_CORE(i) g_cores[i].cycl,
+ FOR_CORES
+#undef FOR_CORE
+ blob_size, g_steps
+ );
+
+ deflateEnd(&strm);
+ free(out);
+ }
+ }
+
+ // Reset data aggregation fields
+ for (int i = 0; i < CORES; ++i) {
+ struct Core *core = &g_cores[i];
+
+ core->emb0 = 0;
+ core->emb1 = 0;
+ core->eliv = 0;
+ core->edea = 0;
+
+ memset(core->aeva, 0, sizeof(uint64_t) * MVEC_SIZE);
+ //memset(core->eeva, 0, sizeof(uint64_t) * MVEC_SIZE);
+ }
+
+ // Push arch-specific data
+ arch_push_data_line();
+}
+#endif
+
#if defined(COMMAND_BENCH) || defined(COMMAND_NEW)
void salis_init() {
assert(g_info);
@@ -691,8 +958,9 @@ void salis_init() {
// See: https://sqlite.org/wal.html
salis_exec_sql(0, NULL, NULL, "pragma journal_mode=wal;");
- arch_push_data_header();
- arch_push_data_line();
+ // Initialize database
+ salis_push_data_header();
+ salis_push_data_line();
#endif
}
#endif
@@ -835,7 +1103,7 @@ void salis_loop(uint64_t ns, uint64_t dt) {
#if defined(DATA_PUSH_PATH)
if (g_steps % DATA_PUSH_INTERVAL == 0) {
- arch_push_data_line();
+ salis_push_data_line();
}
#endif