From d9670610f8caa755527961841f898beb901765b8 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Sat, 12 Jul 2025 13:13:46 +0200 Subject: [PATCH] improved EEPROM system --- build.zig | 5 -- src/components/eeprom.c | 110 ++++++++++++++++++++++++++++++---------- src/emulator.c | 84 +++++++++++++++--------------- src/neonucleus.h | 36 +++++++------ 4 files changed, 146 insertions(+), 89 deletions(-) diff --git a/build.zig b/build.zig index 303d58d..85f1b4c 100644 --- a/build.zig +++ b/build.zig @@ -13,11 +13,6 @@ fn addEngineSources(b: *std.Build, opts: LibBuildOpts) *std.Build.Module { .root_source_file = b.path("src/data.zig"), .target = opts.target, .optimize = opts.optimize, - .single_threaded = true, - .sanitize_c = true, - .valgrind = true, - .stack_check = true, - .stack_protector = true, }); dataMod.addCSourceFiles(.{ diff --git a/src/components/eeprom.c b/src/components/eeprom.c index 651a3d8..1c99039 100644 --- a/src/components/eeprom.c +++ b/src/components/eeprom.c @@ -1,11 +1,53 @@ #include "../neonucleus.h" -nn_eepromControl nn_eeprom_getControl(nn_component *component, nn_eeprom *eeprom) { - return eeprom->control(component, eeprom->userdata); +typedef struct nn_eeprom { + nn_Context ctx; + nn_refc refc; + nn_guard *lock; + nn_eepromTable table; + nn_eepromControl control; +} nn_eeprom; + +nn_eeprom *nn_newEEPROM(nn_Context *context, nn_eepromTable table, nn_eepromControl control) { + nn_eeprom *e = nn_alloc(&context->allocator, sizeof(nn_eeprom)); + if(e == NULL) return NULL; + e->lock = nn_newGuard(context); + if(e->lock == NULL) { + nn_dealloc(&context->allocator, e, sizeof(nn_eeprom)); + return NULL; + } + e->ctx = *context; + e->refc = 1; + e->control = control; + e->table = table; + return e; +} + +nn_guard *nn_getEEPROMLock(nn_eeprom *eeprom) { + return eeprom->lock; +} +void nn_retainEEPROM(nn_eeprom *eeprom) { + nn_incRef(&eeprom->refc); +} + +nn_bool_t nn_destroyEEPROM(nn_eeprom *eeprom) { + if(!nn_decRef(&eeprom->refc)) return false; + // no need to lock, we are the only one with a reference + + if(eeprom->table.deinit != NULL) { + eeprom->table.deinit(eeprom->table.userdata); + } + + nn_Context ctx = eeprom->ctx; + + nn_deleteGuard(&ctx, eeprom->lock); + nn_dealloc(&ctx.allocator, eeprom, sizeof(nn_eeprom)); + + return true; } static void nn_eeprom_readCost(nn_component *component, nn_size_t bytesRead) { - nn_eepromControl control = nn_eeprom_getControl(component, nn_getComponentUserdata(component)); + nn_eepromControl control = ((nn_eeprom *)nn_getComponentUserdata(component))->control; nn_computer *computer = nn_getComputerOfComponent(component); nn_removeEnergy(computer, control.readEnergyCostPerByte * bytesRead); @@ -14,7 +56,7 @@ static void nn_eeprom_readCost(nn_component *component, nn_size_t bytesRead) { } static void nn_eeprom_writeCost(nn_component *component, nn_size_t bytesWritten) { - nn_eepromControl control = nn_eeprom_getControl(component, nn_getComponentUserdata(component)); + nn_eepromControl control = ((nn_eeprom *)nn_getComponentUserdata(component))->control; nn_computer *computer = nn_getComputerOfComponent(component); nn_removeEnergy(computer, control.writeEnergyCostPerByte * bytesWritten); @@ -23,25 +65,21 @@ static void nn_eeprom_writeCost(nn_component *component, nn_size_t bytesWritten) } void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *eeprom) { - if(!nn_decRef(&eeprom->refc)) return; - - if(eeprom->deinit != NULL) { - eeprom->deinit(component, eeprom->userdata); - } + nn_destroyEEPROM(eeprom); } void nn_eeprom_getSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - nn_return(computer, nn_values_integer(eeprom->getSize(component, eeprom->userdata))); + nn_return(computer, nn_values_integer(eeprom->table.size)); } void nn_eeprom_getDataSize(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - nn_return(computer, nn_values_integer(eeprom->getDataSize(component, eeprom->userdata))); + nn_return(computer, nn_values_integer(eeprom->table.dataSize)); } void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { char buf[NN_LABEL_SIZE]; nn_size_t l = NN_LABEL_SIZE; - eeprom->getLabel(component, eeprom->userdata, buf, &l); + eeprom->table.getLabel(eeprom->table.userdata, buf, &l); if(l == 0) { nn_return(computer, nn_values_nil()); } else { @@ -60,7 +98,9 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_ nn_setCError(computer, "bad label (string expected)"); return; } - l = eeprom->setLabel(component, eeprom->userdata, buf, l); + nn_lock(&eeprom->ctx, eeprom->lock); + l = eeprom->table.setLabel(eeprom->table.userdata, buf, l); + nn_unlock(&eeprom->ctx, eeprom->lock); nn_return_string(computer, buf, l); // Latency, energy costs and stuff @@ -68,14 +108,16 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_ } void nn_eeprom_get(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - nn_size_t cap = eeprom->getSize(component, eeprom->userdata); + nn_size_t cap = eeprom->table.size; nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); char *buf = nn_alloc(alloc, cap); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; } - nn_size_t len = eeprom->get(component, eeprom->userdata, buf); + nn_lock(&eeprom->ctx, eeprom->lock); + nn_size_t len = eeprom->table.get(eeprom->table.userdata, buf); + nn_unlock(&eeprom->ctx, eeprom->lock); nn_return_string(computer, buf, len); nn_dealloc(alloc, buf, cap); @@ -86,7 +128,7 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu nn_value data = nn_getArgument(computer, 0); nn_size_t len; const char *buf = nn_toString(data, &len); - if(len > eeprom->getSize(component, eeprom->userdata)) { + if(len > eeprom->table.size) { nn_setCError(computer, "out of space"); return; } @@ -99,20 +141,24 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu return; } } - eeprom->set(component, eeprom->userdata, buf, len); + nn_lock(&eeprom->ctx, eeprom->lock); + eeprom->table.set(eeprom->table.userdata, buf, len); + nn_unlock(&eeprom->ctx, eeprom->lock); nn_eeprom_writeCost(component, len); } void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - nn_size_t cap = eeprom->getDataSize(component, eeprom->userdata); + nn_size_t cap = eeprom->table.dataSize; nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); char *buf = nn_alloc(alloc, cap); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; } - int len = eeprom->getData(component, eeprom->userdata, buf); + nn_lock(&eeprom->ctx, eeprom->lock); + int len = eeprom->table.getData(eeprom->table.userdata, buf); + nn_unlock(&eeprom->ctx, eeprom->lock); if(len < 0) { nn_return(computer, nn_values_nil()); } else { @@ -136,42 +182,52 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c return; } } - if(len > eeprom->getDataSize(component, eeprom->userdata)) { + if(len > eeprom->table.dataSize) { nn_setCError(computer, "out of space"); return; } - eeprom->setData(component, eeprom->userdata, buf, len); + nn_lock(&eeprom->ctx, eeprom->lock); + eeprom->table.setData(eeprom->table.userdata, buf, len); + nn_unlock(&eeprom->ctx, eeprom->lock); nn_eeprom_writeCost(component, len); } void nn_eeprom_isReadOnly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - nn_return(computer, nn_values_boolean(eeprom->isReadonly(component, eeprom->userdata))); + nn_lock(&eeprom->ctx, eeprom->lock); + nn_return(computer, nn_values_boolean(eeprom->table.isReadonly(eeprom->table.userdata))); + nn_unlock(&eeprom->ctx, eeprom->lock); } void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - eeprom->makeReadonly(component, eeprom->userdata); + nn_lock(&eeprom->ctx, eeprom->lock); + eeprom->table.makeReadonly(eeprom->table.userdata); + nn_unlock(&eeprom->ctx, eeprom->lock); } void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { - nn_size_t dataCap = eeprom->getDataSize(component, eeprom->userdata); - nn_size_t codeCap = eeprom->getSize(component, eeprom->userdata); + nn_size_t dataCap = eeprom->table.dataSize; + nn_size_t codeCap = eeprom->table.size; nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); char *buf = nn_alloc(alloc, dataCap + codeCap); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; } - int dataLen = eeprom->getData(component, eeprom->userdata, buf); + nn_lock(&eeprom->ctx, eeprom->lock); + int dataLen = eeprom->table.getData(eeprom->table.userdata, buf); if(dataLen < 0) { + nn_unlock(&eeprom->ctx, eeprom->lock); nn_dealloc(alloc, buf, dataCap + codeCap); return; } - int codeLen = eeprom->get(component, eeprom->userdata, buf + dataLen); + int codeLen = eeprom->table.get(eeprom->table.userdata, buf + dataLen); if(codeLen < 0) { + nn_unlock(&eeprom->ctx, eeprom->lock); nn_dealloc(alloc, buf, dataCap + codeCap); return; } + nn_unlock(&eeprom->ctx, eeprom->lock); char hash[4]; nn_data_crc32(buf, dataLen + codeLen, hash); nn_dealloc(alloc, buf, dataCap + codeCap); diff --git a/src/emulator.c b/src/emulator.c index ed19387..b8ff673 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -96,30 +96,20 @@ Color ne_processColor(unsigned int color) { return GetColor(color); } -nn_eepromControl ne_eeprom_getControl(nn_component *component, void *_) { - return (nn_eepromControl) { - .readHeatPerByte = 0.0015, - .writeHeatPerByte = 0.03, - .readEnergyCostPerByte = 0.001, - .writeEnergyCostPerByte = 0.05, - .bytesReadPerTick = 32768, - .bytesWrittenPerTick = 4096, - }; -} +nn_eepromControl ne_eeprom_ctrl = { + .readHeatPerByte = 0.0015, + .writeHeatPerByte = 0.03, + .readEnergyCostPerByte = 0.001, + .writeEnergyCostPerByte = 0.05, + .bytesReadPerTick = 32768, + .bytesWrittenPerTick = 4096, +}; -size_t ne_eeprom_getSize(nn_component *component, void *_) { - return 4096; -} - -size_t ne_eeprom_getDataSize(nn_component *component, void *_) { - return 1024; -} - -void ne_eeprom_getLabel(nn_component *component, void *_, char *buf, size_t *buflen) { +void ne_eeprom_getLabel(void *_, char *buf, size_t *buflen) { *buflen = 0; } -size_t ne_eeprom_setLabel(nn_component *component, void *_, const char *buf, size_t buflen) { +size_t ne_eeprom_setLabel(void *_, const char *buf, size_t buflen) { return 0; } @@ -129,8 +119,8 @@ const char *ne_location(nn_address address) { return buffer; } -size_t ne_eeprom_get(nn_component *component, void *_, char *buf) { - FILE *f = fopen(ne_location(nn_getComponentAddress(component)), "rb"); +size_t ne_eeprom_get(void *addr, char *buf) { + FILE *f = fopen(ne_location(addr), "rb"); if (f == NULL) { printf("couldn't read eeprom"); exit(1); @@ -143,8 +133,8 @@ size_t ne_eeprom_get(nn_component *component, void *_, char *buf) { return len; } -void ne_eeprom_set(nn_component *component, void *_, const char *buf, size_t len) { - FILE *f = fopen(ne_location(nn_getComponentAddress(component)), "wb"); +void ne_eeprom_set(void *addr, const char *buf, size_t len) { + FILE *f = fopen(ne_location(addr), "wb"); if (f == NULL) { printf("couldn't write eeprom"); exit(1); @@ -153,17 +143,17 @@ void ne_eeprom_set(nn_component *component, void *_, const char *buf, size_t len fclose(f); } -int ne_eeprom_getData(nn_component *component, void *_, char *buf) { +int ne_eeprom_getData(void *_, char *buf) { return 0; } -void ne_eeprom_setData(nn_component *component, void *_, const char *buf, size_t len) {} +void ne_eeprom_setData(void *_, const char *buf, size_t len) {} -nn_bool_t ne_eeprom_isReadonly(nn_component *component, void *userdata) { +nn_bool_t ne_eeprom_isReadonly(void *userdata) { return false; } -void ne_eeprom_makeReadonly(nn_component *component, void *userdata) {} +void ne_eeprom_makeReadonly(void *userdata) {} #define NE_FS_MAX 128 @@ -191,6 +181,18 @@ nn_filesystemControl ne_fs_getControl(nn_component *component, ne_fs *_) { }; } +void ne_fs_getLabel(nn_component *component, void *_, char *buf, size_t *buflen) { + *buflen = 0; +} + +nn_size_t ne_fs_setLabel(nn_component *component, void *_, const char *buf, size_t buflen) { + return 0; +} + +nn_bool_t ne_fs_isReadonly(nn_component *component, void *userdata) { + return false; +} + size_t ne_fs_spaceUsed(nn_component *component, void *_) { return 0; // ultra accurate } @@ -677,16 +679,14 @@ int main() { // 1MB of RAM, 16 components max nn_computer *computer = nn_newComputer(universe, "testMachine", arch, NULL, 1*1024*1024, 16); nn_setEnergyInfo(computer, 5000, 5000); - nn_setCallBudget(computer, 18000); + //nn_setCallBudget(computer, 18000); nn_addSupportedArchitecture(computer, arch); - nn_eeprom genericEEPROM = { - .userdata = NULL, - .refc = 1, + nn_eepromTable genericEEPROMTable = { + .userdata = "luaBios.lua", .deinit = NULL, - .control = ne_eeprom_getControl, - .getSize = ne_eeprom_getSize, - .getDataSize = ne_eeprom_getDataSize, + .size = 4096, + .dataSize = 1024, .getLabel = ne_eeprom_getLabel, .setLabel = ne_eeprom_setLabel, .get = ne_eeprom_get, @@ -697,7 +697,9 @@ int main() { .makeReadonly = ne_eeprom_makeReadonly, }; - nn_addEeprom(computer, "luaBios.lua", 0, &genericEEPROM); + nn_eeprom *genericEEPROM = nn_newEEPROM(&ctx, genericEEPROMTable, ne_eeprom_ctrl); + + nn_addEeprom(computer, "luaBios.lua", 0, genericEEPROM); ne_fs fs = { .files = {NULL}, @@ -709,11 +711,11 @@ int main() { .userdata = &fs, .deinit = NULL, .control = (void *)ne_fs_getControl, - .getLabel = ne_eeprom_getLabel, - .setLabel = ne_eeprom_setLabel, + .getLabel = ne_fs_getLabel, + .setLabel = ne_fs_setLabel, .spaceUsed = ne_fs_spaceUsed, .spaceTotal = ne_fs_spaceTotal, - .isReadOnly = ne_eeprom_isReadonly, + .isReadOnly = ne_fs_isReadonly, .size = (void *)ne_fs_size, .remove = NULL, .lastModified = (void *)ne_fs_lastModified, @@ -740,8 +742,8 @@ int main() { .userdata = &drive, .deinit = (void *)ne_drive_close, .control = (void *)ne_drive_getControl, - .getLabel = ne_eeprom_getLabel, - .setLabel = ne_eeprom_setLabel, + .getLabel = ne_fs_getLabel, + .setLabel = ne_fs_setLabel, .getPlatterCount = (void *)ne_drive_getPlatterCount, .getSectorSize = (void *)ne_drive_getSectorSize, .getCapacity = (void *)ne_drive_getCapacity, diff --git a/src/neonucleus.h b/src/neonucleus.h index 2094bc1..c1ad4c9 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -582,25 +582,29 @@ typedef struct nn_eepromControl { double bytesWrittenPerTick; } nn_eepromControl; -typedef struct nn_eeprom { - nn_refc refc; +typedef struct nn_eepromTable { void *userdata; - void (*deinit)(nn_component *component, void *userdata); - - nn_eepromControl (*control)(nn_component *component, void *userdata); + void (*deinit)(void *userdata); // methods - nn_size_t (*getSize)(nn_component *component, void *userdata); - nn_size_t (*getDataSize)(nn_component *component, void *userdata); - void (*getLabel)(nn_component *component, void *userdata, char *buf, nn_size_t *buflen); - nn_size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, nn_size_t buflen); - nn_size_t (*get)(nn_component *component, void *userdata, char *buf); - void (*set)(nn_component *component, void *userdata, const char *buf, nn_size_t len); - int (*getData)(nn_component *component, void *userdata, char *buf); - void (*setData)(nn_component *component, void *userdata, const char *buf, nn_size_t len); - nn_bool_t (*isReadonly)(nn_component *component, void *userdata); - void (*makeReadonly)(nn_component *component, void *userdata); -} nn_eeprom; + nn_size_t size; + nn_size_t dataSize; + void (*getLabel)(void *userdata, char *buf, nn_size_t *buflen); + nn_size_t (*setLabel)(void *userdata, const char *buf, nn_size_t buflen); + nn_size_t (*get)(void *userdata, char *buf); + void (*set)(void *userdata, const char *buf, nn_size_t len); + int (*getData)(void *userdata, char *buf); + void (*setData)(void *userdata, const char *buf, nn_size_t len); + nn_bool_t (*isReadonly)(void *userdata); + void (*makeReadonly)(void *userdata); +} nn_eepromTable; + +typedef struct nn_eeprom nn_eeprom; + +nn_eeprom *nn_newEEPROM(nn_Context *context, nn_eepromTable table, nn_eepromControl control); +nn_guard *nn_getEEPROMLock(nn_eeprom *eeprom); +void nn_retainEEPROM(nn_eeprom *eeprom); +nn_bool_t nn_destroyEEPROM(nn_eeprom *eeprom); nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom); // FileSystem