@ai-ecoverse/slicc-kernel 1.54.3 → 1.54.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.js CHANGED
@@ -6586,12 +6586,14 @@ var AsyncOps = class {
6586
6586
  const at = this.ready.indexOf(id2);
6587
6587
  if (at >= 0) this.ready.splice(at, 1);
6588
6588
  }
6589
- async wait(timeoutMs, signal) {
6589
+ async wait(timeoutMs, blocking) {
6590
+ let signal;
6590
6591
  for (; ; ) {
6591
6592
  if (this.closed) return -1;
6592
6593
  const id2 = this.ready.shift();
6593
6594
  if (id2 !== void 0) return id2;
6594
6595
  if (timeoutMs !== void 0 && timeoutMs <= 0) return 0;
6596
+ signal ??= blocking();
6595
6597
  const woke = await this.sleep(timeoutMs, signal);
6596
6598
  if (!woke) return 0;
6597
6599
  }
@@ -6652,7 +6654,7 @@ async function hostSyscall(req, ctx) {
6652
6654
  if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
6653
6655
  return json3(ctx.ops.submit(req.req));
6654
6656
  case "async-wait":
6655
- return json3(await ctx.ops.wait(req.timeoutMs, ctx.blocking()));
6657
+ return json3(await ctx.ops.wait(req.timeoutMs, ctx.blocking));
6656
6658
  case "async-take":
6657
6659
  return ctx.ops.take(req.id);
6658
6660
  case "async-resolve":
@@ -9575,6 +9577,9 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
9575
9577
  "dl-closure",
9576
9578
  "dl-closure-free",
9577
9579
  "dl-reserve",
9580
+ "dl-load-reserve",
9581
+ "dl-lock",
9582
+ "dl-unlock",
9578
9583
  "fd-renumber",
9579
9584
  "fd-promote",
9580
9585
  "fd-open-tty",
@@ -9634,7 +9639,7 @@ var WasmProcess = class {
9634
9639
  stopped = 0;
9635
9640
  stops = 0;
9636
9641
  owed = false;
9637
- waits = 0;
9642
+ waiting = /* @__PURE__ */ new Set();
9638
9643
  resumed = Promise.resolve();
9639
9644
  wake;
9640
9645
  stateListeners = [];
@@ -9690,7 +9695,8 @@ var WasmProcess = class {
9690
9695
  return "terminate";
9691
9696
  }
9692
9697
  this.options.onPending?.(sig);
9693
- if (this.options.jobs?.keyboard && KEYBOARD.has(sig)) this.owed = true;
9698
+ if (this.options.jobs?.keyboard && KEYBOARD.has(sig) && this.waiting.size === 0)
9699
+ this.owed = true;
9694
9700
  const blocked = this.interrupt;
9695
9701
  this.interrupt = new AbortController();
9696
9702
  blocked.abort();
@@ -9735,10 +9741,15 @@ var WasmProcess = class {
9735
9741
  await this.resumed;
9736
9742
  if (this.dying) return DYING;
9737
9743
  const stops = this.stops;
9738
- const waits = this.waits;
9739
- const result = await this.dispatch(req, cancelled);
9744
+ const scope = new AbortController();
9745
+ const forward = () => scope.abort();
9746
+ if (cancelled?.aborted) scope.abort();
9747
+ cancelled?.addEventListener("abort", forward, { once: true });
9748
+ const result = await this.dispatch(req, scope.signal).finally(() => {
9749
+ cancelled?.removeEventListener("abort", forward);
9750
+ this.waiting.delete(scope.signal);
9751
+ });
9740
9752
  if (this.dying) return DYING;
9741
- if (!result.ok && result.errno === "EINTR" && this.waits !== waits) this.owed = false;
9742
9753
  const restart = !result.ok && result.errno === "EINTR" && this.stops !== stops;
9743
9754
  if (restart && !this.options.hasPending?.()) continue;
9744
9755
  await this.resumed;
@@ -9791,12 +9802,31 @@ var WasmProcess = class {
9791
9802
  refuseIfPending(restart) {
9792
9803
  if (restart && this.options.hasPending?.()) throw new KernelError("EINTR");
9793
9804
  }
9805
+ async procWait(req, cancelled) {
9806
+ const flags = {
9807
+ untraced: req.untraced,
9808
+ continued: req.continued,
9809
+ inGroup: this.waitGroup(req.pid)
9810
+ };
9811
+ if (this.owed && !req.nohang) {
9812
+ const now = await this.children.wait(req.pid, true, this.interrupt.signal, flags);
9813
+ if (now[0] !== 0) return now;
9814
+ }
9815
+ const signal = req.nohang ? this.interrupt.signal : this.blockingSignal(cancelled);
9816
+ const waited = await this.children.wait(req.pid, req.nohang, signal, flags);
9817
+ return waited;
9818
+ }
9794
9819
  blockingSignal(cancelled, owing = true) {
9795
- if (owing) this.waits++;
9796
- if (this.options.hasPending?.() || cancelled?.aborted || owing && this.owed) {
9820
+ if (owing && this.owed) {
9821
+ this.owed = false;
9797
9822
  throw new KernelError("EINTR");
9798
9823
  }
9799
- return cancelled ? AbortSignal.any([this.interrupt.signal, cancelled]) : this.interrupt.signal;
9824
+ if (this.options.hasPending?.() || cancelled.aborted) throw new KernelError("EINTR");
9825
+ if (owing) this.waiting.add(cancelled);
9826
+ return this.cancelSignal(cancelled);
9827
+ }
9828
+ cancelSignal(cancelled) {
9829
+ return AbortSignal.any([this.interrupt.signal, cancelled]);
9800
9830
  }
9801
9831
  async read(req, cancelled) {
9802
9832
  const file = this.fds.get(req.fd).file;
@@ -9820,7 +9850,7 @@ var WasmProcess = class {
9820
9850
  if (nonblock) return file.write(body, AbortSignal.abort());
9821
9851
  return file.write(
9822
9852
  body,
9823
- this.options.hasPending?.() ? AbortSignal.abort() : this.interrupt.signal
9853
+ this.options.hasPending?.() ? AbortSignal.abort() : this.cancelSignal(cancelled)
9824
9854
  );
9825
9855
  }
9826
9856
  async openVfs(req) {
@@ -9964,6 +9994,11 @@ var WasmProcess = class {
9964
9994
  return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
9965
9995
  case "fd-select": {
9966
9996
  const { read, write, timeoutMs } = req;
9997
+ if (this.owed && timeoutMs !== 0) {
9998
+ const ready2 = await selectFds(this.fds, read, write, 0, this.interrupt.signal);
9999
+ if (ready2.read.length + ready2.write.length > 0)
10000
+ return { ok: true, kind: "json", json: ready2 };
10001
+ }
9967
10002
  const signal = this.blockingSignal(cancelled, timeoutMs !== 0);
9968
10003
  const selected = await selectFds(this.fds, read, write, timeoutMs, signal);
9969
10004
  return { ok: true, kind: "json", json: selected };
@@ -10161,16 +10196,8 @@ var WasmProcess = class {
10161
10196
  case "proc-spawn":
10162
10197
  this.refuseIfPending(req.restart);
10163
10198
  return { ok: true, kind: "json", json: await this.spawn(req) };
10164
- case "proc-wait": {
10165
- const signal = req.nohang ? this.interrupt.signal : this.blockingSignal(cancelled);
10166
- const flags = {
10167
- untraced: req.untraced,
10168
- continued: req.continued,
10169
- inGroup: this.waitGroup(req.pid)
10170
- };
10171
- const waited = await this.children.wait(req.pid, req.nohang, signal, flags);
10172
- return { ok: true, kind: "json", json: waited };
10173
- }
10199
+ case "proc-wait":
10200
+ return { ok: true, kind: "json", json: await this.procWait(req, cancelled) };
10174
10201
  case "proc-identity":
10175
10202
  return { ok: true, kind: "json", json: await this.options.identity?.() ?? null };
10176
10203
  case "proc-exec": {
@@ -10202,7 +10229,7 @@ var WasmProcess = class {
10202
10229
  return { ok: true, kind: "json", json: this.options.mounts?.() ?? [] };
10203
10230
  case "mount":
10204
10231
  case "umount":
10205
- return this.mountSyscall(req);
10232
+ return this.mountSyscall(req, cancelled);
10206
10233
  case "proc-alarm":
10207
10234
  this.setAlarm(req.sig, req.firstMs ?? req.ms, req.repeat ? req.ms : 0, req.timer);
10208
10235
  return { ok: true, kind: "void" };
@@ -10223,6 +10250,18 @@ var WasmProcess = class {
10223
10250
  return { ok: true, kind: "void" };
10224
10251
  case "dl-reserve":
10225
10252
  return { ok: true, kind: "json", json: this.reserveSlots(req.floor, req.size) };
10253
+ case "dl-load-reserve":
10254
+ return {
10255
+ ok: true,
10256
+ kind: "json",
10257
+ json: { base: this.reserveSlots(req.floor, req.size), handle: this.closures.handle++ }
10258
+ };
10259
+ case "dl-lock":
10260
+ await this.lockDl(req.owner);
10261
+ return { ok: true, kind: "void" };
10262
+ case "dl-unlock":
10263
+ this.unlockDl(req.owner);
10264
+ return { ok: true, kind: "void" };
10226
10265
  case "sig-mask":
10227
10266
  this.caught = req.caught;
10228
10267
  this.ignored = req.ignored;
@@ -10237,14 +10276,14 @@ var WasmProcess = class {
10237
10276
  return { ok: true, kind: "bytes", bytes: this.children.captured(req.pid, req.slot) };
10238
10277
  }
10239
10278
  }
10240
- async mountSyscall(req) {
10279
+ async mountSyscall(req, cancelled) {
10241
10280
  const { mount, umount } = this.options;
10242
10281
  if (!mount || !umount) throw new KernelError("ENOSYS");
10243
10282
  try {
10244
10283
  if (req.op === "umount") await umount(req.target, req.flags);
10245
10284
  else {
10246
10285
  const { source, target, type, flags, data } = req;
10247
- const signal = this.blockingSignal();
10286
+ const signal = this.blockingSignal(cancelled);
10248
10287
  await Promise.race([mount({ source, target, type, flags, data }, signal), aborted(signal)]);
10249
10288
  }
10250
10289
  } catch (err) {
@@ -10259,7 +10298,12 @@ var WasmProcess = class {
10259
10298
  }
10260
10299
  alarm;
10261
10300
  dlLog = [];
10262
- closures = { next: 0, free: [], live: /* @__PURE__ */ new Set() };
10301
+ closures = {
10302
+ next: 0,
10303
+ handle: 1,
10304
+ free: [],
10305
+ live: /* @__PURE__ */ new Set()
10306
+ };
10263
10307
  allocateClosure(floor) {
10264
10308
  const index = this.closures.free.pop() ?? Math.max(floor, this.closures.next);
10265
10309
  this.closures.next = Math.max(this.closures.next, index + 1);
@@ -10272,6 +10316,47 @@ var WasmProcess = class {
10272
10316
  this.closures.free.push(index);
10273
10317
  this.dlLog.push({ kind: "closure-free", index });
10274
10318
  }
10319
+ dlLock = {
10320
+ owner: 0,
10321
+ depth: 0,
10322
+ waiters: /* @__PURE__ */ new Set()
10323
+ };
10324
+ async lockDl(owner) {
10325
+ while (this.dlLock.depth > 0 && this.dlLock.owner !== owner) {
10326
+ if (this.dying) throw new KernelError("EINTR");
10327
+ const interrupt = this.interrupt.signal;
10328
+ const gone = await new Promise((resolve) => {
10329
+ const waiter = {
10330
+ owner,
10331
+ wake: (ended) => {
10332
+ this.dlLock.waiters.delete(waiter);
10333
+ interrupt.removeEventListener("abort", recheck);
10334
+ resolve(ended);
10335
+ }
10336
+ };
10337
+ const recheck = () => waiter.wake(false);
10338
+ this.dlLock.waiters.add(waiter);
10339
+ interrupt.addEventListener("abort", recheck, { once: true });
10340
+ });
10341
+ if (gone) throw new KernelError("EINTR");
10342
+ }
10343
+ this.dlLock.owner = owner;
10344
+ this.dlLock.depth++;
10345
+ }
10346
+ threadEnded(tid) {
10347
+ for (const waiter of [...this.dlLock.waiters]) if (waiter.owner === tid) waiter.wake(true);
10348
+ if (this.dlLock.depth === 0 || this.dlLock.owner !== tid) return;
10349
+ this.dlLock.depth = 0;
10350
+ this.wakeDl();
10351
+ }
10352
+ unlockDl(owner) {
10353
+ if (this.dlLock.depth === 0 || this.dlLock.owner !== owner) throw new KernelError("EPERM");
10354
+ this.dlLock.depth--;
10355
+ if (this.dlLock.depth === 0) this.wakeDl();
10356
+ }
10357
+ wakeDl() {
10358
+ for (const waiter of [...this.dlLock.waiters]) waiter.wake(false);
10359
+ }
10275
10360
  reserveSlots(floor, size) {
10276
10361
  const base = Math.max(floor, this.closures.next);
10277
10362
  this.closures.next = base + size;
@@ -10583,6 +10668,7 @@ function spawnWasmProcess(opts) {
10583
10668
  const endThread = (tid) => {
10584
10669
  const end = threads.get(tid);
10585
10670
  threads.delete(tid);
10671
+ process2.threadEnded(tid);
10586
10672
  end?.();
10587
10673
  };
10588
10674
  const spawnThread = (thread) => {