diff --git a/src/components/screen.c b/src/components/screen.c index 20c8350..82c9733 100644 --- a/src/components/screen.c +++ b/src/components/screen.c @@ -2,11 +2,12 @@ #include #include -nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) { +nn_screen *nn_newScreen(nn_Context *context, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors) { + nn_Alloc *alloc = &context->allocator; nn_screen *screen = nn_alloc(alloc, sizeof(nn_screen)); - screen->alloc = *alloc; + screen->ctx = *context; screen->buffer = nn_alloc(alloc, sizeof(nn_scrchr_t) * maxWidth * maxHeight); - screen->lock = nn_newGuard(alloc); + screen->lock = nn_newGuard(context); screen->refc = 1; screen->width = maxWidth; screen->height = maxHeight; @@ -36,19 +37,19 @@ void nn_retainScreen(nn_screen *screen) { void nn_destroyScreen(nn_screen *screen) { if(!nn_decRef(&screen->refc)) return; - nn_Alloc a = screen->alloc; - nn_deleteGuard(&a, screen->lock); + nn_Alloc a = screen->ctx.allocator; + nn_deleteGuard(&screen->ctx, 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) { - nn_lock(screen->lock); + nn_lock(&screen->ctx, screen->lock); } void nn_unlockScreen(nn_screen *screen) { - nn_unlock(screen->lock); + nn_unlock(&screen->ctx, screen->lock); } void nn_getResolution(nn_screen *screen, int *width, int *height) { @@ -88,7 +89,7 @@ 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; - char *kb = nn_strdup(&screen->alloc, address); + char *kb = nn_strdup(&screen->ctx.allocator, address); if(kb == NULL) return; screen->keyboards[screen->keyboardCount++] = kb; } @@ -97,7 +98,7 @@ 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_deallocStr(&screen->alloc, screen->keyboards[i]); + nn_deallocStr(&screen->ctx.allocator, screen->keyboards[i]); } else { screen->keyboards[j] = screen->keyboards[i]; j++; @@ -212,12 +213,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(&screen->alloc, nn_getKeyboardCount(screen)); + nn_value arr = nn_values_array(&screen->ctx.allocator, 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(&screen->alloc, nn_getKeyboard(screen, i), addrlen); + nn_value addr = nn_values_string(&screen->ctx.allocator, nn_getKeyboard(screen, i), addrlen); nn_values_set(arr, i, addr); } diff --git a/src/components/screen.h b/src/components/screen.h index da5adb1..bf5ae5e 100644 --- a/src/components/screen.h +++ b/src/components/screen.h @@ -4,7 +4,7 @@ #include "../neonucleus.h" typedef struct nn_screen { - nn_Alloc alloc; + nn_Context ctx; nn_scrchr_t *buffer; nn_guard *lock; nn_refc refc; diff --git a/src/computer.c b/src/computer.c index f80aabb..b8e68ee 100644 --- a/src/computer.c +++ b/src/computer.c @@ -5,23 +5,24 @@ #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_alloc(&universe->alloc, sizeof(nn_computer)); - c->components = nn_alloc(&universe->alloc, sizeof(nn_component) * componentLimit); + nn_Alloc *alloc = &universe->ctx.allocator; + nn_computer *c = nn_alloc(alloc, sizeof(nn_computer)); + c->components = nn_alloc(alloc, sizeof(nn_component) * componentLimit); if(c->components == NULL) { - nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); + nn_dealloc(alloc, c, sizeof(nn_computer)); return NULL; } - c->address = nn_strdup(&universe->alloc, address); + c->address = nn_strdup(alloc, address); if(c->address == NULL) { - nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit); - nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); + nn_dealloc(alloc, c->components, sizeof(nn_component) * componentLimit); + nn_dealloc(alloc, c, sizeof(nn_computer)); return NULL; } - c->lock = nn_newGuard(&universe->alloc); + c->lock = nn_newGuard(&universe->ctx); if(c->lock == NULL) { - nn_deallocStr(&universe->alloc, c->address); - nn_dealloc(&universe->alloc, c->components, sizeof(nn_component) * componentLimit); - nn_dealloc(&universe->alloc, c, sizeof(nn_computer)); + nn_deallocStr(alloc, c->address); + nn_dealloc(alloc, c->components, sizeof(nn_component) * componentLimit); + nn_dealloc(alloc, c, sizeof(nn_computer)); return NULL; } c->timeOffset = nn_getTime(universe); @@ -51,10 +52,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(&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)); + nn_deleteGuard(&universe->ctx, c->lock); + nn_deallocStr(alloc, c->address); + nn_dealloc(alloc, c->components, sizeof(nn_component) * componentLimit); + nn_dealloc(alloc, c, sizeof(nn_computer)); return NULL; } @@ -66,8 +67,8 @@ nn_universe *nn_getUniverse(nn_computer *computer) { } void nn_setTmpAddress(nn_computer *computer, nn_address tmp) { - nn_deallocStr(&computer->universe->alloc, computer->tmpAddress); - computer->tmpAddress = nn_strdup(&computer->universe->alloc, tmp); + nn_deallocStr(&computer->universe->ctx.allocator, computer->tmpAddress); + computer->tmpAddress = nn_strdup(&computer->universe->ctx.allocator, tmp); } nn_address nn_getComputerAddress(nn_computer *computer) { @@ -131,12 +132,12 @@ void nn_deleteComputer(nn_computer *computer) { while(computer->signalCount > 0) { nn_popSignal(computer); } - nn_Alloc *a = &computer->universe->alloc; + nn_Alloc *a = &computer->universe->ctx.allocator; for(size_t i = 0; i < computer->userCount; i++) { nn_deallocStr(a, computer->users[i]); } computer->arch->teardown(computer, computer->archState, computer->arch->userdata); - nn_deleteGuard(a, computer->lock); + nn_deleteGuard(&computer->universe->ctx, computer->lock); nn_deallocStr(a, computer->address); nn_deallocStr(a, computer->tmpAddress); nn_dealloc(a, computer->components, sizeof(nn_component) * computer->componentCap); @@ -185,7 +186,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(&computer->universe->alloc, name); + char *user = nn_strdup(&computer->universe->ctx.allocator, name); if(user == NULL) return "out of memory"; computer->users[computer->userCount] = user; computer->userCount++; @@ -197,7 +198,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_deallocStr(&computer->universe->alloc, user); + nn_deallocStr(&computer->universe->ctx.allocator, user); } else { computer->users[j] = user; j++; @@ -329,7 +330,7 @@ const char *nn_getError(nn_computer *computer) { void nn_clearError(nn_computer *computer) { if(computer->allocatedError) { - nn_deallocStr(&computer->universe->alloc, computer->err); + nn_deallocStr(&computer->universe->ctx.allocator, computer->err); } computer->err = NULL; computer->allocatedError = false; @@ -337,7 +338,7 @@ void nn_clearError(nn_computer *computer) { void nn_setError(nn_computer *computer, const char *err) { nn_clearError(computer); - char *copy = nn_strdup(&computer->universe->alloc, err); + char *copy = nn_strdup(&computer->universe->ctx.allocator, err); if(copy == NULL) { nn_setCError(computer, "out of memory"); return; @@ -367,7 +368,7 @@ nn_component *nn_newComponent(nn_computer *computer, nn_address address, int slo computer->componentLen++; } - c->address = nn_strdup(&computer->universe->alloc, address); + c->address = nn_strdup(&computer->universe->ctx.allocator, address); if(c->address == NULL) return NULL; c->table = table; c->slot = slot; @@ -389,7 +390,7 @@ void nn_removeComponent(nn_computer *computer, nn_address address) { } void nn_destroyComponent(nn_component *component) { - nn_deallocStr(&component->computer->universe->alloc, component->address); + nn_deallocStr(&component->computer->universe->ctx.allocator, component->address); if(component->table->destructor != NULL) { component->table->destructor(component->table->userdata, component, component->statePtr); } @@ -467,11 +468,11 @@ void nn_deserializeProgram(nn_computer *computer, const char *memory, size_t len } void nn_lockComputer(nn_computer *computer) { - nn_lock(computer->lock); + nn_lock(&computer->universe->ctx, computer->lock); } void nn_unlockComputer(nn_computer *computer) { - nn_unlock(computer->lock); + nn_unlock(&computer->universe->ctx, computer->lock); } void nn_return_nil(nn_computer *computer) { @@ -495,7 +496,7 @@ 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 val = nn_values_string(&computer->universe->alloc, str, len); + nn_value val = nn_values_string(&computer->universe->ctx.allocator, str, len); if(val.tag == NN_VALUE_NIL) { nn_setCError(computer, "out of memory"); } @@ -503,7 +504,7 @@ 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 val = nn_values_array(&computer->universe->alloc, len); + nn_value val = nn_values_array(&computer->universe->ctx.allocator, len); if(val.tag == NN_VALUE_NIL) { nn_setCError(computer, "out of memory"); } @@ -512,7 +513,7 @@ nn_value nn_return_array(nn_computer *computer, size_t len) { } nn_value nn_return_table(nn_computer *computer, size_t len) { - nn_value val = nn_values_table(&computer->universe->alloc, len); + nn_value val = nn_values_table(&computer->universe->ctx.allocator, len); if(val.tag == NN_VALUE_NIL) { nn_setCError(computer, "out of memory"); } diff --git a/src/emulator.c b/src/emulator.c index 777f34a..bd39460 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -579,8 +579,9 @@ typedef struct ne_pressedKey { int main() { printf("Setting up universe\n"); - nn_Alloc alloc = nn_libcAllocator(); - nn_universe *universe = nn_newUniverse(alloc); + nn_Context ctx = nn_libcContext(); + nn_Alloc alloc = ctx.allocator; + nn_universe *universe = nn_newUniverse(ctx); if(universe == NULL) { printf("Failed to create universe\n"); return 1; @@ -669,7 +670,7 @@ int main() { int maxWidth = 80, maxHeight = 32; - nn_screen *s = nn_newScreen(&alloc, maxWidth, maxHeight, 24, 16, 256); + nn_screen *s = nn_newScreen(&ctx, maxWidth, maxHeight, 24, 16, 256); nn_setDepth(s, 4); // looks cool nn_addKeyboard(s, "shitty keyboard"); nn_mountKeyboard(computer, "shitty keyboard", 2); diff --git a/src/lock.c b/src/lock.c index d748660..ea4b1d4 100644 --- a/src/lock.c +++ b/src/lock.c @@ -1,31 +1,73 @@ #include "neonucleus.h" +#include + +#ifndef NN_BAREMETAL #include "tinycthread.h" -typedef struct nn_guard { - mtx_t m; -} nn_guard; +static bool nni_libcLock(void *_, mtx_t *lock, int action, int flags) { + if(action == NN_LOCK_INIT) { + mtx_init(lock, mtx_recursive); + } else if(action == NN_LOCK_DEINIT) { + mtx_destroy(lock); + } else if(action == NN_LOCK_RETAIN) { + if(flags & NN_LOCK_IMMEDIATE) { + return mtx_trylock(lock) == thrd_success; + } + return mtx_lock(lock); + } else if(action == NN_LOCK_RELEASE) { + mtx_unlock(lock); + } + return true; +} -nn_guard *nn_newGuard(nn_Alloc *alloc) { - nn_guard *g = nn_alloc(alloc, sizeof(nn_guard)); +nn_LockManager nn_libcMutex() { + nn_LockManager mgr = {}; + mgr.lockSize = sizeof(mtx_t); + mgr.userdata = NULL; + mgr.proc = (nn_LockProc *)nni_libcLock; + return mgr; +} + +#endif + +static bool nni_noLock(void *_, void *__, int action, int flags) { + return true; +} + +nn_LockManager nn_noMutex() { + return (nn_LockManager) { + .userdata = NULL, + .lockSize = 0, + .proc = (nn_LockProc *)nni_noLock, + }; +} + +nn_guard *nn_newGuard(nn_Context *ctx) { + nn_guard *g = nn_alloc(&ctx->allocator, ctx->lockManager.lockSize); if(g == NULL) return NULL; - mtx_init(&g->m, mtx_recursive); + ctx->lockManager.proc(ctx->lockManager.userdata, g, NN_LOCK_INIT, NN_LOCK_DEFAULT); return g; } -void nn_lock(nn_guard *guard) { +void nn_lock(nn_Context *context, nn_guard *guard) { if(guard == NULL) return; - mtx_lock(&guard->m); + context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_RETAIN, NN_LOCK_DEFAULT); } -void nn_unlock(nn_guard *guard) { - if(guard == NULL) return; - mtx_unlock(&guard->m); +bool nn_tryLock(nn_Context *context, nn_guard *guard) { + if(guard == NULL) return true; + return context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_RETAIN, NN_LOCK_IMMEDIATE); } -void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard) { +void nn_unlock(nn_Context *context, nn_guard *guard) { if(guard == NULL) return; - mtx_destroy(&guard->m); - nn_dealloc(alloc, guard, sizeof(nn_guard)); + context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_RELEASE, NN_LOCK_DEFAULT); +} + +void nn_deleteGuard(nn_Context *context, nn_guard *guard) { + if(guard == NULL) return; + context->lockManager.proc(context->lockManager.userdata, guard, NN_LOCK_DEINIT, NN_LOCK_DEFAULT); + nn_dealloc(&context->allocator, guard, context->lockManager.lockSize); } void nn_addRef(nn_refc *refc, size_t count) { @@ -37,8 +79,7 @@ void nn_incRef(nn_refc *refc) { } bool nn_removeRef(nn_refc *refc, size_t count) { - (*refc) -= count; - return *refc == 0; + return ((*refc) -= count) == 0; } bool nn_decRef(nn_refc *refc) { diff --git a/src/neonucleus.h b/src/neonucleus.h index ddd2e2a..581d07d 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -105,12 +105,46 @@ typedef struct nn_Alloc { nn_AllocProc *proc; } nn_Alloc; +#define NN_LOCK_DEFAULT 0 +#define NN_LOCK_IMMEDIATE 1 + +#define NN_LOCK_INIT 0 +#define NN_LOCK_DEINIT 1 +#define NN_LOCK_RETAIN 2 +#define NN_LOCK_RELEASE 3 + +typedef bool nn_LockProc(void *userdata, void *lock, int action, int flags); + +typedef struct nn_LockManager { + void *userdata; + size_t lockSize; + nn_LockProc *proc; +} nn_LockManager; + +typedef double nn_ClockProc(void *userdata); + +typedef struct nn_Clock { + void *userdata; + nn_ClockProc *proc; +} nn_Clock; + +typedef struct nn_Context { + nn_Alloc allocator; + nn_LockManager lockManager; + nn_Clock clock; +} nn_Context; + // TODO: write a bunch of utils so this *can* work on baremetal. #ifndef NN_BAREMETAL nn_Alloc nn_libcAllocator(); +nn_Clock nn_libcRealTime(); +nn_LockManager nn_libcMutex(); +nn_Context nn_libcContext(); #endif +nn_LockManager nn_noMutex(); + // Values for architectures #define NN_VALUE_INT 0 @@ -171,10 +205,11 @@ 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_Alloc *alloc); -void nn_lock(nn_guard *guard); -void nn_unlock(nn_guard *guard); -void nn_deleteGuard(nn_Alloc *alloc, nn_guard *guard); +nn_guard *nn_newGuard(nn_Context *context); +void nn_lock(nn_Context *context, nn_guard *guard); +bool nn_tryLock(nn_Context *context, nn_guard *guard); +void nn_unlock(nn_Context *context, nn_guard *guard); +void nn_deleteGuard(nn_Context *context, nn_guard *guard); void nn_addRef(nn_refc *refc, size_t count); void nn_incRef(nn_refc *refc); @@ -201,17 +236,16 @@ unsigned int nn_unicode_lowerCodepoint(unsigned int codepoint); // returned string must be nn_deallocStr()'d char *nn_unicode_lower(nn_Alloc *alloc, const char *s); -double nn_realTime(); -double nn_realTimeClock(void *_); -typedef double nn_clock_t(void *_); -nn_universe *nn_newUniverse(nn_Alloc alloc); +nn_universe *nn_newUniverse(nn_Context context); +nn_Context *nn_getContext(nn_universe *universe); nn_Alloc *nn_getAllocator(nn_universe *universe); +nn_Clock *nn_getClock(nn_universe *universe); +nn_LockManager *nn_getLockManager(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); -void nn_setClock(nn_universe *universe, nn_clock_t *clock, void *userdata); double nn_getTime(nn_universe *universe); nn_computer *nn_newComputer(nn_universe *universe, nn_address address, nn_architecture *arch, void *userdata, size_t memoryLimit, size_t componentLimit); @@ -587,7 +621,7 @@ typedef struct nn_scrchr_t { bool isBgPalette; } nn_scrchr_t; -nn_screen *nn_newScreen(nn_Alloc *alloc, int maxWidth, int maxHeight, int maxDepth, int editableColors, int paletteColors); +nn_screen *nn_newScreen(nn_Context *context, 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/universe.c b/src/universe.c index 4e47ecc..e230741 100644 --- a/src/universe.c +++ b/src/universe.c @@ -2,26 +2,24 @@ #include "universe.h" #include -nn_universe *nn_newUniverse(nn_Alloc alloc) { - nn_universe *u = nn_alloc(&alloc, sizeof(nn_universe)); +nn_universe *nn_newUniverse(nn_Context ctx) { + nn_universe *u = nn_alloc(&ctx.allocator, sizeof(nn_universe)); if(u == NULL) return u; - u->alloc = alloc; + u->ctx = ctx; // we leave udata uninitialized because it does not matter u->udataLen = 0; - u->clockUserdata = NULL; - u->currentClock = nn_realTimeClock; return u; } nn_Alloc *nn_getAllocator(nn_universe *universe) { - return &universe->alloc; + return &universe->ctx.allocator; } void nn_unsafeDeleteUniverse(nn_universe *universe) { for(size_t i = 0; i < universe->udataLen; i++) { - nn_deallocStr(&universe->alloc, universe->udata[i].name); + nn_deallocStr(&universe->ctx.allocator, universe->udata[i].name); } - nn_dealloc(&universe->alloc, universe, sizeof(nn_universe)); + nn_dealloc(&universe->ctx.allocator, universe, sizeof(nn_universe)); } void *nn_queryUserdata(nn_universe *universe, const char *name) { @@ -37,7 +35,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(&universe->alloc, name); + char *allocName = nn_strdup(&universe->ctx.allocator, name); if(allocName == NULL) return; universe->udata[idx].name = allocName; @@ -46,7 +44,7 @@ void nn_storeUserdata(nn_universe *universe, const char *name, void *data) { } double nn_getTime(nn_universe *universe) { - return universe->currentClock(universe->clockUserdata); + return universe->ctx.clock.proc(universe->ctx.clock.userdata); } void nn_loadCoreComponentTables(nn_universe *universe) { diff --git a/src/universe.h b/src/universe.h index fc49e32..69fc569 100644 --- a/src/universe.h +++ b/src/universe.h @@ -9,11 +9,9 @@ typedef struct nn_universe_udata { } nn_universe_udata; typedef struct nn_universe { - nn_Alloc alloc; + nn_Context ctx; nn_universe_udata udata[NN_MAX_USERDATA]; size_t udataLen; - nn_clock_t *currentClock; - void *clockUserdata; } nn_universe; #endif diff --git a/src/utils.c b/src/utils.c index db621d9..0ce582e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -40,6 +40,8 @@ void nn_dealloc(nn_Alloc *alloc, void *memory, size_t size) { alloc->proc(alloc->userdata, memory, size, 0, NULL); } +#ifndef NN_BAREMETAL + 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); @@ -59,6 +61,15 @@ nn_Alloc nn_libcAllocator() { }; } +nn_Context nn_libcContext() { + return (nn_Context) { + .allocator = nn_libcAllocator(), + .clock = nn_libcRealTime(), + .lockManager = nn_libcMutex(), + }; +} +#endif + // Utilities, both internal and external char *nn_strdup(nn_Alloc *alloc, const char *s) { size_t l = strlen(s); @@ -78,17 +89,11 @@ void nn_deallocStr(nn_Alloc *alloc, char *s) { nn_dealloc(alloc, s, strlen(s)+1); } -#ifdef NN_BAREMETAL - -double nn_realTime() { - return 0; -} - -#else +#ifndef NN_BAREMETAL #ifdef NN_POSIX -double nn_realTime() { +static double nni_realTime() { struct timespec time; if(clock_gettime(CLOCK_MONOTONIC, &time) < 0) return 0; // oh no return time.tv_sec + ((double)time.tv_nsec) / 1e9; @@ -96,7 +101,7 @@ double nn_realTime() { #else -double nn_realTime() { +static double nni_realTime() { LARGE_INTEGER frequency = {0}; if(!QueryPerformanceFrequency(&frequency)) return 0; @@ -108,12 +113,19 @@ double nn_realTime() { #endif -#endif - -double nn_realTimeClock(void *_) { - return nn_realTime(); +static double nni_realTimeClock(void *_) { + return nni_realTime(); } +nn_Clock nn_libcRealTime() { + return (nn_Clock) { + .userdata = NULL, + .proc = nni_realTimeClock, + }; +} + +#endif + // TODO: use OKLAB the color space for more accurate results. typedef struct nn_rgbColor {