call budgets match OC logic

This commit is contained in:
2026-05-08 03:40:02 +03:00
parent ac79e6af35
commit 51bc2ad8e6
3 changed files with 71 additions and 62 deletions

View File

@@ -948,7 +948,6 @@ typedef struct nn_Universe {
typedef struct nn_ComponentEntry {
const char *address;
nn_Component *comp;
double budgetUsed;
int slot;
} nn_ComponentEntry;
@@ -1080,8 +1079,8 @@ typedef struct nn_Computer {
void *archState;
nn_Architecture arch;
nn_Architecture desiredArch;
size_t callBudget;
size_t totalCallBudget;
double callBudget;
double totalCallBudget;
nn_HashMap components;
nn_DeviceInfoArray deviceInfo;
double totalEnergy;
@@ -1200,7 +1199,7 @@ nn_Computer *nn_createComputer(nn_Universe *universe, void *userdata, const char
c->desiredArch.name = NULL;
c->archState = NULL;
c->totalCallBudget = 10000;
c->totalCallBudget = 1;
c->callBudget = c->totalCallBudget;
if(nn_hashInit(&c->components, maxComponents, ctx, &nn_componentHasher)) {
@@ -2065,7 +2064,6 @@ nn_Exit nn_mountComponent(nn_Computer *c, nn_Component *comp, int slot, bool sil
.address = comp->address,
.comp = comp,
.slot = slot,
.budgetUsed = 0,
};
if(!nn_hashPut(&c->components, &ent)) return NN_ELIMIT;
nn_retainComponent(comp);
@@ -2165,6 +2163,9 @@ nn_Exit nn_invokeComponent(nn_Computer *computer, const char *compAddress, const
nn_pop(computer);
}
// TODO: configurable cost
nn_costComponent(computer, 22000);
nn_ComponentRequest req;
req.ctx = &c->universe->ctx;
req.computer = computer;
@@ -2486,17 +2487,20 @@ static void nn_dropValue(nn_Value val) {
}
}
// TODO: call
double nn_defaultCallBudgets[4] = { 0.5, 1, 1.5, 2 };
double nn_unlimitedCallBudget = 0;
size_t nn_defaultComponentLimits[4] = { 8, 12, 16, 20 };
size_t nn_creativeComponentLimit = 1024;
void nn_setCallBudget(nn_Computer *computer, size_t budget) {
void nn_setCallBudget(nn_Computer *computer, double budget) {
computer->totalCallBudget = budget;
}
size_t nn_getCallBudget(nn_Computer *computer) {
double nn_getCallBudget(nn_Computer *computer) {
return computer->totalCallBudget;
}
size_t nn_callBudgetRemaining(nn_Computer *computer) {
double nn_callBudgetRemaining(nn_Computer *computer) {
return computer->callBudget;
}
@@ -2505,30 +2509,24 @@ void nn_resetCallBudget(nn_Computer *computer) {
}
bool nn_componentsOverused(nn_Computer *computer) {
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
if(c->budgetUsed >= NN_COMPONENT_CALLBUDGET) return true;
}
if(computer->totalCallBudget == 0) return false;
return computer->callBudget == 0;
if(computer->totalCallBudget <= 0) return false;
return computer->callBudget <= 0;
}
void nn_resetComponentBudgets(nn_Computer *computer) {
for(nn_ComponentEntry *c = nn_hashIterate(&computer->components, NULL); c != NULL; c = nn_hashIterate(&computer->components, c)) {
c->budgetUsed = 0;
}
computer->callBudget = computer->totalCallBudget;
}
bool nn_costComponent(nn_Computer *computer, const char *address, double perTick) {
return nn_costComponentN(computer, address, 1, perTick);
bool nn_costComponent(nn_Computer *computer, double perTick) {
return nn_costComponentN(computer, 1, perTick);
}
bool nn_costComponentN(nn_Computer *computer, const char *address, double amount, double perTick) {
bool nn_costComponentN(nn_Computer *computer, double amount, double perTick) {
// this means 0 per tick means free
if(perTick == 0) return false;
nn_ComponentEntry *c = nn_getInternalComponent(computer, address);
if(c == NULL) return false;
c->budgetUsed += (NN_COMPONENT_CALLBUDGET * amount) / perTick;
return c->budgetUsed >= NN_COMPONENT_CALLBUDGET;
computer->callBudget -= amount / perTick;
if(computer->callBudget < 0) computer->callBudget = 0;
return computer->callBudget <= 0;
}
bool nn_checkstack(nn_Computer *computer, size_t amount) {
@@ -4556,7 +4554,7 @@ static nn_Exit nn_fsHandler(nn_ComponentRequest *req) {
e = state->handler(&freq);
if(e) return e;
req->returnCount = 1;
nn_costComponent(C, req->compAddress, state->fs.opensPerTick);
nn_costComponent(C, state->fs.opensPerTick);
return nn_pushinteger(C, freq.fd);
}
if(method == NN_FSNUM_READ) {
@@ -4581,7 +4579,7 @@ static nn_Exit nn_fsHandler(nn_ComponentRequest *req) {
nn_free(ctx, buf, state->fs.maxReadSize);
return NN_OK;
}
nn_costComponent(C, req->compAddress, state->fs.readsPerTick);
nn_costComponent(C, state->fs.readsPerTick);
nn_removeEnergy(C, state->fs.dataEnergyCost * freq.read.len);
req->returnCount = 1;
e = nn_pushlstring(C, buf, freq.read.len);
@@ -4597,7 +4595,7 @@ static nn_Exit nn_fsHandler(nn_ComponentRequest *req) {
e = state->handler(&freq);
if(e) return e;
req->returnCount = 1;
nn_costComponent(C, req->compAddress, state->fs.writesPerTick);
nn_costComponent(C, state->fs.writesPerTick);
nn_removeEnergy(C, state->fs.dataEnergyCost * freq.write.len);
return nn_pushbool(C, true);
}
@@ -4627,7 +4625,7 @@ static nn_Exit nn_fsHandler(nn_ComponentRequest *req) {
e = state->handler(&freq);
if(e) return e;
req->returnCount = 1;
nn_costComponent(C, req->compAddress, state->fs.readsPerTick);
nn_costComponent(C, state->fs.readsPerTick);
return nn_pushinteger(C, freq.seek.off);
}
if(method == NN_FSNUM_CLOSE) {
@@ -4961,7 +4959,7 @@ static nn_Exit nn_drvHandler(nn_ComponentRequest *request) {
curPos = dreq.curpos;
nn_drive_seekPenalty(C, curPos, sec, &state->drive);
nn_costComponent(C, request->compAddress, state->drive.readsPerTick);
nn_costComponent(C, state->drive.readsPerTick);
nn_removeEnergy(C, state->drive.dataEnergyCost * ss);
char *sector = nn_alloc(ctx, ss);
@@ -5170,7 +5168,7 @@ static nn_Exit nn_flashHandler(nn_ComponentRequest *request) {
nn_setError(C, "sector out of bounds");
return NN_EBADCALL;
}
nn_costComponent(C, request->compAddress, state->flash.readsPerTick);
nn_costComponent(C, state->flash.readsPerTick);
nn_removeEnergy(C, state->flash.dataEnergyCost * ss);
char *sector = nn_alloc(ctx, ss);
@@ -5205,7 +5203,7 @@ static nn_Exit nn_flashHandler(nn_ComponentRequest *request) {
return NN_EBADCALL;
}
nn_costComponent(C, request->compAddress, state->flash.writesPerTick);
nn_costComponent(C, state->flash.writesPerTick);
nn_removeEnergy(C, state->flash.dataEnergyCost * ss);
size_t len;
@@ -5650,7 +5648,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
}
// setBackground
if(m == NN_GPUNUM_SETBG) {
if(isScreen) nn_costComponent(C, req->compAddress, cls->gpu.setBackgroundPerTick);
if(isScreen) nn_costComponent(C, cls->gpu.setBackgroundPerTick);
if(nn_checknumber(C, 0,
"bad argument #1 (number expected)"))
return NN_EBADCALL;
@@ -5685,7 +5683,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
}
// setForeground
if(m == NN_GPUNUM_SETFG) {
if(isScreen) nn_costComponent(C, req->compAddress, cls->gpu.setForegroundPerTick);
if(isScreen) nn_costComponent(C, cls->gpu.setForegroundPerTick);
if(nn_checknumber(C, 0,
"bad argument #1 (number expected)"))
return NN_EBADCALL;
@@ -5907,7 +5905,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
if(e) return e;
req->returnCount = 1;
if(isScreen) {
nn_costComponent(C, req->compAddress, cls->gpu.setPerTick);
nn_costComponent(C, cls->gpu.setPerTick);
nn_removeEnergy(C, cls->gpu.energyPerWrite * g.set.len);
}
return nn_pushbool(C, true);
@@ -5935,7 +5933,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
if(e) return e;
req->returnCount = 1;
if(isScreen) {
nn_costComponent(C, req->compAddress, cls->gpu.copyPerTick);
nn_costComponent(C, cls->gpu.copyPerTick);
nn_removeEnergy(C, cls->gpu.energyPerWrite * g.copy.w * g.copy.h);
}
return nn_pushbool(C, true);
@@ -5966,7 +5964,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
if(e) return e;
req->returnCount = 1;
if(isScreen) {
nn_costComponent(C, req->compAddress, cls->gpu.fillPerTick);
nn_costComponent(C, cls->gpu.fillPerTick);
nn_removeEnergy(C, (g.fill.codepoint == ' ' ? cls->gpu.energyPerClear : cls->gpu.energyPerWrite) * g.fill.w * g.fill.h);
}
return nn_pushbool(C, true);
@@ -6082,7 +6080,7 @@ static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
if(g.bitblt.h > g.gpu->maxHeight) g.bitblt.h = g.gpu->maxHeight;
if(g.bitblt.dst == 0 || g.bitblt.src == 0) {
// taxed as a copy
nn_costComponent(C, req->compAddress, g.gpu->copyPerTick);
nn_costComponent(C, g.gpu->copyPerTick);
nn_removeEnergy(C, g.gpu->energyPerWrite * g.bitblt.w * g.bitblt.h);
}
e = cls->handler(&g);
@@ -6508,7 +6506,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
// TODO: the cool methods
if(method == NN_DATANUM_ENCODE64) {
nn_costComponent(C, req->compAddress, dataCard.base64PerTick);
nn_costComponent(C, dataCard.base64PerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_ENCODE64;
dreq.data = nn_tolstring(C, 0, &dreq.datalen);
@@ -6520,7 +6518,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return NN_OK;
}
if(method == NN_DATANUM_DECODE64) {
nn_costComponent(C, req->compAddress, dataCard.base64PerTick);
nn_costComponent(C, dataCard.base64PerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_DECODE64;
dreq.data = nn_tolstring(C, 0, &dreq.datalen);
@@ -6532,7 +6530,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return NN_OK;
}
if(method == NN_DATANUM_DEFLATE) {
nn_costComponent(C, req->compAddress, dataCard.deflatingPerTick);
nn_costComponent(C, dataCard.deflatingPerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_DEFLATE;
dreq.data = nn_tolstring(C, 0, &dreq.datalen);
@@ -6544,7 +6542,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return NN_OK;
}
if(method == NN_DATANUM_INFLATE) {
nn_costComponent(C, req->compAddress, dataCard.deflatingPerTick);
nn_costComponent(C, dataCard.deflatingPerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_INFLATE;
dreq.data = nn_tolstring(C, 0, &dreq.datalen);
@@ -6556,7 +6554,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return NN_OK;
}
if(method == NN_DATANUM_CRC32) {
nn_costComponent(C, req->compAddress, dataCard.crc32PerTick);
nn_costComponent(C, dataCard.crc32PerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_CRC32;
dreq.crc32.data = nn_tolstring(C, 0, &dreq.crc32.datalen);
@@ -6568,7 +6566,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return nn_pushlstring(C, dreq.crc32.checksum, 4);
}
if(method == NN_DATANUM_MD5) {
nn_costComponent(C, req->compAddress, dataCard.md5PerTick);
nn_costComponent(C, dataCard.md5PerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_MD5;
dreq.md5.data = nn_tolstring(C, 0, &dreq.md5.datalen);
@@ -6580,7 +6578,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return nn_pushlstring(C, dreq.md5.checksum, 16);
}
if(method == NN_DATANUM_SHA256) {
nn_costComponent(C, req->compAddress, dataCard.sha256PerTick);
nn_costComponent(C, dataCard.sha256PerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
dreq.action = NN_DATA_SHA256;
dreq.sha256.data = nn_tolstring(C, 0, &dreq.sha256.datalen);
@@ -6592,7 +6590,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return nn_pushlstring(C, dreq.sha256.checksum, 32);
}
if(method == NN_DATANUM_RANDOM) {
nn_costComponent(C, req->compAddress, dataCard.randomPerTick);
nn_costComponent(C, dataCard.randomPerTick);
if(nn_checkinteger(C, 0, "bad argument #1 (integer expected)")) return NN_EBADCALL;
intptr_t n = nn_tointeger(C, 0);
if(n <= 0) {
@@ -6615,7 +6613,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return e;
}
if(method == NN_DATANUM_ENCRYPT) {
nn_costComponent(C, req->compAddress, dataCard.encryptPerTick);
nn_costComponent(C, dataCard.encryptPerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
if(nn_checkstring(C, 1, "bad argument #2 (string expected)")) return NN_EBADCALL;
if(nn_checkstring(C, 2, "bad argument #3 (string expected)")) return NN_EBADCALL;
@@ -6640,7 +6638,7 @@ static nn_Exit nn_dataHandler(nn_ComponentRequest *req) {
return NN_OK;
}
if(method == NN_DATANUM_DECRYPT) {
nn_costComponent(C, req->compAddress, dataCard.encryptPerTick);
nn_costComponent(C, dataCard.encryptPerTick);
if(nn_checkstring(C, 0, "bad argument #1 (string expected)")) return NN_EBADCALL;
if(nn_checkstring(C, 1, "bad argument #2 (string expected)")) return NN_EBADCALL;
if(nn_checkstring(C, 2, "bad argument #3 (string expected)")) return NN_EBADCALL;