@ai-ecoverse/slicc-kernel 1.8.12 → 1.9.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.
@@ -268,28 +268,28 @@ function createNodeOps(h) {
268
268
  blocks: Math.ceil(size / 4096) * 8
269
269
  };
270
270
  },
271
- setattr(node, attr) {
271
+ setattr(node, attr2) {
272
272
  if (node.live.orphan) {
273
- if (attr.mode !== void 0 && attr.mode !== null) {
274
- node.mode = node.mode & ~PERM_MASK | attr.mode & PERM_MASK;
273
+ if (attr2.mode !== void 0 && attr2.mode !== null) {
274
+ node.mode = node.mode & ~PERM_MASK | attr2.mode & PERM_MASK;
275
275
  }
276
- if (attr.size !== void 0 && attr.size !== null) truncate(node, attr.size);
276
+ if (attr2.size !== void 0 && attr2.size !== null) truncate(node, attr2.size);
277
277
  return;
278
278
  }
279
279
  const path = liveNodePath(node);
280
- if (attr.mode !== void 0 && attr.mode !== null) {
281
- const perm = attr.mode & PERM_MASK;
280
+ if (attr2.mode !== void 0 && attr2.mode !== null) {
281
+ const perm = attr2.mode & PERM_MASK;
282
282
  if (perm !== (node.mode & PERM_MASK)) {
283
283
  metadataCall(() => bridgeOf(node).chmod(path, perm));
284
284
  node.mode = node.mode & ~PERM_MASK | perm;
285
285
  }
286
286
  }
287
- if (attr.size !== void 0 && attr.size !== null && Fs.isFile(node.mode)) {
288
- truncate(node, attr.size);
287
+ if (attr2.size !== void 0 && attr2.size !== null && Fs.isFile(node.mode)) {
288
+ truncate(node, attr2.size);
289
289
  }
290
- const mtime = toMs(attr.mtime) ?? attr.timestamp;
290
+ const mtime = toMs(attr2.mtime) ?? attr2.timestamp;
291
291
  if (mtime !== void 0) {
292
- const atime = toMs(attr.atime) ?? mtime;
292
+ const atime = toMs(attr2.atime) ?? mtime;
293
293
  flushNode(node);
294
294
  metadataCall(() => bridgeOf(node).utimes(path, atime, mtime));
295
295
  }
@@ -2405,10 +2405,297 @@ var init_process_sockets = __esm({
2405
2405
  }
2406
2406
  });
2407
2407
 
2408
+ // src/process/procfs.ts
2409
+ function commOf(info) {
2410
+ const name = info.argv[0] ?? "";
2411
+ return name.slice(name.lastIndexOf("/") + 1).slice(0, 15);
2412
+ }
2413
+ function ttyNumber(tty) {
2414
+ const pts = tty && /^\/dev\/pts\/(\d+)$/.exec(tty);
2415
+ if (pts) return 136 << 8 | Number(pts[1]);
2416
+ const vt = tty && /^\/dev\/tty(\d+)$/.exec(tty);
2417
+ return vt ? 4 << 8 | Number(vt[1]) : 0;
2418
+ }
2419
+ function ticks(ms) {
2420
+ return Math.max(0, Math.floor(ms * HZ / 1e3));
2421
+ }
2422
+ function pidStat(info, boot) {
2423
+ const fields = [
2424
+ info.pid,
2425
+ `(${commOf(info)})`,
2426
+ info.state,
2427
+ info.ppid,
2428
+ info.pgid,
2429
+ info.sid,
2430
+ ttyNumber(info.tty),
2431
+ info.tty ? info.pgid : -1,
2432
+ 4194304,
2433
+ 0,
2434
+ 0,
2435
+ 0,
2436
+ 0,
2437
+ 0,
2438
+ 0,
2439
+ 0,
2440
+ 0,
2441
+ 20,
2442
+ 0,
2443
+ 1,
2444
+ 0,
2445
+ ticks(info.started - boot),
2446
+ 0,
2447
+ 0,
2448
+ "18446744073709551615",
2449
+ ...Array(12).fill(0),
2450
+ 17,
2451
+ 0,
2452
+ 0,
2453
+ 0,
2454
+ 0,
2455
+ 0,
2456
+ 0,
2457
+ ...Array(7).fill(0),
2458
+ 0
2459
+ ];
2460
+ return `${fields.join(" ")}
2461
+ `;
2462
+ }
2463
+ function pidStatus(info) {
2464
+ const state = info.state === "Z" ? "Z (zombie)" : "S (sleeping)";
2465
+ const ids = `${UID} ${UID} ${UID} ${UID}`;
2466
+ return [
2467
+ `Name: ${commOf(info)}`,
2468
+ "Umask: 0022",
2469
+ `State: ${state}`,
2470
+ `Tgid: ${info.pid}`,
2471
+ "Ngid: 0",
2472
+ `Pid: ${info.pid}`,
2473
+ `PPid: ${info.ppid}`,
2474
+ "TracerPid: 0",
2475
+ `Uid: ${ids}`,
2476
+ `Gid: ${ids}`,
2477
+ "FDSize: 64",
2478
+ "Groups: ",
2479
+ `NSpid: ${info.pid}`,
2480
+ `NSpgid: ${info.pgid}`,
2481
+ `NSsid: ${info.sid}`,
2482
+ "Threads: 1",
2483
+ "SigQ: 0/0",
2484
+ "SigPnd: 0000000000000000",
2485
+ "ShdPnd: 0000000000000000",
2486
+ "SigBlk: 0000000000000000",
2487
+ "SigIgn: 0000000000000000",
2488
+ "SigCgt: 0000000000000000",
2489
+ ""
2490
+ ].join("\n");
2491
+ }
2492
+ function pidFile(name, info, boot) {
2493
+ if (name === "cmdline") return info.state === "Z" ? "" : `${info.argv.join("\0")}\0`;
2494
+ if (name === "comm") return `${commOf(info)}
2495
+ `;
2496
+ if (name === "stat") return pidStat(info, boot);
2497
+ if (name === "statm") return "0 0 0 0 0 0 0\n";
2498
+ return pidStatus(info);
2499
+ }
2500
+ function memoryInfo(source) {
2501
+ const total = source.deviceMemory ? source.deviceMemory * KIB * KIB * KIB : FALLBACK_MEMORY;
2502
+ const free = Math.max(0, total - (source.usedHeap ?? 0));
2503
+ const kb = (bytes) => `${Math.floor(bytes / KIB)} kB`;
2504
+ return [
2505
+ ["MemTotal", kb(total)],
2506
+ ["MemFree", kb(free)],
2507
+ ["MemAvailable", kb(free)],
2508
+ ["Buffers", kb(0)],
2509
+ ["Cached", kb(0)],
2510
+ ["SwapCached", kb(0)],
2511
+ ["Shmem", kb(0)],
2512
+ ["SReclaimable", kb(0)],
2513
+ ["SwapTotal", kb(0)],
2514
+ ["SwapFree", kb(0)]
2515
+ ].map(([key, value2]) => `${`${key}:`.padEnd(16)}${value2.padStart(12)}`).concat("").join("\n");
2516
+ }
2517
+ function systemFile(name, listing, now, memory) {
2518
+ const up = Math.max(0, now - listing.boot) / 1e3;
2519
+ if (name === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
2520
+ `;
2521
+ if (name === "meminfo") return memoryInfo(memory);
2522
+ const live = listing.processes.filter((p) => p.state !== "Z");
2523
+ if (name === "loadavg") {
2524
+ const last = Math.max(0, ...listing.processes.map((p) => p.pid));
2525
+ return `0.00 0.00 0.00 1/${live.length} ${last}
2526
+ `;
2527
+ }
2528
+ const idle = ticks(now - listing.boot);
2529
+ return [
2530
+ `cpu 0 0 0 ${idle} 0 0 0 0 0 0`,
2531
+ `cpu0 0 0 0 ${idle} 0 0 0 0 0 0`,
2532
+ "intr 0",
2533
+ "ctxt 0",
2534
+ `btime ${Math.floor(listing.boot / 1e3)}`,
2535
+ `processes ${listing.processes.length}`,
2536
+ "procs_running 1",
2537
+ "procs_blocked 0",
2538
+ ""
2539
+ ].join("\n");
2540
+ }
2541
+ function memorySource(scope2 = globalThis) {
2542
+ const nav = scope2.navigator;
2543
+ const perf = scope2.performance;
2544
+ const deviceMemory = nav?.deviceMemory;
2545
+ const used = perf?.memory?.usedJSHeapSize;
2546
+ return {
2547
+ ...typeof deviceMemory === "number" && deviceMemory > 0 ? { deviceMemory } : {},
2548
+ ...typeof used === "number" ? { usedHeap: used } : {}
2549
+ };
2550
+ }
2551
+ function attr(node) {
2552
+ const now = /* @__PURE__ */ new Date();
2553
+ return {
2554
+ dev: 3,
2555
+ ino: node.id,
2556
+ mode: node.mode,
2557
+ nlink: 1,
2558
+ uid: UID,
2559
+ gid: UID,
2560
+ rdev: 0,
2561
+ size: 0,
2562
+ atime: now,
2563
+ mtime: now,
2564
+ ctime: now,
2565
+ blksize: 4096,
2566
+ blocks: 0
2567
+ };
2568
+ }
2569
+ function useProcfs(Fs, sys, pid, memory = memorySource()) {
2570
+ const { lookupPath, createNode, hashRemoveNode } = Fs;
2571
+ const procList = sys.procList?.bind(sys);
2572
+ if (!lookupPath || !createNode || !hashRemoveNode || !procList) return;
2573
+ let proc;
2574
+ let self;
2575
+ try {
2576
+ proc = lookupPath.call(Fs, "/proc", { follow: true }).node;
2577
+ self = lookupPath.call(Fs, "/proc/self", { follow: true }).node;
2578
+ } catch {
2579
+ return;
2580
+ }
2581
+ const error = (errno2 = ENOENT) => new Fs.ErrnoError(errno2);
2582
+ const fresh = (parent, name, mode) => {
2583
+ const node = createNode.call(Fs, parent, name, mode, 0);
2584
+ hashRemoveNode.call(Fs, node);
2585
+ node.node_ops = { getattr: attr, setattr: () => {
2586
+ } };
2587
+ node.stream_ops = {
2588
+ llseek: (stream, offset, whence) => {
2589
+ const at = (whence === 1 ? stream.position : 0) + offset;
2590
+ if (at < 0) throw error(EINVAL);
2591
+ return at;
2592
+ }
2593
+ };
2594
+ return node;
2595
+ };
2596
+ const file = (parent, name, content) => {
2597
+ const node = fresh(parent, name, FILE_MODE);
2598
+ node.stream_ops = {
2599
+ open: (stream) => {
2600
+ stream.sliccProc = new TextEncoder().encode(content());
2601
+ },
2602
+ read: (stream, buffer, offset, length, at) => {
2603
+ const data = stream.sliccProc ?? new Uint8Array(0);
2604
+ const chunk = data.subarray(at, at + length);
2605
+ buffer.set(chunk, offset);
2606
+ return chunk.length;
2607
+ },
2608
+ llseek: (stream, offset, whence) => {
2609
+ const end = stream.sliccProc?.length ?? 0;
2610
+ const at = (whence === 1 ? stream.position : whence === 2 ? end : 0) + offset;
2611
+ if (at < 0) throw error(EINVAL);
2612
+ return at;
2613
+ }
2614
+ };
2615
+ return node;
2616
+ };
2617
+ const find = (processes2, target, own) => processes2.find((p) => own ? p.tid === target : p.pid === target || p.tid === target);
2618
+ const infoOf = (target) => find(procList().processes, target, false);
2619
+ const pidContent = (target, name, own = false) => () => {
2620
+ const listing = procList();
2621
+ const info = find(listing.processes, target, own);
2622
+ if (!info) throw error(ESRCH);
2623
+ return pidFile(name, info, listing.boot);
2624
+ };
2625
+ const pidNames = (names) => [.../* @__PURE__ */ new Set([...names, ...PID_FILES])];
2626
+ const pidDir = (name, target) => {
2627
+ const dir = fresh(proc, name, DIR_MODE2);
2628
+ dir.node_ops.lookup = (parent, child) => {
2629
+ if (!PID_FILES.includes(child)) throw error();
2630
+ return file(parent, child, pidContent(target, child));
2631
+ };
2632
+ dir.node_ops.readdir = () => [".", "..", ...PID_FILES];
2633
+ return dir;
2634
+ };
2635
+ const procOps = proc.node_ops;
2636
+ const lookup = procOps.lookup?.bind(procOps);
2637
+ const readdir = procOps.readdir?.bind(procOps);
2638
+ proc.node_ops = {
2639
+ ...procOps,
2640
+ lookup: (parent, name) => {
2641
+ if (/^[1-9]\d*$/.test(name)) {
2642
+ if (!infoOf(Number(name))) throw error();
2643
+ return pidDir(name, Number(name));
2644
+ }
2645
+ if (SYSTEM_FILES.includes(name)) {
2646
+ return file(
2647
+ parent,
2648
+ name,
2649
+ () => systemFile(name, procList(), Date.now(), memory)
2650
+ );
2651
+ }
2652
+ if (!lookup) throw error();
2653
+ return lookup(parent, name);
2654
+ },
2655
+ readdir: (node) => {
2656
+ const names = new Set(readdir ? readdir(node) : [".", ".."]);
2657
+ for (const name of SYSTEM_FILES) names.add(name);
2658
+ for (const p of procList().processes) names.add(String(p.pid));
2659
+ return [...names];
2660
+ }
2661
+ };
2662
+ const selfOps = self.node_ops;
2663
+ const selfLookup = selfOps.lookup?.bind(selfOps);
2664
+ const selfReaddir = selfOps.readdir?.bind(selfOps);
2665
+ self.node_ops = {
2666
+ ...selfOps,
2667
+ lookup: (parent, name) => {
2668
+ if (PID_FILES.includes(name)) {
2669
+ return file(parent, name, pidContent(pid, name, true));
2670
+ }
2671
+ if (!selfLookup) throw error();
2672
+ return selfLookup(parent, name);
2673
+ },
2674
+ readdir: (node) => pidNames(selfReaddir ? selfReaddir(node) : [".", ".."])
2675
+ };
2676
+ }
2677
+ var HZ, DIR_MODE2, FILE_MODE, ENOENT, ESRCH, EINVAL, UID, KIB, FALLBACK_MEMORY, PID_FILES, SYSTEM_FILES;
2678
+ var init_procfs = __esm({
2679
+ "src/process/procfs.ts"() {
2680
+ "use strict";
2681
+ HZ = 100;
2682
+ DIR_MODE2 = 16749;
2683
+ FILE_MODE = 33060;
2684
+ ENOENT = 44;
2685
+ ESRCH = 71;
2686
+ EINVAL = 28;
2687
+ UID = 1e3;
2688
+ KIB = 1024;
2689
+ FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
2690
+ PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
2691
+ SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
2692
+ }
2693
+ });
2694
+
2408
2695
  // src/process/realm-user.ts
2409
2696
  function ownByRealmUser(Fs) {
2410
2697
  const { stat, fstat } = Fs;
2411
- const owned = (attr) => ({ ...attr, uid: REALM_UID, gid: REALM_GID });
2698
+ const owned = (attr2) => ({ ...attr2, uid: REALM_UID, gid: REALM_GID });
2412
2699
  if (typeof stat === "function") {
2413
2700
  Fs.stat = (path, dontFollow) => owned(stat.call(Fs, path, dontFollow));
2414
2701
  }
@@ -2519,6 +2806,9 @@ function kernelSys(transport) {
2519
2806
  ptyNumbers() {
2520
2807
  return json(call2({ op: "pty-list" }, "pty-list"));
2521
2808
  },
2809
+ procList() {
2810
+ return json(call2({ op: "proc-list" }, "proc-list"));
2811
+ },
2522
2812
  ptyNumber(fd) {
2523
2813
  return json(call2({ op: "pty-number", fd }, `pty-number ${fd}`));
2524
2814
  },
@@ -2680,6 +2970,7 @@ async function runWasmProcess(init, port, deps = {}) {
2680
2970
  streams.useControllingTerminal();
2681
2971
  useDevFd(running.FS);
2682
2972
  useMounts(running.FS);
2973
+ useProcfs(running.FS, sys, init.pid);
2683
2974
  ownByRealmUser(running.FS);
2684
2975
  const livePath = (s) => liveNodePath(s.node);
2685
2976
  running.sliccKernel = createProcessKernel({
@@ -2746,6 +3037,7 @@ var init_process_runtime = __esm({
2746
3037
  init_process_http();
2747
3038
  init_process_signals();
2748
3039
  init_process_sockets();
3040
+ init_procfs();
2749
3041
  init_realm_user();
2750
3042
  init_kernel_streams();
2751
3043
  O_RDONLY = 0;
@@ -4453,7 +4745,7 @@ function importsContext({
4453
4745
  const path = pathOf(fd);
4454
4746
  if (path === void 0) {
4455
4747
  const kind = e.type === "device" ? "device" : "stream";
4456
- return { kind, mode: kind === "device" ? 8630 : 4480, uid: UID, gid: UID, size: 0 };
4748
+ return { kind, mode: kind === "device" ? 8630 : 4480, uid: UID2, gid: UID2, size: 0 };
4457
4749
  }
4458
4750
  host.fds.flushPath(path);
4459
4751
  const s = fs.stat(path);
@@ -4461,8 +4753,8 @@ function importsContext({
4461
4753
  kind: s.isDirectory ? "dir" : "file",
4462
4754
  path,
4463
4755
  mode: s.mode ?? (s.isDirectory ? 16877 : 33188),
4464
- uid: UID,
4465
- gid: UID,
4756
+ uid: UID2,
4757
+ gid: UID2,
4466
4758
  size: s.size,
4467
4759
  ...s.ino !== void 0 ? { ino: s.ino } : {},
4468
4760
  ...s.mtimeMs !== void 0 ? { mtimeMs: s.mtimeMs } : {}
@@ -4580,13 +4872,13 @@ function processes(host, call2) {
4580
4872
  }
4581
4873
  };
4582
4874
  }
4583
- var UID, STDIO;
4875
+ var UID2, STDIO;
4584
4876
  var init_wasi_imports = __esm({
4585
4877
  "src/process/wasi/wasi-imports.ts"() {
4586
4878
  "use strict";
4587
4879
  init_wasi_abi();
4588
4880
  init_wasi_files();
4589
- UID = 1e3;
4881
+ UID2 = 1e3;
4590
4882
  STDIO = ["stdin", "stdout", "stderr"];
4591
4883
  }
4592
4884
  });