From f14474ebb739a28b42fae7caee67fbca2dcf0180 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Tue, 27 May 2025 22:28:52 +0200 Subject: [PATCH] initial work on some interfaces --- src/components/eeprom.c | 9 +++- src/lock.c | 17 ++++++++ src/neonucleus.h | 91 ++++++++++++++++++++++++++++++++++++++++- src/sandbox.lua | 4 +- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/src/components/eeprom.c b/src/components/eeprom.c index 16d83f5..535c7ad 100644 --- a/src/components/eeprom.c +++ b/src/components/eeprom.c @@ -1,7 +1,7 @@ #include "../neonucleus.h" void nn_eeprom_destroy(void *_, nn_component *component, nn_eeprom *eeprom) { - if(atomic_fetch_sub(&eeprom->refc, 1) > 1) return; + if(!nn_decRef(&eeprom->refc)) return; if(eeprom->deinit == NULL) { eeprom->deinit(component, eeprom); @@ -56,7 +56,8 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu size_t len; const char *buf = nn_toString(data, &len); if(len > eeprom->getSize(component, eeprom->userdata)) { - + nn_setCError(computer, "out of space"); + return; } eeprom->set(component, eeprom->userdata, buf, len); } @@ -81,6 +82,10 @@ void nn_eeprom_setData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c nn_value data = nn_getArgument(computer, 0); size_t len; const char *buf = nn_toString(data, &len); + if(len > eeprom->getDataSize(component, eeprom->userdata)) { + nn_setCError(computer, "out of space"); + return; + } eeprom->setData(component, eeprom->userdata, buf, len); } diff --git a/src/lock.c b/src/lock.c index c0985e1..2fdc20a 100644 --- a/src/lock.c +++ b/src/lock.c @@ -26,3 +26,20 @@ void nn_deleteGuard(nn_guard *guard) { if(guard == NULL) return; mtx_destroy(&guard->m); } + +void nn_addRef(nn_refc *refc, size_t count) { + atomic_fetch_add(refc, count); +} + +void nn_incRef(nn_refc *refc) { + nn_addRef(refc, 1); +} + +bool nn_removeRef(nn_refc *refc, size_t count) { + size_t old = atomic_fetch_sub(refc, count); + return old == count; +} + +bool nn_decRef(nn_refc *refc) { + return nn_removeRef(refc, 1); +} diff --git a/src/neonucleus.h b/src/neonucleus.h index bca577d..790f653 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -58,6 +58,8 @@ #define NN_MAX_USERDATA 1024 #define NN_MAX_USER_SIZE 128 #define NN_MAX_SIGNAL_SIZE 8192 +#define NN_MAX_OPEN_FILES 128 + #define NN_OVERHEAT_MIN 100 #define NN_CALL_HEAT 0.05 #define NN_CALL_COST 1 @@ -65,6 +67,7 @@ #define NN_INDIRECT_CALL_LATENCY 0.05 typedef struct nn_guard nn_guard; +typedef atomic_size_t nn_refc; typedef struct nn_universe nn_universe; typedef struct nn_computer nn_computer; typedef struct nn_component nn_component; @@ -143,6 +146,13 @@ void nn_lock(nn_guard *guard); void nn_unlock(nn_guard *guard); void nn_deleteGuard(nn_guard *guard); +void nn_addRef(nn_refc *refc, size_t count); +void nn_incRef(nn_refc *refc); +/* Returns true if the object should be freed */ +bool nn_removeRef(nn_refc *refc, size_t count); +/* Returns true if the object should be freed */ +bool nn_decRef(nn_refc *refc); + double nn_realTime(); double nn_realTimeClock(void *_); /* Will busy-loop until the time passes. This is meant for computed latencies in components. */ @@ -334,13 +344,14 @@ void nn_loadCoreComponentTables(nn_universe *universe); // loading each component void nn_loadEepromTable(nn_universe *universe); +void nn_loadFilesystemTable(nn_universe *universe); // the helpers // EEPROM typedef struct nn_eeprom { + nn_refc refc; void *userdata; - atomic_size_t refc; void (*deinit)(nn_component *component, void *userdata); // methods @@ -357,4 +368,82 @@ typedef struct nn_eeprom { } nn_eeprom; nn_component *nn_addEeprom(nn_computer *computer, nn_address address, int slot, nn_eeprom *eeprom); +// FileSystem +typedef struct nn_filesystemControl { + int pretendChunkSize; + + // speed + // used to calculate the latency of seeking a file. It will treat the file as continuous within the storage medium, which is completely + // unrealistic. Essentially, after a seek, it will check how much the file pointer was changed. If it went backwards, it will pretend + // the whole drive had to spin. You can imagine the drive spinning counter-clockwise. + // Seeks are assumed to be *chunked* too, so seeking within a chunk, even backwards, won't actually do anything. + // Set it to 0 to disable seek latency. + int pretendRPM; + double readLatencyPerChunk; + double writeLatencyPerChunk; + + // these control *random* latencies that each operation will do + double randomLatencyMin; + double randomLatencyMax; + + // thermals + double motorHeat; // this times how many chunks have been seeked will be the heat addres, +/- the heat range. + double heatRange; +} nn_filesystemControl; + +typedef struct nn_filesystem { + nn_refc refc; + nn_filesystemControl *control; + void *userdata; + void (*deinit)(nn_component *component, void *userdata); + + void (*getLabel)(nn_component *component, void *userdata, char *buf, size_t *buflen); + size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, size_t buflen); + + size_t (*spaceUsed)(nn_component *component, void *userdata); + size_t (*spaceTotal)(nn_component *component, void *userdata); +} nn_filesystem; + +nn_filesystem *nn_volatileFileSystem(size_t capacity, nn_filesystemControl *control); +nn_component *nn_addFileSystem(nn_computer *computer, nn_address address, int slot, nn_filesystem *filesystem); + +// Drive +typedef struct nn_driveControl { + // Set it to 0 to disable seek latency. + int rpm; + + double readLatencyPerByte; + double writeLatencyPerByte; + + double randomLatencyMin; + double randomLatencyMax; + + double motorHeat; + double heatRange; +} nn_driveControl; + +typedef struct nn_drive { + nn_refc refc; + nn_driveControl *control; + void *userdata; + void (*deinit)(nn_component *component, void *userdata); + + void (*getLabel)(nn_component *component, void *userdata, char *buf, size_t *buflen); + size_t (*setLabel)(nn_component *component, void *userdata, const char *buf, size_t buflen); + + size_t (*getPlatterCount)(nn_component *component, void *userdata); + size_t (*getCapacity)(nn_component *component, void *userdata); + size_t (*getSectorSize)(nn_component *component, void *userdata); + + // sectors start at 1 as per OC. + void (*readSector)(nn_component *component, void *userdata, int sector, char *buf); + void (*writeSector)(nn_component *component, void *userdata, int sector, const char *buf); + + // readByte and writeByte will internally use readSector and writeSector. This is to ensure they are handled *consistently.* + // Also makes the interface less redundant +} nn_drive; + +nn_drive *nn_volatileDrive(size_t capacity, size_t platterCount, nn_driveControl *control); +nn_component *nn_addDrive(nn_computer *computer, nn_address address, int slot, nn_drive *drive); + #endif diff --git a/src/sandbox.lua b/src/sandbox.lua index e775a80..a8cc488 100644 --- a/src/sandbox.lua +++ b/src/sandbox.lua @@ -128,8 +128,10 @@ libcomponent = { assert(ok, "blackout") end - if computer.getState() ~= states.busy then + if computer.getState() == states.busy then -- busy gets to try again + computer.setState(states.running) + else if r[1] then return table.unpack(r, 2) end