diff --git a/data/OpenOS/tmp/event.log b/data/OpenOS/tmp/event.log index e69de29..7c3134b 100644 --- a/data/OpenOS/tmp/event.log +++ b/data/OpenOS/tmp/event.log @@ -0,0 +1,18 @@ +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') +boot/91_gpu.lua:14: attempt to call a nil value (field 'getDepth') diff --git a/src/component.c b/src/component.c index 181f9a1..1203592 100644 --- a/src/component.c +++ b/src/component.c @@ -2,36 +2,45 @@ #include #include "component.h" -nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor) { - nn_componentTable *table = nn_malloc(sizeof(nn_componentTable)); - table->name = nn_strdup(typeName); +nn_componentTable *nn_newComponentTable(nn_Alloc *alloc, const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor) { + nn_componentTable *table = nn_alloc(alloc, sizeof(nn_componentTable)); + if(table == NULL) { + return NULL; + } + table->name = nn_strdup(alloc, typeName); + if(table->name == NULL) { + nn_dealloc(alloc, table, sizeof(nn_componentTable)); + return NULL; + } table->userdata = userdata; table->constructor = constructor; table->destructor = destructor; table->methodCount = 0; + table->alloc = *alloc; return table; } void nn_destroyComponentTable(nn_componentTable *table) { - nn_free(table->name); + nn_Alloc alloc = table->alloc; + nn_deallocStr(&alloc, table->name); for(size_t i = 0; i < table->methodCount; i++) { nn_method method = table->methods[i]; - nn_free(method.name); - nn_free(method.doc); + nn_deallocStr(&alloc, method.name); + nn_deallocStr(&alloc, method.doc); } - nn_free(table); + nn_dealloc(&alloc, table, sizeof(nn_componentTable)); } void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc) { if(table->methodCount == NN_MAX_METHODS) return; nn_method method; method.method = methodFunc; - method.name = nn_strdup(methodName); + method.name = nn_strdup(&table->alloc, methodName); if(method.name == NULL) return; method.direct = direct; - method.doc = nn_strdup(methodDoc); + method.doc = nn_strdup(&table->alloc, methodDoc); if(method.doc == NULL) { - nn_free(method.name); + nn_deallocStr(&table->alloc, method.name); return; } method.userdata = methodUserdata; diff --git a/src/component.h b/src/component.h index 22f5ebb..7ab172a 100644 --- a/src/component.h +++ b/src/component.h @@ -14,6 +14,7 @@ typedef struct nn_method { typedef struct nn_componentTable { char *name; + nn_Alloc alloc; void *userdata; nn_componentConstructor *constructor; nn_componentDestructor *destructor; diff --git a/src/components/drive.c b/src/components/drive.c index fd5efb8..3af2046 100644 --- a/src/components/drive.c +++ b/src/components/drive.c @@ -21,7 +21,7 @@ void nn_drive_getLabel(nn_drive *drive, void *_, nn_component *component, nn_com if(l == 0) { nn_return(computer, nn_values_nil()); } else { - nn_return(computer, nn_values_string(buf, l)); + nn_return_string(computer, buf, l); } } void nn_drive_setLabel(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) { @@ -33,7 +33,7 @@ void nn_drive_setLabel(nn_drive *drive, void *_, nn_component *component, nn_com return; } l = drive->setLabel(component, drive->userdata, buf, l); - nn_return(computer, nn_values_string(buf, l)); + nn_return_string(computer, buf, l); } void nn_drive_getSectorSize(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) { size_t sector_size = drive->getSectorSize(component, drive->userdata); @@ -53,7 +53,7 @@ void nn_drive_readSector(nn_drive *drive, void *_, nn_component *component, nn_c size_t sector_size = drive->getSectorSize(component, drive->userdata); char buf[sector_size]; drive->readSector(component, drive->userdata, sector, buf); - nn_return(computer, nn_values_string(buf, sector_size)); + nn_return_string(computer, buf, sector_size); } void nn_drive_writeSector(nn_drive *drive, void *_, nn_component *component, nn_computer *computer) { nn_value sectorValue = nn_getArgument(computer, 0); @@ -93,7 +93,7 @@ void nn_drive_writeByte(nn_drive *drive, void *_, nn_component *component, nn_co } void nn_loadDriveTable(nn_universe *universe) { - nn_componentTable *driveTable = nn_newComponentTable("drive", NULL, NULL, (void *)nn_drive_destroy); + nn_componentTable *driveTable = nn_newComponentTable(nn_getAllocator(universe), "drive", NULL, NULL, (void *)nn_drive_destroy); nn_storeUserdata(universe, "NN:DRIVE", driveTable); nn_defineMethod(driveTable, "getLabel", false, (void *)nn_drive_getLabel, NULL, "getLabel():string - Get the current label of the drive."); diff --git a/src/components/eeprom.c b/src/components/eeprom.c index 3bfe9c9..68d8532 100644 --- a/src/components/eeprom.c +++ b/src/components/eeprom.c @@ -41,7 +41,7 @@ void nn_eeprom_getLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_ if(l == 0) { nn_return(computer, nn_values_nil()); } else { - nn_return(computer, nn_values_string(buf, l)); + nn_return_string(computer, buf, l); } // Latency, energy costs and stuff @@ -61,7 +61,7 @@ void nn_eeprom_setLabel(nn_eeprom *eeprom, void *_, nn_component *component, nn_ return; } l = eeprom->setLabel(component, eeprom->userdata, buf, l); - nn_return(computer, nn_values_string(buf, l)); + nn_return_string(computer, buf, l); // Latency, energy costs and stuff nn_eepromControl control = nn_eeprom_getControl(component, eeprom); @@ -74,14 +74,15 @@ 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) { size_t cap = eeprom->getSize(component, eeprom->userdata); - char *buf = nn_malloc(cap); + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); + char *buf = nn_alloc(alloc, cap); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; } size_t len = eeprom->get(component, eeprom->userdata, buf); - nn_return(computer, nn_values_string(buf, len)); - nn_free(buf); + nn_return_string(computer, buf, len); + nn_dealloc(alloc, buf, cap); nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); @@ -119,7 +120,8 @@ void nn_eeprom_set(nn_eeprom *eeprom, void *_, nn_component *component, nn_compu void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { size_t cap = eeprom->getDataSize(component, eeprom->userdata); - char *buf = nn_malloc(cap); + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); + char *buf = nn_alloc(alloc, cap); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; @@ -128,9 +130,9 @@ void nn_eeprom_getData(nn_eeprom *eeprom, void *_, nn_component *component, nn_c if(len < 0) { nn_return(computer, nn_values_nil()); } else { - nn_return(computer, nn_values_string(buf, len)); + nn_return_string(computer, buf, len); } - nn_free(buf); + nn_dealloc(alloc, buf, cap); nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); @@ -178,7 +180,8 @@ void nn_eeprom_makeReadonly(nn_eeprom *eeprom, void *_, nn_component *component, // TODO: make good void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, nn_computer *computer) { size_t cap = eeprom->getDataSize(component, eeprom->userdata); - char *buf = nn_malloc(cap); + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); + char *buf = nn_alloc(alloc, cap); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; @@ -188,9 +191,9 @@ void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, for(size_t i = 0; i < len; i++) { sum += buf[i]; } - nn_free(buf); + nn_dealloc(alloc, buf, cap); - nn_return(computer, nn_values_string((void *)&sum, sizeof(sum))); + nn_return_string(computer, (void *)&sum, sizeof(sum)); nn_eepromControl control = nn_eeprom_getControl(component, eeprom); nn_randomLatency(control.randomLatencyMin, control.randomLatencyMax); @@ -200,7 +203,7 @@ void nn_eeprom_getChecksum(nn_eeprom *eeprom, void *_, nn_component *component, } void nn_loadEepromTable(nn_universe *universe) { - nn_componentTable *eepromTable = nn_newComponentTable("eeprom", NULL, NULL, (void *)nn_eeprom_destroy); + nn_componentTable *eepromTable = nn_newComponentTable(nn_getAllocator(universe), "eeprom", NULL, NULL, (void *)nn_eeprom_destroy); nn_storeUserdata(universe, "NN:EEPROM", eepromTable); nn_defineMethod(eepromTable, "getSize", true, (void *)nn_eeprom_getSize, NULL, "getSize(): integer - Returns the maximum code capacity of the EEPROM."); diff --git a/src/components/filesystem.c b/src/components/filesystem.c index ff1569b..ed3044a 100644 --- a/src/components/filesystem.c +++ b/src/components/filesystem.c @@ -69,7 +69,7 @@ void nn_fs_getLabel(nn_filesystem *fs, void *_, nn_component *component, nn_comp if(l == 0) { nn_return(computer, nn_values_nil()); } else { - nn_return(computer, nn_values_string(buf, l)); + nn_return_string(computer, buf, l); } // Latency, energy costs and stuff @@ -89,7 +89,7 @@ void nn_fs_setLabel(nn_filesystem *fs, void *_, nn_component *component, nn_comp return; } l = fs->setLabel(component, fs->userdata, buf, l); - nn_return(computer, nn_values_string(buf, l)); + nn_return_string(computer, buf, l); nn_fs_readCost(fs, 1, component, computer); } @@ -270,18 +270,20 @@ void nn_fs_list(nn_filesystem *fs, void *_, nn_component *component, nn_computer nn_setCError(computer, "bad path (illegal path)"); return; } + + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); size_t fileCount = 0; - char **files = fs->list(component, fs->userdata, path, &fileCount); + char **files = fs->list(alloc, component, fs->userdata, path, &fileCount); if(files != NULL) { // operation succeeded - nn_value arr = nn_values_array(fileCount); + nn_value arr = nn_values_array(alloc, fileCount); for(size_t i = 0; i < fileCount; i++) { - nn_values_set(arr, i, nn_values_string(files[i], strlen(files[i]))); - nn_free(files[i]); + nn_values_set(arr, i, nn_values_string(alloc, files[i], strlen(files[i]))); + nn_deallocStr(alloc, files[i]); } - nn_free(files); + nn_dealloc(alloc, files, sizeof(char *) * fileCount); nn_return(computer, arr); } @@ -356,7 +358,8 @@ void nn_fs_read(nn_filesystem *fs, void *_, nn_component *component, nn_computer if(len > capacity) len = capacity; size_t byteLen = len; - char *buf = nn_malloc(byteLen); + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); + char *buf = nn_alloc(alloc, byteLen); if(buf == NULL) { nn_setCError(computer, "out of memory"); return; @@ -365,9 +368,9 @@ void nn_fs_read(nn_filesystem *fs, void *_, nn_component *component, nn_computer size_t readLen = fs->read(component, fs->userdata, fd, buf, byteLen); if(readLen > 0) { // Nothing read means EoF. - nn_return(computer, nn_values_string(buf, readLen)); + nn_return_string(computer, buf, readLen); } - nn_free(buf); + nn_dealloc(alloc, buf, byteLen); // do not ask where it comes from, balance is hard nn_fs_readCost(fs, nn_fs_countChunks(fs, readLen, component), component, computer); @@ -410,7 +413,7 @@ void nn_fs_seek(nn_filesystem *fs, void *_, nn_component *component, nn_computer } void nn_loadFilesystemTable(nn_universe *universe) { - nn_componentTable *fsTable = nn_newComponentTable("filesystem", NULL, NULL, (void *)nn_fs_destroy); + nn_componentTable *fsTable = nn_newComponentTable(nn_getAllocator(universe), "filesystem", NULL, NULL, (void *)nn_fs_destroy); nn_storeUserdata(universe, "NN:FILESYSTEM", fsTable); nn_defineMethod(fsTable, "getLabel", false, (void *)nn_fs_getLabel, NULL, "getLabel(): string - Returns the label of the filesystem."); diff --git a/src/components/gpu.c b/src/components/gpu.c index 2110fa7..71f9aea 100644 --- a/src/components/gpu.c +++ b/src/components/gpu.c @@ -4,6 +4,7 @@ #include typedef struct nni_gpu { + nn_Alloc alloc; nn_screen *currentScreen; nn_address screenAddress; nn_gpuControl ctrl; @@ -34,8 +35,10 @@ bool nni_inBounds(nni_gpu *gpu, int x, int y) { true; } -nni_gpu *nni_newGPU(nn_gpuControl *ctrl) { - nni_gpu *gpu = nn_malloc(sizeof(nni_gpu)); +nni_gpu *nni_newGPU(nn_Alloc *alloc, nn_gpuControl *ctrl) { + nni_gpu *gpu = nn_alloc(alloc, sizeof(nni_gpu)); + if(gpu == NULL) return NULL; + gpu->alloc = *alloc; gpu->currentScreen = NULL; gpu->screenAddress = NULL; gpu->ctrl = *ctrl; @@ -50,10 +53,11 @@ void nni_gpuDeinit(nni_gpu *gpu) { if(gpu->currentScreen != NULL) { nn_destroyScreen(gpu->currentScreen); } + nn_Alloc a = gpu->alloc; if(gpu->screenAddress != NULL) { - nn_free(gpu->screenAddress); + nn_deallocStr(&a, gpu->screenAddress); } - nn_free(gpu); + nn_dealloc(&a, gpu, sizeof(nni_gpu)); } nn_scrchr_t nni_gpu_makePixel(nni_gpu *gpu, const char *s) { @@ -111,9 +115,9 @@ void nni_gpu_bind(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c gpu->currentScreen = screen; if(gpu->screenAddress != NULL) { - nn_free(gpu->screenAddress); + nn_deallocStr(&gpu->alloc, gpu->screenAddress); } - gpu->screenAddress = nn_strdup(addr); + gpu->screenAddress = nn_strdup(&gpu->alloc, addr); nn_addHeat(computer, gpu->ctrl.bindHeat); nn_callCost(computer, gpu->ctrl.bindCost); @@ -170,7 +174,7 @@ void nni_gpu_get(nni_gpu *gpu, void *_, nn_component *component, nn_computer *co void nni_gpu_getScreen(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { if(gpu->screenAddress == NULL) return; - nn_return(computer, nn_values_string(gpu->screenAddress, 0)); + nn_return_string(computer, gpu->screenAddress, 0); } void nni_gpu_maxResolution(nni_gpu *gpu, void *_, nn_component *component, nn_computer *computer) { @@ -360,7 +364,7 @@ void nni_gpu_copy(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c int changes = 0, clears = 0; - nn_scrchr_t *tmpBuffer = nn_malloc(sizeof(nn_scrchr_t) * w * h); + nn_scrchr_t *tmpBuffer = nn_alloc(&gpu->alloc, sizeof(nn_scrchr_t) * w * h); if(tmpBuffer == NULL) { nn_setCError(computer, "out of memory"); return; @@ -388,7 +392,7 @@ void nni_gpu_copy(nni_gpu *gpu, void *_, nn_component *component, nn_computer *c } } - nn_free(tmpBuffer); + nn_dealloc(&gpu->alloc, tmpBuffer, sizeof(nn_scrchr_t) * w * h); nn_addHeat(computer, gpu->ctrl.pixelChangeHeat * changes); nn_callCost(computer, gpu->ctrl.pixelChangeCost * changes); @@ -411,7 +415,7 @@ void nni_gpu_getViewport(nni_gpu *gpu, void *_, nn_component *component, nn_comp } void nn_loadGraphicsCardTable(nn_universe *universe) { - nn_componentTable *gpuTable = nn_newComponentTable("gpu", NULL, NULL, (void *)nni_gpuDeinit); + nn_componentTable *gpuTable = nn_newComponentTable(nn_getAllocator(universe), "gpu", NULL, NULL, (void *)nni_gpuDeinit); nn_storeUserdata(universe, "NN:GPU", gpuTable); nn_defineMethod(gpuTable, "bind", false, (void *)nni_gpu_bind, NULL, "bind(addr: string[, reset: boolean = false]): boolean - Bind a GPU to a screen. Very expensive. If reset is true, it will clear the screen."); @@ -432,7 +436,7 @@ void nn_loadGraphicsCardTable(nn_universe *universe) { nn_component *nn_addGPU(nn_computer *computer, nn_address address, int slot, nn_gpuControl *control) { nn_componentTable *gpuTable = nn_queryUserdata(nn_getUniverse(computer), "NN:GPU"); - nni_gpu *gpu = nni_newGPU(control); + nni_gpu *gpu = nni_newGPU(nn_getAllocator(nn_getUniverse(computer)), control); if(gpu == NULL) { return NULL; } diff --git a/src/components/keyboard.c b/src/components/keyboard.c index cbea043..bbb300e 100644 --- a/src/components/keyboard.c +++ b/src/components/keyboard.c @@ -1,7 +1,7 @@ #include "../neonucleus.h" void nn_loadKeyboardTable(nn_universe *universe) { - nn_componentTable *keyboardTable = nn_newComponentTable("keyboard", NULL, NULL, NULL); + nn_componentTable *keyboardTable = nn_newComponentTable(nn_getAllocator(universe), "keyboard", NULL, NULL, NULL); nn_storeUserdata(universe, "NN:KEYBOARD", keyboardTable); } diff --git a/src/components/screen.c b/src/components/screen.c index 5f0c5d5..e80f82a 100644 --- a/src/components/screen.c +++ b/src/components/screen.c @@ -1,10 +1,11 @@ #include "screen.h" #include -nn_screen *nn_newScreen(int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) { - nn_screen *screen = nn_malloc(sizeof(nn_screen)); - screen->buffer = nn_malloc(sizeof(nn_scrchr_t) * maxWidth * maxHeight); - screen->lock = nn_newGuard(); +nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) { + nn_screen *screen = nn_alloc(alloc, sizeof(nn_screen)); + screen->alloc = *alloc; + screen->buffer = nn_alloc(alloc, sizeof(nn_scrchr_t) * maxWidth * maxHeight); + screen->lock = nn_newGuard(alloc); screen->refc = 1; screen->width = maxWidth; screen->height = maxHeight; @@ -16,7 +17,7 @@ nn_screen *nn_newScreen(int maxWidth, int maxHeight, int maxDepth, int editableC screen->depth = maxDepth; screen->editableColors = editableColors; screen->paletteColors = paletteColors; - screen->palette = nn_malloc(sizeof(int) * screen->paletteColors); + screen->palette = nn_alloc(alloc, sizeof(int) * screen->paletteColors); memset(screen->palette, 0, sizeof(int) * screen->paletteColors); screen->aspectRatioWidth = 1; screen->aspectRatioHeight = 1; @@ -34,10 +35,11 @@ void nn_retainScreen(nn_screen *screen) { void nn_destroyScreen(nn_screen *screen) { if(!nn_decRef(&screen->refc)) return; - nn_deleteGuard(screen->lock); - nn_free(screen->buffer); - nn_free(screen->palette); - nn_free(screen); + nn_Alloc a = screen->alloc; + nn_deleteGuard(&a, screen->lock); + nn_dealloc(&a, screen->buffer, sizeof(nn_scrchr_t) * screen->maxWidth * screen->maxHeight); + nn_dealloc(&a, screen->palette, sizeof(int) * screen->paletteColors); + nn_dealloc(&a, screen, sizeof(nn_screen)); } void nn_lockScreen(nn_screen *screen) { @@ -85,14 +87,14 @@ void nn_setAspectRatio(nn_screen *screen, int width, int height) { void nn_addKeyboard(nn_screen *screen, nn_address address) { if(screen->keyboardCount == NN_MAX_SCREEN_KEYBOARDS) return; - screen->keyboards[screen->keyboardCount++] = nn_strdup(address); + screen->keyboards[screen->keyboardCount++] = nn_strdup(&screen->alloc, address); } void nn_removeKeyboard(nn_screen *screen, nn_address address) { size_t j = 0; for(size_t i = 0; i < screen->keyboardCount; i++) { if(strcmp(screen->keyboards[i], address) == 0) { - nn_free(screen->keyboards[i]); + nn_deallocStr(&screen->alloc, screen->keyboards[i]); } else { screen->keyboards[j] = screen->keyboards[i]; j++; @@ -206,12 +208,12 @@ void nn_screenComp_destroy(void *_, nn_component *component, nn_screen *screen) void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *component, nn_computer *computer) { nn_lockScreen(screen); - nn_value arr = nn_values_array(nn_getKeyboardCount(screen)); + nn_value arr = nn_values_array(&screen->alloc, nn_getKeyboardCount(screen)); size_t len = arr.array->len; for(size_t i = 0; i < len; i++) { size_t addrlen = strlen(nn_getKeyboard(screen, i)); - nn_value addr = nn_values_string(nn_getKeyboard(screen, i), addrlen); + nn_value addr = nn_values_string(&screen->alloc, nn_getKeyboard(screen, i), addrlen); nn_values_set(arr, i, addr); } @@ -220,7 +222,7 @@ void nn_screenComp_getKeyboards(nn_screen *screen, void *_, nn_component *compon } void nn_loadScreenTable(nn_universe *universe) { - nn_componentTable *screenTable = nn_newComponentTable("screen", NULL, NULL, (void *)nn_screenComp_destroy); + nn_componentTable *screenTable = nn_newComponentTable(nn_getAllocator(universe), "screen", NULL, NULL, (void *)nn_screenComp_destroy); nn_storeUserdata(universe, "NN:SCREEN", screenTable); nn_defineMethod(screenTable, "getKeyboards", false, (void *)nn_screenComp_getKeyboards, NULL, "getKeyboards(): string[] - Returns the keyboards registered to this screen."); diff --git a/src/components/screen.h b/src/components/screen.h index f620bda..f7fec7a 100644 --- a/src/components/screen.h +++ b/src/components/screen.h @@ -4,6 +4,7 @@ #include "../neonucleus.h" typedef struct nn_screen { + nn_Alloc alloc; nn_scrchr_t *buffer; nn_guard *lock; nn_refc refc; diff --git a/src/computer.c b/src/computer.c index e621492..1504063 100644 --- a/src/computer.c +++ b/src/computer.c @@ -1,26 +1,27 @@ #include "computer.h" #include "component.h" +#include "universe.h" #include "neonucleus.h" #include nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit) { - nn_computer *c = nn_malloc(sizeof(nn_computer)); - c->components = nn_malloc(sizeof(nn_component) * componentLimit); + nn_computer *c = nn_alloc(&universe->alloc, sizeof(nn_computer)); + c->components = nn_alloc(&universe->alloc, sizeof(nn_component) * componentLimit); if(c->components == NULL) { - nn_free(c); + nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); return NULL; } - c->address = nn_strdup(address); + c->address = nn_strdup(&universe->alloc, address); if(c->address == NULL) { - nn_free(c->components); - nn_free(c); + nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit); + nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); return NULL; } - c->lock = nn_newGuard(); + c->lock = nn_newGuard(&universe->alloc); if(c->lock == NULL) { - nn_free(c->address); - nn_free(c->components); - nn_free(c); + nn_deallocStr(&universe->alloc, c->address); + nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit); + nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); return NULL; } c->timeOffset = nn_getTime(universe); @@ -50,10 +51,10 @@ nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_archit // Setup Architecture c->archState = c->arch->setup(c, c->arch->userdata); if(c->archState == NULL) { - nn_deleteGuard(c->lock); - nn_free(c->address); - nn_free(c->components); - nn_free(c); + nn_deleteGuard(&universe->alloc, c->lock); + nn_deallocStr(&universe->alloc, c->address); + nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit); + nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); return NULL; } @@ -65,8 +66,8 @@ nn_universe *nn_getUniverse(nn_computer *computer) { } void nn_setTmpAddress(nn_computer *computer, nn_address tmp) { - nn_free(computer->tmpAddress); - computer->tmpAddress = nn_strdup(tmp); + nn_deallocStr(&computer->universe->alloc, computer->tmpAddress); + computer->tmpAddress = nn_strdup(&computer->universe->alloc, tmp); } nn_address nn_getComputerAddress(nn_computer *computer) { @@ -130,15 +131,15 @@ void nn_deleteComputer(nn_computer *computer) { while(computer->signalCount > 0) { nn_popSignal(computer); } + nn_Alloc *a = &computer->universe->alloc; for(size_t i = 0; i < computer->userCount; i++) { - nn_free(computer->users[i]); + nn_deallocStr(a, computer->users[i]); } computer->arch->teardown(computer, computer->archState, computer->arch->userdata); - nn_deleteGuard(computer->lock); - nn_free(computer->components); - nn_free(computer->address); - nn_free(computer->tmpAddress); - nn_free(computer); + nn_deleteGuard(a, computer->lock); + nn_deallocStr(a, computer->address); + nn_dealloc(a, computer->components, sizeof(nn_component) * computer->componentCap); + nn_dealloc(a, computer->components, sizeof(nn_computer)); } const char *nn_pushSignal(nn_computer *computer, nn_value *values, size_t len) { @@ -183,7 +184,7 @@ void nn_popSignal(nn_computer *computer) { const char *nn_addUser(nn_computer *computer, const char *name) { if(computer->userCount == NN_MAX_USERS) return "too many users"; - char *user = nn_strdup(name); + char *user = nn_strdup(&computer->universe->alloc, name); if(user == NULL) return "out of memory"; computer->users[computer->userCount] = user; computer->userCount++; @@ -195,7 +196,7 @@ void nn_deleteUser(nn_computer *computer, const char *name) { for(size_t i = 0; i < computer->userCount; i++) { char *user = computer->users[i]; if(strcmp(user, name) == 0) { - nn_free(user); + nn_deallocStr(&computer->universe->alloc, user); } else { computer->users[j] = user; j++; @@ -322,7 +323,7 @@ const char *nn_getError(nn_computer *computer) { void nn_clearError(nn_computer *computer) { if(computer->allocatedError) { - nn_free(computer->err); + nn_deallocStr(&computer->universe->alloc, computer->err); } computer->err = NULL; computer->allocatedError = false; @@ -330,7 +331,7 @@ void nn_clearError(nn_computer *computer) { void nn_setError(nn_computer *computer, const char *err) { nn_clearError(computer); - char *copy = nn_strdup(err); + char *copy = nn_strdup(&computer->universe->alloc, err); if(copy == NULL) { nn_setCError(computer, "out of memory"); return; @@ -360,7 +361,7 @@ nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slo computer->componentLen++; } - c->address = nn_strdup(address); + c->address = nn_strdup(&computer->universe->alloc, address); if(c->address == NULL) return NULL; c->table = table; c->slot = slot; @@ -382,7 +383,7 @@ void nn_removeComponent(nn_computer *computer, nn_address address) { } void nn_destroyComponent(nn_component *component) { - nn_free(component->address); + nn_deallocStr(&component->computer->universe->alloc, component->address); if(component->table->destructor != NULL) { component->table->destructor(component->table->userdata, component, component->statePtr); } @@ -391,6 +392,7 @@ void nn_destroyComponent(nn_component *component) { nn_component *nn_findComponent(nn_computer *computer, nn_address address) { for(size_t i = 0; i < computer->componentLen; i++) { + if(computer->components[i].address == NULL) continue; // empty slot if(strcmp(computer->components[i].address, address) == 0) { return computer->components + i; } @@ -398,19 +400,13 @@ nn_component *nn_findComponent(nn_computer *computer, nn_address address) { return NULL; } -nn_component **nn_listComponent(nn_computer *computer, size_t *len) { - nn_component **c = nn_malloc(sizeof(nn_component *) * computer->componentLen); - if(c == NULL) return NULL; - size_t j = 0; - for(size_t i = 0; i < computer->componentLen; i++) { - nn_component *component = computer->components + i; - if(component->address != NULL) { - c[j] = component; - j++; - } +nn_component *nn_iterComponent(nn_computer *computer, size_t *internalIndex) { + for(size_t i = *internalIndex; i < computer->componentLen; i++) { + if(computer->components[i].address == NULL) continue; + *internalIndex = i+1; + return computer->components + i; } - *len = j; - return c; + return NULL; } void nn_resetCall(nn_computer *computer) { @@ -471,3 +467,49 @@ void nn_lockComputer(nn_computer *computer) { void nn_unlockComputer(nn_computer *computer) { nn_unlock(computer->lock); } + +void nn_return_nil(nn_computer *computer) { + nn_return(computer, nn_values_nil()); +} + +void nn_return_integer(nn_computer *computer, intptr_t integer) { + nn_return(computer, nn_values_integer(integer)); +} + +void nn_return_number(nn_computer *computer, double number) { + nn_return(computer, nn_values_number(number)); +} + +void nn_return_boolean(nn_computer *computer, bool boolean) { + nn_return(computer, nn_values_boolean(boolean)); +} + +void nn_return_cstring(nn_computer *computer, const char *cstr) { + nn_return(computer, nn_values_cstring(cstr)); +} + +void nn_return_string(nn_computer *computer, const char *str, size_t len) { + nn_value val = nn_values_string(&computer->universe->alloc, str, len); + if(val.tag == NN_VALUE_NIL) { + nn_setCError(computer, "out of memory"); + } + nn_return(computer, val); +} + +nn_value nn_return_array(nn_computer *computer, size_t len) { + nn_value val = nn_values_array(&computer->universe->alloc, len); + if(val.tag == NN_VALUE_NIL) { + nn_setCError(computer, "out of memory"); + } + nn_return(computer, val); + return val; +} + +nn_value nn_return_table(nn_computer *computer, size_t len) { + nn_value val = nn_values_table(&computer->universe->alloc, len); + if(val.tag == NN_VALUE_NIL) { + nn_setCError(computer, "out of memory"); + } + nn_return(computer, val); + return val; +} diff --git a/src/emulator.c b/src/emulator.c index 4474d79..141ac9b 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -184,16 +184,16 @@ size_t ne_fs_read(nn_component *component, ne_fs *fs, int fd, char *buf, size_t return fread(buf, sizeof(char), required, f); } -char **ne_fs_list(nn_component *component, ne_fs *fs, const char *path, size_t *len) { +char **ne_fs_list(nn_Alloc *alloc, nn_component *component, ne_fs *fs, const char *path, size_t *len) { const char *p = ne_fs_diskPath(component, path); if(p[0] == '/') p++; FilePathList files = LoadDirectoryFiles(p); *len = files.count; - char **buf = nn_malloc(sizeof(char *) * files.count); + char **buf = nn_alloc(alloc, sizeof(char *) * files.count); for(size_t i = 0; i < files.count; i++) { - buf[i] = nn_strdup(GetFileName(files.paths[i])); + buf[i] = nn_strdup(alloc, GetFileName(files.paths[i])); } UnloadDirectoryFiles(files); @@ -466,7 +466,12 @@ int keycode_to_oc(int keycode) { int main() { printf("Setting up universe\n"); - nn_universe *universe = nn_newUniverse(); + nn_Alloc alloc = nn_libcAllocator(); + nn_universe *universe = nn_newUniverse(alloc); + if(universe == NULL) { + printf("Failed to create universe\n"); + return 1; + } nn_loadCoreComponentTables(universe); nn_architecture *arch = testLuaArch_getArchitecture("src/sandbox.lua"); @@ -528,7 +533,7 @@ int main() { }; nn_addFileSystem(computer, "OpenOS", 1, &genericFS); - nn_screen *s = nn_newScreen(80, 32, 16, 16, 256); + nn_screen *s = nn_newScreen(&alloc, 80, 32, 16, 16, 256); nn_addKeyboard(s, "shitty keyboard"); nn_mountKeyboard(computer, "shitty keyboard", 2); nn_addScreen(computer, "Main Screen", 2, s); diff --git a/src/lock.c b/src/lock.c index 2fdc20a..5777a7b 100644 --- a/src/lock.c +++ b/src/lock.c @@ -5,8 +5,8 @@ typedef struct nn_guard { mtx_t m; } nn_guard; -nn_guard *nn_newGuard() { - nn_guard *g = nn_malloc(sizeof(nn_guard)); +nn_guard *nn_newGuard(nn_Alloc *alloc) { + nn_guard *g = nn_alloc(alloc, sizeof(nn_guard)); if(g == NULL) return NULL; mtx_init(&g->m, mtx_recursive); return g; @@ -22,9 +22,10 @@ void nn_unlock(nn_guard *guard) { mtx_unlock(&guard->m); } -void nn_deleteGuard(nn_guard *guard) { +void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard) { if(guard == NULL) return; mtx_destroy(&guard->m); + nn_dealloc(alloc, guard, sizeof(nn_guard)); } void nn_addRef(nn_refc *refc, size_t count) { diff --git a/src/neonucleus.h b/src/neonucleus.h index f92e0bd..b582b66 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -90,6 +90,23 @@ typedef struct nn_architecture { } nn_architecture; typedef char *nn_address; +// A non-zero malloc is a null ptr, with a 0 oldSize, but a non-0 newSize. +// A zero malloc is never called, the proc address itself is returned, which is ignored when freeing. +// A free is a non-null ptr, with a non-zero oldSize, but a newSize of 0. +// A realloc is a non-null ptr, with a non-zero oldSize, and a non-zero newSize. +typedef void *nn_AllocProc(void *userdata, void *ptr, size_t oldSize, size_t newSize, void *extra); + +typedef struct nn_Alloc { + void *userdata; + nn_AllocProc *proc; +} nn_Alloc; + +// TODO: write a bunch of utils so this *can* work on baremetal. + +#ifndef NN_BAREMETAL +nn_Alloc nn_libcAllocator(); +#endif + // Values for architectures #define NN_VALUE_INT 0 @@ -105,18 +122,21 @@ typedef struct nn_string { char *data; size_t len; size_t refc; + nn_Alloc alloc; } nn_string; typedef struct nn_array { struct nn_value *values; size_t len; size_t refc; + nn_Alloc alloc; } nn_array; typedef struct nn_object { struct nn_pair *pairs; size_t len; size_t refc; + nn_Alloc alloc; } nn_table; typedef struct nn_value { @@ -138,18 +158,19 @@ typedef struct nn_pair { } nn_pair; // we expose the allocator because of some utilities -void *nn_malloc(size_t size); -void *nn_realloc(void *memory, size_t newSize); -void nn_free(void *memory); +void *nn_alloc(nn_Alloc *alloc, size_t size); +void *nn_resize(nn_Alloc *alloc, void *memory, size_t oldSize, size_t newSize); +void nn_dealloc(nn_Alloc *alloc, void *memory, size_t size); // Utilities, both internal and external -char *nn_strdup(const char *s); -void *nn_memdup(const void *buf, size_t len); +char *nn_strdup(nn_Alloc *alloc, const char *s); +void *nn_memdup(nn_Alloc *alloc, const void *buf, size_t len); +void nn_deallocStr(nn_Alloc *alloc, char *s); -nn_guard *nn_newGuard(); +nn_guard *nn_newGuard(nn_Alloc *alloc); void nn_lock(nn_guard *guard); void nn_unlock(nn_guard *guard); -void nn_deleteGuard(nn_guard *guard); +void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard); void nn_addRef(nn_refc *refc, size_t count); void nn_incRef(nn_refc *refc); @@ -159,10 +180,10 @@ bool nn_removeRef(nn_refc *refc, size_t count); bool nn_decRef(nn_refc *refc); bool nn_unicode_validate(const char *s); -// returned string must be nn_free()'d -char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount); -// returned array must be nn_free()'d -unsigned int *nn_unicode_codepoints(const char *s); +// returned string must be nn_deallocStr()'d +char *nn_unicode_char(nn_Alloc *alloc, unsigned int *codepoints, size_t codepointCount); +// returned array must be nn_dealloc()'d +unsigned int *nn_unicode_codepoints(nn_Alloc *alloc, const char *s, size_t *len); size_t nn_unicode_len(const char *s); unsigned int nn_unicode_codepointAt(const char *s, size_t byteOffset); size_t nn_unicode_codepointSize(unsigned int codepoint); @@ -170,9 +191,11 @@ const char *nn_unicode_codepointToChar(unsigned int codepoint, size_t *len); size_t nn_unicode_charWidth(unsigned int codepoint); size_t nn_unicode_wlen(const char *s); unsigned int nn_unicode_upperCodepoint(unsigned int codepoint); -char *nn_unicode_upper(const char *s); +// returned string must be nn_deallocStr()'d +char *nn_unicode_upper(nn_Alloc *alloc, const char *s); unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint); -char *nn_unicode_lower(const char *s); +// returned string must be nn_deallocStr()'d +char *nn_unicode_lower(nn_Alloc *alloc, const char *s); double nn_realTime(); double nn_realTimeClock(void *_); @@ -183,7 +206,8 @@ void nn_randomLatency(double min, double max); typedef double nn_clock_t(void *_); -nn_universe *nn_newUniverse(); +nn_universe *nn_newUniverse(nn_Alloc alloc); +nn_Alloc *nn_getAllocator(nn_universe *universe); void nn_unsafeDeleteUniverse(nn_universe *universe); void *nn_queryUserdata(nn_universe *universe, const char *name); void nn_storeUserdata(nn_universe *universe, const char *name, void *data); @@ -300,8 +324,11 @@ nn_componentTable *nn_getComponentTable(nn_component *component); const char *nn_getComponentType(nn_componentTable *table); void *nn_getComponentUserdata(nn_component *component); nn_component *nn_findComponent(nn_computer *computer, nn_address address); -/* RESULT SHOULD BE NN_FREE()'D OR ELSE MEMORY IS LEAKED */ -nn_component **nn_listComponent(nn_computer *computer, size_t *len); +// the internal index is not the array index, but rather an index into +// an internal structure. YOU SHOULD NOT ADD OR REMOVE COMPONENTS WHILE ITERATING. +// the internalIndex SHOULD BE INITIALIZED TO 0. +// Returns NULL at the end +nn_component *nn_iterComponent(nn_computer *computer, size_t *internalIndex); // Component VTable stuff @@ -309,7 +336,7 @@ typedef void *nn_componentConstructor(void *tableUserdata, void *componentUserda typedef void *nn_componentDestructor(void *tableUserdata, nn_component *component, void *componentUserdata); typedef void nn_componentMethod(void *componentUserdata, void *methodUserdata, nn_component *component, nn_computer *computer); -nn_componentTable *nn_newComponentTable(const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor); +nn_componentTable *nn_newComponentTable(nn_Alloc *alloc, const char *typeName, void *userdata, nn_componentConstructor *constructor, nn_componentDestructor *destructor); void nn_destroyComponentTable(nn_componentTable *table); void nn_defineMethod(nn_componentTable *table, const char *methodName, bool direct, nn_componentMethod *methodFunc, void *methodUserdata, const char *methodDoc); const char *nn_getTableMethod(nn_componentTable *table, size_t idx, bool *outDirect); @@ -334,9 +361,18 @@ nn_value nn_values_integer(intptr_t integer); nn_value nn_values_number(double num); nn_value nn_values_boolean(bool boolean); nn_value nn_values_cstring(const char *string); -nn_value nn_values_string(const char *string, size_t len); -nn_value nn_values_array(size_t len); -nn_value nn_values_table(size_t pairCount); +nn_value nn_values_string(nn_Alloc *alloc, const char *string, size_t len); +nn_value nn_values_array(nn_Alloc *alloc, size_t len); +nn_value nn_values_table(nn_Alloc *alloc, size_t pairCount); + +void nn_return_nil(nn_computer *computer); +void nn_return_integer(nn_computer *computer, intptr_t integer); +void nn_return_number(nn_computer *computer, double number); +void nn_return_boolean(nn_computer *computer, bool boolean); +void nn_return_cstring(nn_computer *computer, const char *cstr); +void nn_return_string(nn_computer *computer, const char *str, size_t len); +nn_value nn_return_array(nn_computer *computer, size_t len); +nn_value nn_return_table(nn_computer *computer, size_t len); size_t nn_values_getType(nn_value val); nn_value nn_values_retain(nn_value val); @@ -471,10 +507,13 @@ typedef struct nn_filesystem { // directory operations bool (*isDirectory)(nn_component *component, void *userdata, const char *path); bool (*makeDirectory)(nn_component *component, void *userdata, const char *path); - // the length and array must be nn_alloc'd. - // The strings must be NULL-terminated and also nn_alloc'd. - // See nn_strdup(). - char **(*list)(nn_component *component, void *userdata, const char *path, size_t *len); + // The returned array should be allocated with the supplied allocator. + // The strings should be null terminated. Use nn_strdup for the allocation to guarantee nn_deallocStr deallocates it correctly. + // For the array, the *exact* size of the allocation should be sizeof(char *) * (*len), + // If it is not, the behavior is undefined. + // We recommend first computing len then allocating, though if that is not doable or practical, + // consider nn_resize()ing it to the correct size to guarantee a correct deallocation. + char **(*list)(nn_Alloc *alloc, nn_component *component, void *userdata, const char *path, size_t *len); // file operations size_t (*open)(nn_component *component, void *userdata, const char *path, const char *mode); @@ -549,7 +588,7 @@ typedef struct nn_scrchr_t { bool isBgPalette; } nn_scrchr_t; -nn_screen *nn_newScreen(int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors); +nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors); nn_componentTable *nn_getScreenTable(nn_universe *universe); void nn_retainScreen(nn_screen *screen); diff --git a/src/testLuaArch.c b/src/testLuaArch.c index 78bb0f2..5c7f761 100644 --- a/src/testLuaArch.c +++ b/src/testLuaArch.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "neonucleus.h" @@ -40,6 +41,13 @@ testLuaArch *testLuaArch_get(lua_State *L) { return arch; } +nn_Alloc *testLuaArch_getAlloc(lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "archPtr"); + testLuaArch *arch = lua_touserdata(L, -1); + lua_pop(L, 1); + return nn_getAllocator(nn_getUniverse(arch->computer)); +} + const char *testLuaArch_pushlstring(lua_State *L, const char *s, size_t len) { if (lua_checkstack(L, 1) == 0) { return NULL; @@ -58,9 +66,10 @@ const char *testLuaArch_pushstring(lua_State *L, const char *s) { void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize) { + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(arch->computer)); if(nsize == 0) { arch->memoryUsed -= osize; - nn_free(ptr); + free(ptr); return NULL; } else { size_t actualOldSize = osize; @@ -70,7 +79,7 @@ void *testLuaArch_alloc(testLuaArch *arch, void *ptr, size_t osize, size_t nsize } arch->memoryUsed -= actualOldSize; arch->memoryUsed += nsize; - return nn_realloc(ptr, nsize); + return realloc(ptr, nsize); } } @@ -80,6 +89,7 @@ nn_computer *testLuaArch_getComputer(lua_State *L) { static nn_value testLuaArch_getValue(lua_State *L, int index) { int type = lua_type(L, index); + nn_Alloc *alloc = testLuaArch_getAlloc(L); if(type == LUA_TBOOLEAN) { return nn_values_boolean(lua_toboolean(L, index)); @@ -90,7 +100,7 @@ static nn_value testLuaArch_getValue(lua_State *L, int index) { if(type == LUA_TSTRING) { size_t l = 0; const char *s = lua_tolstring(L, index, &l); - return nn_values_string(s, l); + return nn_values_string(alloc, s, l); } if(type == LUA_TNUMBER && lua_isinteger(L, index)) { return nn_values_integer(lua_tointeger(L, index)); @@ -330,17 +340,12 @@ static int testLuaArch_computer_setState(lua_State *L) { static int testLuaArch_component_list(lua_State *L) { nn_computer *c = testLuaArch_getComputer(L); - size_t len = 0; - nn_component **components = nn_listComponent(c, &len); - if(components == NULL) { - lua_pushnil(L); - lua_pushstring(L, "out of memory"); - return 2; - } - lua_createtable(L, 0, len); + lua_createtable(L, 0, 10); + size_t iter = 0; int list = lua_gettop(L); - for(size_t i = 0; i < len; i++) { - nn_component *component = components[i]; + while(true) { + nn_component *component = nn_iterComponent(c, &iter); + if(component == NULL) break; nn_componentTable *table = nn_getComponentTable(component); nn_address addr = nn_getComponentAddress(component); const char *type = nn_getComponentType(table); @@ -348,7 +353,6 @@ static int testLuaArch_component_list(lua_State *L) { lua_pushstring(L, type); lua_setfield(L, list, addr); } - nn_free(components); return 1; } @@ -463,6 +467,7 @@ static int testLuaArch_component_invoke(lua_State *L) { int testLuaArch_unicode_sub(lua_State *L) { const char *s = luaL_checkstring(L, 1); + nn_Alloc *alloc = testLuaArch_getAlloc(L); int start = luaL_checkinteger(L, 2); if(!nn_unicode_validate(s)) { luaL_error(L, "invalid utf-8"); @@ -500,15 +505,20 @@ int testLuaArch_unicode_sub(lua_State *L) { // there is a way to do it without an allocation // however, I'm lazy - unsigned int *points = nn_unicode_codepoints(s); + size_t pointLen; + unsigned int *points = nn_unicode_codepoints(alloc, s, &pointLen); if(points == NULL) { luaL_error(L, "out of memory"); } - char *sub = nn_unicode_char(points + start - 1, stop - start + 1); + char *sub = nn_unicode_char(alloc, points + start - 1, stop - start + 1); + if(sub == NULL) { + nn_dealloc(alloc, points, sizeof(unsigned int) * pointLen); + luaL_error(L, "out of memory"); + } const char *res = testLuaArch_pushstring(L, sub); - nn_free(sub); - nn_free(points); + nn_deallocStr(alloc, sub); + nn_dealloc(alloc, points, sizeof(unsigned int) * pointLen); if (!res) { luaL_error(L, "out of memory"); } @@ -518,23 +528,24 @@ int testLuaArch_unicode_sub(lua_State *L) { int testLuaArch_unicode_char(lua_State *L) { int argc = lua_gettop(L); - unsigned int *codepoints = nn_malloc(sizeof(unsigned int) * argc); + nn_Alloc *alloc = testLuaArch_getAlloc(L); + unsigned int *codepoints = nn_alloc(alloc, sizeof(unsigned int) * argc); if(codepoints == NULL) { luaL_error(L, "out of memory"); } for(int i = 0; i < argc; i++) { int idx = i + 1; if(!lua_isinteger(L, idx)) { - nn_free(codepoints); + nn_dealloc(alloc, codepoints, sizeof(unsigned int) * argc); luaL_argerror(L, idx, "integer expected"); return 0; } codepoints[i] = lua_tointeger(L, idx); } - char *s = nn_unicode_char(codepoints, argc); + char *s = nn_unicode_char(alloc, codepoints, argc); const char *res = testLuaArch_pushstring(L, s); - nn_free(s); - nn_free(codepoints); + nn_deallocStr(alloc, s); + nn_dealloc(alloc, codepoints, sizeof(unsigned int) * argc); if (!res) { luaL_error(L, "out of memory"); } @@ -649,7 +660,8 @@ void testLuaArch_loadEnv(lua_State *L) { } testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) { - testLuaArch *s = nn_malloc(sizeof(testLuaArch)); + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); + testLuaArch *s = nn_alloc(alloc, sizeof(testLuaArch)); if(s == NULL) return NULL; s->memoryUsed = 0; s->computer = computer; @@ -665,8 +677,9 @@ testLuaArch *testLuaArch_setup(nn_computer *computer, void *_) { } void testLuaArch_teardown(nn_computer *computer, testLuaArch *arch, void *_) { + nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); lua_close(arch->L); - nn_free(arch); + nn_dealloc(alloc, arch, sizeof(testLuaArch)); } void testLuaArch_tick(nn_computer *computer, testLuaArch *arch, void *_) { @@ -719,7 +732,7 @@ nn_architecture *testLuaArch_getArchitecture(const char *sandboxPath) { if(f == NULL) return NULL; fseek(f, 0, SEEK_END); size_t l = ftell(f); - testLuaSandbox = nn_malloc(l+1); + testLuaSandbox = malloc(l+1); if(testLuaSandbox == NULL) { fclose(f); return NULL; diff --git a/src/unicode.c b/src/unicode.c index bca67b2..27e78a5 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -205,14 +205,14 @@ bool nn_unicode_validate(const char *b) { // It is used to power the Lua architecture's Unicode API re-implementation. // It can also just be used to deal with unicode. -char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount) { +char *nn_unicode_char(nn_Alloc *alloc, unsigned int *codepoints, size_t codepointCount) { size_t len = 0; for (size_t i = 0; i < codepointCount; i++) { unsigned int codepoint = codepoints[i]; len += nn_unicode_codepointSize(codepoint); } - char *buf = nn_malloc(len+1); + char *buf = nn_alloc(alloc, len+1); if (buf == NULL) return buf; size_t j = 0; @@ -224,15 +224,18 @@ char *nn_unicode_char(unsigned int *codepoints, size_t codepointCount) { j += codepointLen; } buf[j] = '\0'; - assert(j == len); // better safe than sorry + // this can only fail if size_t is smaller than a pointer and overflowed. + // IF THIS HAPPENS, THE SYSTEM HEADERS ARE BUGGED. + assert(j == len); return buf; } -unsigned int *nn_unicode_codepoints(const char *s) { +unsigned int *nn_unicode_codepoints(nn_Alloc *alloc, const char *s, size_t *len) { size_t l = nn_unicode_len(s); - unsigned int *buf = nn_malloc(sizeof(unsigned int) * l); + unsigned int *buf = nn_alloc(alloc, sizeof(unsigned int) * l); if(buf == NULL) return NULL; + if(len != NULL) *len = l; size_t cur = 0; size_t bufidx = 0; while(s[cur] != 0) { @@ -363,6 +366,6 @@ size_t nn_unicode_wlen(const char *s) { // NOT IMPLEMENTED YET unsigned int nn_unicode_upperCodepoint(unsigned int codepoint); -char *nn_unicode_upper(const char *s); +char *nn_unicode_upper(nn_Alloc *alloc, const char *s); unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint); -char *nn_unicode_lower(const char *s); +char *nn_unicode_lower(nn_Alloc *alloc, const char *s); diff --git a/src/universe.c b/src/universe.c index 439cd28..4e47ecc 100644 --- a/src/universe.c +++ b/src/universe.c @@ -2,9 +2,10 @@ #include "universe.h" #include -nn_universe *nn_newUniverse() { - nn_universe *u = nn_malloc(sizeof(nn_universe)); +nn_universe *nn_newUniverse(nn_Alloc alloc) { + nn_universe *u = nn_alloc(&alloc, sizeof(nn_universe)); if(u == NULL) return u; + u->alloc = alloc; // we leave udata uninitialized because it does not matter u->udataLen = 0; u->clockUserdata = NULL; @@ -12,11 +13,15 @@ nn_universe *nn_newUniverse() { return u; } +nn_Alloc *nn_getAllocator(nn_universe *universe) { + return &universe->alloc; +} + void nn_unsafeDeleteUniverse(nn_universe *universe) { for(size_t i = 0; i < universe->udataLen; i++) { - nn_free(universe->udata[i].name); + nn_deallocStr(&universe->alloc, universe->udata[i].name); } - nn_free(universe); + nn_dealloc(&universe->alloc, universe, sizeof(nn_universe)); } void *nn_queryUserdata(nn_universe *universe, const char *name) { @@ -32,7 +37,7 @@ void nn_storeUserdata(nn_universe *universe, const char *name, void *data) { if(universe->udataLen == NN_MAX_USERDATA) return; // prevent overflow size_t idx = universe->udataLen; - char *allocName = nn_strdup(name); + char *allocName = nn_strdup(&universe->alloc, name); if(allocName == NULL) return; universe->udata[idx].name = allocName; diff --git a/src/universe.h b/src/universe.h index 7e5aee4..fc49e32 100644 --- a/src/universe.h +++ b/src/universe.h @@ -9,6 +9,7 @@ typedef struct nn_universe_udata { } nn_universe_udata; typedef struct nn_universe { + nn_Alloc alloc; nn_universe_udata udata[NN_MAX_USERDATA]; size_t udataLen; nn_clock_t *currentClock; diff --git a/src/utils.c b/src/utils.c index 0482066..00f2484 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,5 @@ #include "neonucleus.h" +#include #include #include @@ -8,32 +9,71 @@ #include #endif -void *nn_malloc(size_t size) { - return malloc(size); +void *nn_alloc(nn_Alloc *alloc, size_t size) { + if(size == 0) return alloc->proc; + return alloc->proc(alloc->userdata, NULL, 0, size, NULL); } -void *nn_realloc(void *memory, size_t newSize) { - return realloc(memory, newSize); +void *nn_resize(nn_Alloc *alloc, void *memory, size_t oldSize, size_t newSize) { + if(oldSize == newSize) return memory; + if(newSize == 0) { + nn_dealloc(alloc, memory, oldSize); + return alloc->proc; + } + if(memory == NULL) { + return nn_alloc(alloc, newSize); + } + if(memory == alloc->proc) { + if(newSize == 0) return memory; + return nn_alloc(alloc, newSize); + } + return alloc->proc(alloc->userdata, memory, oldSize, newSize, NULL); } -void nn_free(void *memory) { - free(memory); +void nn_dealloc(nn_Alloc *alloc, void *memory, size_t size) { + if(memory == NULL) return; // matches free() + if(memory == alloc->proc) return; // 0-sized memory + alloc->proc(alloc->userdata, memory, size, 0, NULL); +} + +static void *nn_libcAllocProc(void *_, void *ptr, size_t oldSize, size_t newSize, void *__) { + if(newSize == 0) { + //printf("Freed %lu bytes from %p\n", oldSize, ptr); + free(ptr); + return NULL; + } else { + void *rptr = realloc(ptr, newSize); + //printf("Allocated %lu bytes for %p\n", newSize - oldSize, rptr); + return rptr; + } +} + +nn_Alloc nn_libcAllocator() { + return (nn_Alloc) { + .userdata = NULL, + .proc = nn_libcAllocProc, + }; } // Utilities, both internal and external -char *nn_strdup(const char *s) { +char *nn_strdup(nn_Alloc *alloc, const char *s) { size_t l = strlen(s); - char *m = nn_malloc(l+1); + char *m = nn_alloc(alloc, l+1); if(m == NULL) return m; return strcpy(m, s); } -void *nn_memdup(const void *buf, size_t len) { - char *m = malloc(len); +void *nn_memdup(nn_Alloc *alloc, const void *buf, size_t len) { + char *m = nn_alloc(alloc, len); if(m == NULL) return m; return memcpy(m, buf, len); } +void nn_deallocStr(nn_Alloc *alloc, char *s) { + if(s == NULL) return; + nn_dealloc(alloc, s, strlen(s)+1); +} + #ifdef NN_POSIX double nn_realTime() { @@ -71,3 +111,4 @@ void nn_randomLatency(double min, double max) { double latency = min + t * (max - min); nn_busySleep(latency); } + diff --git a/src/value.c b/src/value.c index 027c0cb..38264b1 100644 --- a/src/value.c +++ b/src/value.c @@ -21,38 +21,38 @@ nn_value nn_values_cstring(const char *string) { return (nn_value) {.tag = NN_VALUE_CSTR, .cstring = string}; } -nn_value nn_values_string(const char *string, size_t len) { - if(len == 0) len = strlen(string); - - char *buf = nn_malloc(len+1); +nn_value nn_values_string(nn_Alloc *alloc, const char *string, size_t len) { + char *buf = nn_alloc(alloc, len+1); if(buf == NULL) { return nn_values_nil(); } memcpy(buf, string, len); buf[len] = '\0'; - nn_string *s = nn_malloc(sizeof(nn_string)); + nn_string *s = nn_alloc(alloc, sizeof(nn_string)); if(s == NULL) { - nn_free(buf); + nn_dealloc(alloc, buf, len+1); return nn_values_nil(); } s->data = buf; s->len = len; s->refc = 1; + s->alloc = *alloc; return (nn_value) {.tag = NN_VALUE_STR, .string = s}; } -nn_value nn_values_array(size_t len) { - nn_array *arr = nn_malloc(sizeof(nn_array)); +nn_value nn_values_array(nn_Alloc *alloc, size_t len) { + nn_array *arr = nn_alloc(alloc, sizeof(nn_array)); if(arr == NULL) { return nn_values_nil(); } + arr->alloc = *alloc; arr->refc = 1; arr->len = len; - nn_value *values = nn_malloc(sizeof(nn_value) * len); + nn_value *values = nn_alloc(alloc, sizeof(nn_value) * len); if(values == NULL) { - nn_free(arr); + nn_dealloc(alloc, arr, sizeof(nn_array)); return nn_values_nil(); } for(size_t i = 0; i < len; i++) { @@ -62,16 +62,17 @@ nn_value nn_values_array(size_t len) { return (nn_value) {.tag = NN_VALUE_ARRAY, .array = arr}; } -nn_value nn_values_table(size_t pairCount) { - nn_table *table = nn_malloc(sizeof(nn_table)); +nn_value nn_values_table(nn_Alloc *alloc, size_t pairCount) { + nn_table *table = nn_alloc(alloc, sizeof(nn_table)); if(table == NULL) { return nn_values_nil(); } + table->alloc = *alloc; table->refc = 1; table->len = pairCount; - nn_pair *pairs = nn_malloc(sizeof(nn_pair) * pairCount); + nn_pair *pairs = nn_alloc(alloc, sizeof(nn_pair) * pairCount); if(pairs == NULL) { - nn_free(table); + nn_dealloc(alloc, table, sizeof(nn_table)); return nn_values_nil(); } for(size_t i = 0; i < pairCount; i++) { @@ -101,8 +102,9 @@ void nn_values_drop(nn_value val) { if(val.tag == NN_VALUE_STR) { val.string->refc--; if(val.string->refc == 0) { - nn_free(val.string->data); - nn_free(val.string); + nn_Alloc *a = &val.string->alloc; + nn_dealloc(a, val.string->data, val.string->len + 1); + nn_dealloc(a, val.string, sizeof(nn_string)); } } else if(val.tag == NN_VALUE_ARRAY) { val.array->refc--; @@ -110,8 +112,9 @@ void nn_values_drop(nn_value val) { for(size_t i = 0; i < val.array->len; i++) { nn_values_drop(val.array->values[i]); } - nn_free(val.array->values); - nn_free(val.array); + nn_Alloc *a = &val.array->alloc; + nn_dealloc(a, val.array->values, sizeof(nn_value) * val.array->len); + nn_dealloc(a, val.array, sizeof(nn_array)); } } else if(val.tag == NN_VALUE_TABLE) { val.table->refc--; @@ -120,8 +123,9 @@ void nn_values_drop(nn_value val) { nn_values_drop(val.table->pairs[i].key); nn_values_drop(val.table->pairs[i].val); } - nn_free(val.table->pairs); - nn_free(val.table); + nn_Alloc *a = &val.table->alloc; + nn_dealloc(a, val.table->pairs, sizeof(nn_pair) * val.table->len); + nn_dealloc(a, val.table, sizeof(nn_table)); } } }