@ai-ecoverse/slicc-kernel 1.122.3 → 1.123.0

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
@@ -6779,7 +6779,7 @@ function satisfies(version, range2) {
6779
6779
  }
6780
6780
 
6781
6781
  // src/version.ts
6782
- var KERNEL_VERSION = true ? "1.122.3" : "0.0.0-dev";
6782
+ var KERNEL_VERSION = true ? "1.123.0" : "0.0.0-dev";
6783
6783
  var OS_RELEASE = "6.0.0-slicc";
6784
6784
  function procVersion() {
6785
6785
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -12647,17 +12647,28 @@ var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
12647
12647
  var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
12648
12648
  var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime", "version"];
12649
12649
  var SYS_TREE = {
12650
- kernel: { osrelease: `${OS_RELEASE}
12651
- `, ostype: "Linux\n" }
12650
+ kernel: {
12651
+ osrelease: `${OS_RELEASE}
12652
+ `,
12653
+ ostype: "Linux\n",
12654
+ slicc_wasm_memories: (listing) => `${listing.wasm?.live ?? 0} ${listing.wasm?.ceiling ?? 0}
12655
+ `
12656
+ }
12652
12657
  };
12658
+ function isSysFile(at) {
12659
+ return typeof at === "string" || typeof at === "function";
12660
+ }
12653
12661
  function sysEntry(parts2) {
12654
12662
  let at = SYS_TREE;
12655
12663
  for (const part of parts2) {
12656
- if (typeof at !== "object" || !Object.hasOwn(at, part)) return void 0;
12664
+ if (isSysFile(at) || !Object.hasOwn(at, part)) return void 0;
12657
12665
  at = at[part];
12658
12666
  }
12659
12667
  return at;
12660
12668
  }
12669
+ function sysText(file, listing) {
12670
+ return typeof file === "string" ? file : file(listing());
12671
+ }
12661
12672
  function commOf(info) {
12662
12673
  const name2 = info.argv[0] ?? "";
12663
12674
  return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
@@ -12893,7 +12904,9 @@ var ProcTree = class {
12893
12904
  }
12894
12905
  if (top === "sys") {
12895
12906
  const entry = sysEntry(parts2.slice(1));
12896
- if (typeof entry === "string") return { kind: "file", content: () => entry };
12907
+ if (typeof entry === "string" || typeof entry === "function") {
12908
+ return { kind: "file", content: () => sysText(entry, () => this.listing()) };
12909
+ }
12897
12910
  return entry && { kind: "dir", names: () => Object.keys(entry) };
12898
12911
  }
12899
12912
  if (top === "self") {
@@ -19192,6 +19205,7 @@ var WasmProcess = class {
19192
19205
  var WASM_PROCESS_INIT = "wasm-process-init";
19193
19206
  var WASM_PROCESS_EXIT = "wasm-process-exit";
19194
19207
  var WASM_PROCESS_ERROR = "wasm-process-error";
19208
+ var WASM_PROCESS_READY = "wasm-process-ready";
19195
19209
  var WASM_THREAD_SPAWN = "wasm-thread-spawn";
19196
19210
  var WASM_THREAD_INIT = "wasm-thread-init";
19197
19211
  var WASM_THREAD_EXIT = "wasm-thread-exit";
@@ -19199,6 +19213,8 @@ var WASM_MAX_THREADS = 256;
19199
19213
 
19200
19214
  // src/kernel/host.ts
19201
19215
  var CRASHED = 70;
19216
+ var NO_MEMORY = 126;
19217
+ var WASM_OOM = /Cannot allocate Wasm memory|WebAssembly\.Memory\(\): could not allocate memory/;
19202
19218
  var KILL_GRACE_MS = 2e3;
19203
19219
  var KILL_HARD_MS = 5e3;
19204
19220
  var descIds = /* @__PURE__ */ new WeakMap();
@@ -19464,7 +19480,22 @@ function threadInit(opts, program, sab, cred, thread, main) {
19464
19480
  function settleExit(exit, settle, code) {
19465
19481
  void exit.catch(() => void 0).then(() => settle(code & 255));
19466
19482
  }
19483
+ function readiness(abi) {
19484
+ const ready2 = Promise.withResolvers();
19485
+ if (abi === "js") ready2.resolve(true);
19486
+ return ready2;
19487
+ }
19488
+ function outOfMemory(opts, data) {
19489
+ if (data?.type !== WASM_PROCESS_ERROR || !WASM_OOM.test(String(data.message))) return false;
19490
+ if (!opts.onOom?.()) {
19491
+ opts.onError?.(
19492
+ `${opts.argv0}: cannot allocate memory for a new process (too many processes at once)`
19493
+ );
19494
+ }
19495
+ return true;
19496
+ }
19467
19497
  function spawnWasmProcess(opts) {
19498
+ const { promise: ready2, resolve: started } = readiness(opts.program.abi);
19468
19499
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
19469
19500
  const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
19470
19501
  const blocked2 = opts.fork?.wasi?.blocked ?? opts.blocked;
@@ -19517,6 +19548,7 @@ function spawnWasmProcess(opts) {
19517
19548
  const finish = (code, sig) => {
19518
19549
  if (done4) return;
19519
19550
  done4 = true;
19551
+ started(true);
19520
19552
  clocks.freeze();
19521
19553
  dying.clear();
19522
19554
  endedBy = sig ?? process2.execTermsig;
@@ -19534,7 +19566,12 @@ function spawnWasmProcess(opts) {
19534
19566
  queueMicrotask(() => finish(...dying.status(code)));
19535
19567
  };
19536
19568
  const handle = (data) => {
19537
- if (data?.type === WASM_PROCESS_EXIT) {
19569
+ if (data?.type === WASM_PROCESS_READY) {
19570
+ started(true);
19571
+ } else if (outOfMemory(opts, data)) {
19572
+ started(false);
19573
+ finish(NO_MEMORY);
19574
+ } else if (data?.type === WASM_PROCESS_EXIT) {
19538
19575
  finish(...dying.status(data.code));
19539
19576
  } else if (data?.type === WASM_PROCESS_ERROR) {
19540
19577
  if (!dying.ending) opts.onError?.(String(data.message));
@@ -19608,6 +19645,7 @@ function spawnWasmProcess(opts) {
19608
19645
  return {
19609
19646
  pid: opts.pid,
19610
19647
  exited,
19648
+ ready: ready2,
19611
19649
  kill,
19612
19650
  signal,
19613
19651
  termsig: () => endedBy,
@@ -21202,6 +21240,63 @@ var SettlingChildren = class {
21202
21240
  }
21203
21241
  };
21204
21242
 
21243
+ // src/kernel/wasm-memories.ts
21244
+ var DEFAULT_CEILING = 112;
21245
+ var IDLE_MS = 1e4;
21246
+ var MARGIN = 16;
21247
+ var WasmMemories = class {
21248
+ live = 0;
21249
+ ceiling;
21250
+ waiters = /* @__PURE__ */ new Set();
21251
+ idleMs;
21252
+ constructor(ceiling, idleMs = IDLE_MS) {
21253
+ this.ceiling = ceiling;
21254
+ this.idleMs = idleMs;
21255
+ }
21256
+ count() {
21257
+ return { live: this.live, ceiling: this.ceiling ?? 0 };
21258
+ }
21259
+ ended() {
21260
+ this.live = Math.max(0, this.live - 1);
21261
+ this.progress();
21262
+ }
21263
+ learn() {
21264
+ this.ceiling = Math.max(1, this.live - 1);
21265
+ }
21266
+ near() {
21267
+ return this.ceiling !== void 0 && this.live + MARGIN >= this.ceiling;
21268
+ }
21269
+ async admit() {
21270
+ while (this.ceiling !== void 0 && this.live >= this.ceiling) {
21271
+ if (!await this.changed()) throw new SpawnError("EAGAIN");
21272
+ }
21273
+ this.live += 1;
21274
+ this.progress();
21275
+ }
21276
+ progress() {
21277
+ const waiters = [...this.waiters];
21278
+ this.waiters.clear();
21279
+ for (const wake of waiters) wake();
21280
+ }
21281
+ changed() {
21282
+ return new Promise((resolve2) => {
21283
+ const wake = () => {
21284
+ clearTimeout(timer);
21285
+ resolve2(true);
21286
+ };
21287
+ const timer = setTimeout(() => {
21288
+ this.waiters.delete(wake);
21289
+ resolve2(false);
21290
+ }, this.idleMs);
21291
+ this.waiters.add(wake);
21292
+ });
21293
+ }
21294
+ };
21295
+ function defaultCeiling() {
21296
+ const node = globalThis.process?.versions?.node;
21297
+ return node === void 0 ? DEFAULT_CEILING : void 0;
21298
+ }
21299
+
21205
21300
  // src/mount/driver.ts
21206
21301
  function ownerOf2(req) {
21207
21302
  const owner = {
@@ -23467,6 +23562,9 @@ function withScriptEnv(target, command) {
23467
23562
  ]
23468
23563
  };
23469
23564
  }
23565
+ function memoriesOf(given) {
23566
+ return new WasmMemories(given?.ceiling ?? defaultCeiling(), given?.idleMs);
23567
+ }
23470
23568
  function childHandle(handle) {
23471
23569
  return {
23472
23570
  pid: handle.pid,
@@ -23538,6 +23636,7 @@ var Launcher = class {
23538
23636
  jobs = new JobTable();
23539
23637
  locks;
23540
23638
  fifos = new FifoTable();
23639
+ memories;
23541
23640
  sems = new SemTable();
23542
23641
  settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
23543
23642
  ptys = new PtyTable(
@@ -23591,6 +23690,7 @@ var Launcher = class {
23591
23690
  terminals = 0;
23592
23691
  constructor(options) {
23593
23692
  this.usersMode = usersMode(options.users);
23693
+ this.memories = memoriesOf(options.wasmMemories);
23594
23694
  this.rootFs = options.fs;
23595
23695
  const peers = options.fs.peers?.();
23596
23696
  this.locks = kernelLocks(options.fs.rootName, peers);
@@ -24421,7 +24521,11 @@ var Launcher = class {
24421
24521
  }
24422
24522
  const done4 = this.heldUrl(program);
24423
24523
  try {
24424
- const handle = this.start({ ...req, cwd, program, argv0: target.argv0, args, env });
24524
+ const handle = await this.admitted(
24525
+ program.abi !== "js",
24526
+ req.fds,
24527
+ (fds, quietOom) => this.start({ ...req, fds, quietOom, cwd, program, argv0: target.argv0, args, env })
24528
+ );
24425
24529
  void handle.exited.finally(done4);
24426
24530
  return handle;
24427
24531
  } catch (err) {
@@ -24465,6 +24569,39 @@ var Launcher = class {
24465
24569
  if (req.tag !== void 0) this.tags.set(pid, req.tag);
24466
24570
  if (req.links !== void 0) this.links.set(pid, req.links);
24467
24571
  }
24572
+ async admitted(wasm, fds, start2) {
24573
+ if (!wasm) return start2(fds);
24574
+ for (; ; ) {
24575
+ await this.memories.admit().catch(async (err) => {
24576
+ await fds.closeAll();
24577
+ throw err;
24578
+ });
24579
+ const counted3 = (handle2) => {
24580
+ void handle2.exited.finally(() => this.memories.ended());
24581
+ return handle2;
24582
+ };
24583
+ if (!this.memories.near()) {
24584
+ try {
24585
+ return counted3(start2(fds));
24586
+ } catch (err) {
24587
+ this.memories.ended();
24588
+ throw err;
24589
+ }
24590
+ }
24591
+ const forked = fds.fork();
24592
+ const handle = await Promise.resolve().then(() => counted3(start2(forked, true))).catch(async (err) => {
24593
+ this.memories.ended();
24594
+ await forked.closeAll();
24595
+ throw err;
24596
+ });
24597
+ const fit = await (handle.ready ?? true);
24598
+ if (fit) {
24599
+ await fds.closeAll();
24600
+ return handle;
24601
+ }
24602
+ await handle.exited;
24603
+ }
24604
+ }
24468
24605
  start(req) {
24469
24606
  this.sampling();
24470
24607
  if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
@@ -24515,6 +24652,10 @@ var Launcher = class {
24515
24652
  ...this.prefixes.length > 0 && !stack.writer ? { readonlyAt: (path) => isProtected(this.prefixes, path) } : {},
24516
24653
  createWorker: this.createWorker,
24517
24654
  onError: req.report,
24655
+ onOom: () => {
24656
+ this.memories.learn();
24657
+ return req.quietOom === true;
24658
+ },
24518
24659
  spawner: this.spawner(pid, req.report),
24519
24660
  forker: this.forker(pid, req),
24520
24661
  kill: (target, sig, info) => this.kill(target, sig, this.credOf(pid), pid, info),
@@ -24523,7 +24664,8 @@ var Launcher = class {
24523
24664
  boot: this.boot,
24524
24665
  processes: this.list(this.credOf(pid)),
24525
24666
  load: this.loadAverage(),
24526
- cpu: this.cpuTotal()
24667
+ cpu: this.cpuTotal(),
24668
+ wasm: this.memories.count()
24527
24669
  }),
24528
24670
  sudo: (call, signal) => this.sudo(pid, call, signal),
24529
24671
  crontab: (call) => this.crontab(pid, call),
@@ -24860,9 +25002,10 @@ var Launcher = class {
24860
25002
  }
24861
25003
  forker(ppid, parent) {
24862
25004
  const { exec: _exec, pgid: _pgid, group: _group, pid: _pid, scrub: _scrub, ...image } = parent;
24863
- return async (state, fds) => childHandle(
24864
- this.start({
25005
+ return async (state, given) => {
25006
+ const fresh2 = (fds, quietOom) => this.start({
24865
25007
  ...image,
25008
+ quietOom,
24866
25009
  cwd: state.cwd ?? parent.cwd,
24867
25010
  fds,
24868
25011
  ppid,
@@ -24873,8 +25016,9 @@ var Launcher = class {
24873
25016
  cred: this.credOf(ppid),
24874
25017
  tag: this.tagOf(ppid),
24875
25018
  links: this.links.get(ppid)
24876
- })
24877
- );
25019
+ });
25020
+ return childHandle(await this.admitted(parent.program.abi !== "js", given, fresh2));
25021
+ };
24878
25022
  }
24879
25023
  keySignal(tty, fallback, sig, send) {
24880
25024
  const pgid = this.jobs.tcgetpgrp(tty, fallback);