@ai-ecoverse/slicc-kernel 1.122.2 → 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
@@ -5171,6 +5171,7 @@ var OpfsFs = class {
5171
5171
  if (await this.handleExists(dir, name2)) throw fsError("EEXIST", path);
5172
5172
  const freshMeta = this.meta.fresh ? await this.meta.fresh([path]) : await this.meta.get([path]);
5173
5173
  if (freshMeta[0]?.link !== void 0) throw fsError("EEXIST", path);
5174
+ if (freshMeta[0] !== void 0) await this.meta.remove([path]);
5174
5175
  this.forget(physical);
5175
5176
  this.refuse(physical);
5176
5177
  await dir.getDirectoryHandle(name2, { create: true });
@@ -5190,7 +5191,8 @@ var OpfsFs = class {
5190
5191
  await this.locked(physical, async () => {
5191
5192
  if (await this.handleExists(dir, name2)) throw fsError("EEXIST", path);
5192
5193
  const freshMeta = this.meta.fresh ? await this.meta.fresh([path]) : await this.meta.get([path]);
5193
- if (freshMeta[0] !== void 0) throw fsError("EEXIST", path);
5194
+ if (freshMeta[0]?.link !== void 0) throw fsError("EEXIST", path);
5195
+ if (freshMeta[0] !== void 0) await this.meta.remove([path]);
5194
5196
  this.forget(physical);
5195
5197
  this.refuse(physical);
5196
5198
  await dir.getFileHandle(name2, { create: true });
@@ -6777,7 +6779,7 @@ function satisfies(version, range2) {
6777
6779
  }
6778
6780
 
6779
6781
  // src/version.ts
6780
- var KERNEL_VERSION = true ? "1.122.2" : "0.0.0-dev";
6782
+ var KERNEL_VERSION = true ? "1.123.0" : "0.0.0-dev";
6781
6783
  var OS_RELEASE = "6.0.0-slicc";
6782
6784
  function procVersion() {
6783
6785
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -12645,17 +12647,28 @@ var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
12645
12647
  var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
12646
12648
  var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime", "version"];
12647
12649
  var SYS_TREE = {
12648
- kernel: { osrelease: `${OS_RELEASE}
12649
- `, 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
+ }
12650
12657
  };
12658
+ function isSysFile(at) {
12659
+ return typeof at === "string" || typeof at === "function";
12660
+ }
12651
12661
  function sysEntry(parts2) {
12652
12662
  let at = SYS_TREE;
12653
12663
  for (const part of parts2) {
12654
- if (typeof at !== "object" || !Object.hasOwn(at, part)) return void 0;
12664
+ if (isSysFile(at) || !Object.hasOwn(at, part)) return void 0;
12655
12665
  at = at[part];
12656
12666
  }
12657
12667
  return at;
12658
12668
  }
12669
+ function sysText(file, listing) {
12670
+ return typeof file === "string" ? file : file(listing());
12671
+ }
12659
12672
  function commOf(info) {
12660
12673
  const name2 = info.argv[0] ?? "";
12661
12674
  return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
@@ -12891,7 +12904,9 @@ var ProcTree = class {
12891
12904
  }
12892
12905
  if (top === "sys") {
12893
12906
  const entry = sysEntry(parts2.slice(1));
12894
- 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
+ }
12895
12910
  return entry && { kind: "dir", names: () => Object.keys(entry) };
12896
12911
  }
12897
12912
  if (top === "self") {
@@ -19190,6 +19205,7 @@ var WasmProcess = class {
19190
19205
  var WASM_PROCESS_INIT = "wasm-process-init";
19191
19206
  var WASM_PROCESS_EXIT = "wasm-process-exit";
19192
19207
  var WASM_PROCESS_ERROR = "wasm-process-error";
19208
+ var WASM_PROCESS_READY = "wasm-process-ready";
19193
19209
  var WASM_THREAD_SPAWN = "wasm-thread-spawn";
19194
19210
  var WASM_THREAD_INIT = "wasm-thread-init";
19195
19211
  var WASM_THREAD_EXIT = "wasm-thread-exit";
@@ -19197,6 +19213,8 @@ var WASM_MAX_THREADS = 256;
19197
19213
 
19198
19214
  // src/kernel/host.ts
19199
19215
  var CRASHED = 70;
19216
+ var NO_MEMORY = 126;
19217
+ var WASM_OOM = /Cannot allocate Wasm memory|WebAssembly\.Memory\(\): could not allocate memory/;
19200
19218
  var KILL_GRACE_MS = 2e3;
19201
19219
  var KILL_HARD_MS = 5e3;
19202
19220
  var descIds = /* @__PURE__ */ new WeakMap();
@@ -19462,7 +19480,22 @@ function threadInit(opts, program, sab, cred, thread, main) {
19462
19480
  function settleExit(exit, settle, code) {
19463
19481
  void exit.catch(() => void 0).then(() => settle(code & 255));
19464
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
+ }
19465
19497
  function spawnWasmProcess(opts) {
19498
+ const { promise: ready2, resolve: started } = readiness(opts.program.abi);
19466
19499
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
19467
19500
  const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
19468
19501
  const blocked2 = opts.fork?.wasi?.blocked ?? opts.blocked;
@@ -19515,6 +19548,7 @@ function spawnWasmProcess(opts) {
19515
19548
  const finish = (code, sig) => {
19516
19549
  if (done4) return;
19517
19550
  done4 = true;
19551
+ started(true);
19518
19552
  clocks.freeze();
19519
19553
  dying.clear();
19520
19554
  endedBy = sig ?? process2.execTermsig;
@@ -19532,7 +19566,12 @@ function spawnWasmProcess(opts) {
19532
19566
  queueMicrotask(() => finish(...dying.status(code)));
19533
19567
  };
19534
19568
  const handle = (data) => {
19535
- 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) {
19536
19575
  finish(...dying.status(data.code));
19537
19576
  } else if (data?.type === WASM_PROCESS_ERROR) {
19538
19577
  if (!dying.ending) opts.onError?.(String(data.message));
@@ -19606,6 +19645,7 @@ function spawnWasmProcess(opts) {
19606
19645
  return {
19607
19646
  pid: opts.pid,
19608
19647
  exited,
19648
+ ready: ready2,
19609
19649
  kill,
19610
19650
  signal,
19611
19651
  termsig: () => endedBy,
@@ -21200,6 +21240,63 @@ var SettlingChildren = class {
21200
21240
  }
21201
21241
  };
21202
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
+
21203
21300
  // src/mount/driver.ts
21204
21301
  function ownerOf2(req) {
21205
21302
  const owner = {
@@ -23465,6 +23562,9 @@ function withScriptEnv(target, command) {
23465
23562
  ]
23466
23563
  };
23467
23564
  }
23565
+ function memoriesOf(given) {
23566
+ return new WasmMemories(given?.ceiling ?? defaultCeiling(), given?.idleMs);
23567
+ }
23468
23568
  function childHandle(handle) {
23469
23569
  return {
23470
23570
  pid: handle.pid,
@@ -23536,6 +23636,7 @@ var Launcher = class {
23536
23636
  jobs = new JobTable();
23537
23637
  locks;
23538
23638
  fifos = new FifoTable();
23639
+ memories;
23539
23640
  sems = new SemTable();
23540
23641
  settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
23541
23642
  ptys = new PtyTable(
@@ -23589,6 +23690,7 @@ var Launcher = class {
23589
23690
  terminals = 0;
23590
23691
  constructor(options) {
23591
23692
  this.usersMode = usersMode(options.users);
23693
+ this.memories = memoriesOf(options.wasmMemories);
23592
23694
  this.rootFs = options.fs;
23593
23695
  const peers = options.fs.peers?.();
23594
23696
  this.locks = kernelLocks(options.fs.rootName, peers);
@@ -24419,7 +24521,11 @@ var Launcher = class {
24419
24521
  }
24420
24522
  const done4 = this.heldUrl(program);
24421
24523
  try {
24422
- 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
+ );
24423
24529
  void handle.exited.finally(done4);
24424
24530
  return handle;
24425
24531
  } catch (err) {
@@ -24463,6 +24569,39 @@ var Launcher = class {
24463
24569
  if (req.tag !== void 0) this.tags.set(pid, req.tag);
24464
24570
  if (req.links !== void 0) this.links.set(pid, req.links);
24465
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
+ }
24466
24605
  start(req) {
24467
24606
  this.sampling();
24468
24607
  if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
@@ -24513,6 +24652,10 @@ var Launcher = class {
24513
24652
  ...this.prefixes.length > 0 && !stack.writer ? { readonlyAt: (path) => isProtected(this.prefixes, path) } : {},
24514
24653
  createWorker: this.createWorker,
24515
24654
  onError: req.report,
24655
+ onOom: () => {
24656
+ this.memories.learn();
24657
+ return req.quietOom === true;
24658
+ },
24516
24659
  spawner: this.spawner(pid, req.report),
24517
24660
  forker: this.forker(pid, req),
24518
24661
  kill: (target, sig, info) => this.kill(target, sig, this.credOf(pid), pid, info),
@@ -24521,7 +24664,8 @@ var Launcher = class {
24521
24664
  boot: this.boot,
24522
24665
  processes: this.list(this.credOf(pid)),
24523
24666
  load: this.loadAverage(),
24524
- cpu: this.cpuTotal()
24667
+ cpu: this.cpuTotal(),
24668
+ wasm: this.memories.count()
24525
24669
  }),
24526
24670
  sudo: (call, signal) => this.sudo(pid, call, signal),
24527
24671
  crontab: (call) => this.crontab(pid, call),
@@ -24858,9 +25002,10 @@ var Launcher = class {
24858
25002
  }
24859
25003
  forker(ppid, parent) {
24860
25004
  const { exec: _exec, pgid: _pgid, group: _group, pid: _pid, scrub: _scrub, ...image } = parent;
24861
- return async (state, fds) => childHandle(
24862
- this.start({
25005
+ return async (state, given) => {
25006
+ const fresh2 = (fds, quietOom) => this.start({
24863
25007
  ...image,
25008
+ quietOom,
24864
25009
  cwd: state.cwd ?? parent.cwd,
24865
25010
  fds,
24866
25011
  ppid,
@@ -24871,8 +25016,9 @@ var Launcher = class {
24871
25016
  cred: this.credOf(ppid),
24872
25017
  tag: this.tagOf(ppid),
24873
25018
  links: this.links.get(ppid)
24874
- })
24875
- );
25019
+ });
25020
+ return childHandle(await this.admitted(parent.program.abi !== "js", given, fresh2));
25021
+ };
24876
25022
  }
24877
25023
  keySignal(tty, fallback, sig, send) {
24878
25024
  const pgid = this.jobs.tcgetpgrp(tty, fallback);