diff --git a/rewrite/luaarch.c b/rewrite/luaarch.c index 6a33d33..2071c8e 100644 --- a/rewrite/luaarch.c +++ b/rewrite/luaarch.c @@ -117,7 +117,8 @@ static void luaArch_nnToLua(luaArch *arch, lua_State *L, size_t nnIdx) { } static int luaArch_computer_freeMemory(lua_State *L) { - lua_pushinteger(L, luaArch_from(L)->freeMem); + size_t freeMem = luaArch_from(L)->freeMem; + lua_pushinteger(L, freeMem); return 1; } @@ -589,13 +590,13 @@ static nn_Exit luaArch_handler(nn_ArchitectureRequest *req) { nn_Context *ctx = nn_getComputerContext(computer); switch(req->action) { case NN_ARCH_FREEMEM: - req->freeMemory = arch->freeMem; + req->freeMemory = arch->freeMem / nn_getMemoryScale(computer); return NN_OK; case NN_ARCH_INIT: // wrapped in a block to prevent L from leaking, because L is common in Lua code so it may be used by mistake { arch = nn_alloc(ctx, sizeof(*arch)); - arch->freeMem = nn_getTotalMemory(computer); + arch->freeMem = nn_getTotalMemory(computer) * nn_getMemoryScale(computer); arch->computer = computer; lua_State *L = lua_newstate(luaArch_alloc, arch); arch->L = L; diff --git a/rewrite/machine.lua b/rewrite/machine.lua index 5663940..445994b 100644 --- a/rewrite/machine.lua +++ b/rewrite/machine.lua @@ -247,8 +247,14 @@ if arch then computer.setArchitecture(arch) end local code = assert(component.invoke(eeprom, "get")) local f = assert(load(code, "=bios")) +local thread = coroutine.create(f) -local ok, err = xpcall(f, debug.traceback) -if not ok then - print(err) +while true do + collectgarbage("collect") + local ok, err = resume(thread) + if not ok then + print(debug.traceback(thread, err)) + end + if coroutine.status(thread) == "dead" then break end + coroutine.yield() end diff --git a/rewrite/main.c b/rewrite/main.c index 3fe4b59..ee6145d 100644 --- a/rewrite/main.c +++ b/rewrite/main.c @@ -1061,14 +1061,16 @@ int main(int argc, char **argv) { nn_ComponentState *gputype = nn_createGPU(u, &nn_defaultGPUs[3], ne_gpu_handler, NULL); size_t ramTotal = 0; - ramTotal += nn_ramSizes[1]; - ramTotal += nn_ramSizes[1]; + ramTotal += nn_ramSizes[0]; nn_Computer *c = nn_createComputer(u, NULL, "computer0", ramTotal, 256, 256); if(showStats) { // collects stats nn_setEnergyHandler(c, NULL, ne_energy_accumulator); } + + // default for 64-bit, we just assume we're 64-bit. + nn_setMemoryScale(c, 1.8); nn_setArchitecture(c, &arch); nn_addSupportedArchitecture(c, &arch); diff --git a/rewrite/neonucleus.c b/rewrite/neonucleus.c index 963354c..14ec6ce 100644 --- a/rewrite/neonucleus.c +++ b/rewrite/neonucleus.c @@ -650,6 +650,7 @@ typedef struct nn_Computer { size_t signalCount; size_t userCount; double idleTimestamp; + double memoryScale; nn_Value callstack[NN_MAX_STACK]; char errorBuffer[NN_MAX_ERROR_SIZE]; nn_Architecture archs[NN_MAX_ARCHITECTURES]; @@ -799,6 +800,7 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char c->signalCount = 0; c->userCount = 0; c->idleTimestamp = 0; + c->memoryScale = 1; // set to empty string c->errorBuffer[0] = '\0'; return c; @@ -997,6 +999,14 @@ void nn_setEnergyHandler(nn_Computer *computer, void *energyState, nn_EnergyHand computer->energyHandler = handler; } +void nn_setMemoryScale(nn_Computer *computer, double scale) { + computer->memoryScale = scale; +} + +double nn_getMemoryScale(nn_Computer *computer) { + return computer->memoryScale; +} + size_t nn_getTotalMemory(nn_Computer *computer) { return computer->totalMemory; } diff --git a/rewrite/neonucleus.h b/rewrite/neonucleus.h index e1cf1c5..716fe81 100644 --- a/rewrite/neonucleus.h +++ b/rewrite/neonucleus.h @@ -329,6 +329,29 @@ const char *nn_getComputerAddress(nn_Computer *computer); nn_Universe *nn_getComputerUniverse(nn_Computer *computer); nn_Context *nn_getUniverseContext(nn_Universe *universe); nn_Context *nn_getComputerContext(nn_Computer *computer); +// Sets the memory scale, which defaults to 1. +// For context, OC will set the memory scale to 1.8 on 64-bit systems by default. +// This scale affects how much real-world memory an amount of VM actually takes up. +// This means if the total memory is 4 MiB, and the scale is set to 2, the computer can take up to 8MiB of actual RAM. +// However, nn_getTotalMemory() will still return 4 MiB. +// The architecture is meant to ensure that the reported free memory is also scaled. As in, the real-world free memory +// is divided by this scale to ensure it is within the correct range. +// It is undefined behavior to change the memory scale *after* the first call to nn_tick(). +// Some architectures may ignore this, if they are very low-level and thus +// do not have any implicit changes of sizes between 32-bit and 64-bit. +void nn_setMemoryScale(nn_Computer *computer, double scale); +double nn_getMemoryScale(nn_Computer *computer); + +// Returns the memory usage limit of the computer. +size_t nn_getTotalMemory(nn_Computer *computer); +// Gets the total amount of free memory the computer has available. The total memory - this is the amount of memory used. +size_t nn_getFreeMemory(nn_Computer *computer); +// Gets the total amount of used memory the computer has allocated. +// This is just the total minus the free, and does not take into +// account the overhead of storing the computer instance. +size_t nn_getUsedMemory(nn_Computer *computer); +// gets the current uptime of a computer. When the computer is not running, this value can be anything and loses all meaning. +double nn_getUptime(nn_Computer *computer); // address is copied. // It can be NULL if you wish to have no tmp address. @@ -397,17 +420,6 @@ typedef double nn_EnergyHandler(void *energyState, nn_Computer *computer, double void nn_setEnergyHandler(nn_Computer *computer, void *energyState, nn_EnergyHandler *handler); -// Returns the memory usage limit of the computer. -size_t nn_getTotalMemory(nn_Computer *computer); -// Gets the total amount of free memory the computer has available. The total memory - this is the amount of memory used. -size_t nn_getFreeMemory(nn_Computer *computer); -// Gets the total amount of used memory the computer has allocated. -// This is just the total minus the free, and does not take into -// account the overhead of storing the computer instance. -size_t nn_getUsedMemory(nn_Computer *computer); -// gets the current uptime of a computer. When the computer is not running, this value can be anything and loses all meaning. -double nn_getUptime(nn_Computer *computer); - // copies the string into the local error buffer. The error is NULL terminated, but also capped by NN_MAX_ERROR_SIZE void nn_setError(nn_Computer *computer, const char *s); // set a default error message from an exit.