@ai-ecoverse/slicc-kernel 1.134.0 → 1.134.3
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/README.md +3 -3
- package/dist/kernel-worker.js +39 -32
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +9 -4
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +40 -32
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +9 -4
- package/dist/process-worker.js.map +3 -3
- package/dist/types/fs/opfs.d.ts +0 -1
- package/dist/types/kernel/wasm-memories.d.ts +1 -0
- package/dist/types/node.d.ts +4 -0
- package/dist/types/process/js/js-context.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1096,8 +1096,8 @@ The kernel writes `/etc/passwd` and `/etc/group` when it starts (see [Users](#us
|
|
|
1096
1096
|
### How many processes at once
|
|
1097
1097
|
|
|
1098
1098
|
In a browser every process worker of the page shares one renderer. V8 reserves about 8 GiB of address space for each 32-bit wasm memory, whatever its declared maximum, and its sandbox holds about 1 TiB. So a page runs about 125 wasm processes (or programs that own a wasm memory) at once, counting everything in the renderer (#970). Node has no such ceiling, and neither does Linux. The kernel keeps processes inside that ceiling:
|
|
1099
|
-
- **The ceiling:** 112 by default in a browser and none in Node. It's the kernel's count of live wasm processes, with the kernel's other wasm memories in the page left outside it. When an instantiation runs out of memory anyway, the kernel learns the real ceiling at that moment (the live count minus one), and that learned value wins over the default. A learned ceiling is never below 16, since an OOM at a low count means something outside it (another tab in the same renderer) filled the renderer. It's raised by 8 for each minute without another OOM, back to the default.
|
|
1100
|
-
- **Admission:** a spawn, fork, exec or `kernel.run` at the ceiling waits for another process to exit. It keeps waiting as long as processes exit or
|
|
1099
|
+
- **The ceiling:** 112 by default in a browser and none in Node (`createNodeKernel({ wasmMemories: { ceiling, idleMs } })` sets one in Node; `idleMs`, the quiet spell before `EAGAIN` below, 10 s by default, is there for tests). It's the kernel's count of live wasm processes, with the kernel's other wasm memories in the page left outside it. When an instantiation runs out of memory anyway, the kernel learns the real ceiling at that moment (the live count minus one), and that learned value wins over the default. A learned ceiling is never below 16, since an OOM at a low count means something outside it (another tab in the same renderer) filled the renderer. It's raised by 8 for each minute without another OOM, back to the default.
|
|
1100
|
+
- **Admission:** a spawn, fork, exec or `kernel.run` at the ceiling waits for another process to exit. It keeps waiting as long as processes exit, are admitted or finish starting (a process becoming ready counts, so a slow host that is still booting the processes ahead of it doesn't fail the spawn, #1196), and fails with `EAGAIN` only after 10 s with none of these. A long `make -j` or `xargs -P` therefore queues, and a pipeline that needs more live processes than the ceiling fails cleanly. bash's own retry on a fork's `EAGAIN` (`fork: retry: Resource temporarily unavailable`) handles the rest.
|
|
1101
1101
|
- **Close to the ceiling** (within 16 of it), the kernel waits for each new process to finish instantiating before the spawn returns. If it ran out of memory, the kernel starts it again, quietly, once there's room, so the caller sees no failure.
|
|
1102
1102
|
- **The rare residual case:** a process that fails to instantiate with nobody waiting on it, which happens only when something outside the count fills the renderer. It ends with status 126 and `<program>: cannot allocate memory for a new process (too many processes at once)` on its stderr, never a JS `RangeError`.
|
|
1103
1103
|
- **Below a learned ceiling,** a process that still runs out of memory is started again once another process exits, and the spawn fails with `EAGAIN` after 10 s with none.
|
|
@@ -1251,7 +1251,7 @@ The tools in `tools/cert-review/`:
|
|
|
1251
1251
|
- **FAIL:** a regression, or a failing test (by the counts, even without its rows) is **not certified**, and the group is red;
|
|
1252
1252
|
- **INCOMPLETE** blocks too: no result, a result from another bios than the pinned one, a missing shard, a shard that exited without a failing test, a refused candidate, 0 tests run, or no test passed;
|
|
1253
1253
|
- **not judged:** every failing test fails on `main`'s own pins too (`both`), so the canary is broken on `main`, not by this group. That passes with a note, as do `both` rows next to a pass. Either way, `pr notice` opens one issue, `downstream: bios canary failing on main (<bios sha>)`, or comments on the open one, and the next group that passes closes it. Flaky rows are advisory.
|
|
1254
|
-
-
|
|
1254
|
+
- **No downstream waiver.** A downstream FAIL or INCOMPLETE in the merge group is not certified; fix the regression or bios's side first (the coordinator-only `downstream-override` label was removed with the 2026-10-19 cert model). A pull request's own certification line ends `downstream: merge group`, since its downstream verdict comes in the group.
|
|
1255
1255
|
|
|
1256
1256
|
Not part of the run yet: the rest of bios's setup (the `rest` shard, the upgrade boot, the sudo rows under `enforce`). More shards plug in through the canary call's `shards`.
|
|
1257
1257
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -2378,14 +2378,14 @@ var OpfsFs = class {
|
|
|
2378
2378
|
const staged = resolvePath(parent.path, staging);
|
|
2379
2379
|
const place = async () => {
|
|
2380
2380
|
this.forget(destination);
|
|
2381
|
-
const
|
|
2381
|
+
const copies = /* @__PURE__ */ new Map();
|
|
2382
2382
|
const root = { ino: inodeOf(source.path), ...moving };
|
|
2383
2383
|
const owned4 = lock ? { lock } : {};
|
|
2384
2384
|
const first = copying ? await this.intend({ from: source.path, to: staged, root, ...owned4 }) : void 0;
|
|
2385
2385
|
const second = copying && swap ? await this.intend({ from: staged, to: destination, replace: true, root, ...owned4 }) : void 0;
|
|
2386
2386
|
const moved2 = await this.replacingTarget(
|
|
2387
2387
|
targetStat !== null,
|
|
2388
|
-
() => this.place(source.handle, dir, staging)
|
|
2388
|
+
() => this.place(source.handle, dir, staging, copies)
|
|
2389
2389
|
).catch(async (err) => {
|
|
2390
2390
|
if (first) await this.rollBack(staged, source.path, [first, second]);
|
|
2391
2391
|
throw err;
|
|
@@ -2399,15 +2399,13 @@ var OpfsFs = class {
|
|
|
2399
2399
|
await this.meta.update(source.path, () => left);
|
|
2400
2400
|
}
|
|
2401
2401
|
if (first) await this.meta.update(first, () => void 0);
|
|
2402
|
-
let copied = !moved2;
|
|
2403
2402
|
if (swap) {
|
|
2404
2403
|
const hidden = await dir.getDirectoryHandle(staging);
|
|
2405
|
-
const placed = await this.place(hidden, dir, name2);
|
|
2404
|
+
const placed = await this.place(hidden, dir, name2, copies);
|
|
2406
2405
|
if (!placed) await dir.removeEntry(staging, { recursive: true });
|
|
2407
|
-
copied ||= !placed;
|
|
2408
2406
|
}
|
|
2409
2407
|
if (second) await this.meta.update(second, () => void 0);
|
|
2410
|
-
|
|
2408
|
+
await this.restamp(destination, copies);
|
|
2411
2409
|
this.changed(source.path, destination);
|
|
2412
2410
|
this.touch(Date.now(), parentOf3(source.path), parent.path);
|
|
2413
2411
|
};
|
|
@@ -2570,15 +2568,21 @@ var OpfsFs = class {
|
|
|
2570
2568
|
let writable2;
|
|
2571
2569
|
let handle;
|
|
2572
2570
|
try {
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
await this.
|
|
2571
|
+
const kept = created4 ? this.files.get(destination) : void 0;
|
|
2572
|
+
if (kept) {
|
|
2573
|
+
if (options.owner?.fifo || options.owner?.socket) throw fsError("ENXIO", to);
|
|
2574
|
+
handle = kept;
|
|
2575
|
+
} else {
|
|
2576
|
+
const [made2, existed, at] = await this.fileFor(destination);
|
|
2577
|
+
handle = made2;
|
|
2578
|
+
target = at;
|
|
2579
|
+
if (!existed && !created4) {
|
|
2580
|
+
created4 = true;
|
|
2581
|
+
await this.stampNew(target, options.owner, false);
|
|
2582
|
+
}
|
|
2583
|
+
const [entry] = await this.meta.get([target]);
|
|
2584
|
+
if (entry?.fifo || entry?.socket) throw fsError("ENXIO", to);
|
|
2579
2585
|
}
|
|
2580
|
-
const [entry] = await this.meta.get([target]);
|
|
2581
|
-
if (entry?.fifo || entry?.socket) throw fsError("ENXIO", to);
|
|
2582
2586
|
this.wrote(handle);
|
|
2583
2587
|
writable2 = await handle.createWritable();
|
|
2584
2588
|
await writable2.write(file);
|
|
@@ -2618,22 +2622,17 @@ var OpfsFs = class {
|
|
|
2618
2622
|
const handle = await this.handle(path);
|
|
2619
2623
|
return handle.kind === "file" ? (await this.snapshot(handle)).lastModified : 0;
|
|
2620
2624
|
}
|
|
2621
|
-
async
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
if (
|
|
2627
|
-
|
|
2628
|
-
return timed2;
|
|
2629
|
-
}
|
|
2630
|
-
async restamp(path, timed2) {
|
|
2631
|
-
for (const rest2 of timed2) {
|
|
2632
|
-
const mtimeFor = await this.modified(path + rest2);
|
|
2625
|
+
async restamp(path, copies) {
|
|
2626
|
+
if (copies.size === 0) return;
|
|
2627
|
+
const copied = [...copies];
|
|
2628
|
+
const entries = await this.meta.get(copied.map(([rest2]) => path + rest2));
|
|
2629
|
+
for (const [i, [rest2, { before, made: made2 }]] of copied.entries()) {
|
|
2630
|
+
if (entries[i]?.mtimeFor !== before) continue;
|
|
2631
|
+
const mtimeFor = (await this.io(made2.getFile())).lastModified;
|
|
2633
2632
|
await this.meta.update(path + rest2, (entry) => entry && { ...entry, mtimeFor });
|
|
2634
2633
|
}
|
|
2635
2634
|
}
|
|
2636
|
-
async place(handle, dir, name2) {
|
|
2635
|
+
async place(handle, dir, name2, copies) {
|
|
2637
2636
|
const move = handle.move;
|
|
2638
2637
|
if (move) this.others++;
|
|
2639
2638
|
const moved2 = await move?.call(handle, dir, name2).then(
|
|
@@ -2643,7 +2642,7 @@ var OpfsFs = class {
|
|
|
2643
2642
|
if (moved2) return true;
|
|
2644
2643
|
const before = this.fileMoves;
|
|
2645
2644
|
try {
|
|
2646
|
-
await this.copy(handle, dir, name2);
|
|
2645
|
+
await this.copy(handle, dir, name2, copies);
|
|
2647
2646
|
} catch (err) {
|
|
2648
2647
|
if (handle.kind === "directory" && this.fileMoves === before) {
|
|
2649
2648
|
await this.io(dir.removeEntry(name2, { recursive: true }));
|
|
@@ -2653,7 +2652,7 @@ var OpfsFs = class {
|
|
|
2653
2652
|
return false;
|
|
2654
2653
|
}
|
|
2655
2654
|
fileMoves = 0;
|
|
2656
|
-
async copy(handle, dir, name2) {
|
|
2655
|
+
async copy(handle, dir, name2, copies, rest2 = "") {
|
|
2657
2656
|
if (handle.kind === "file" && movable(handle)) {
|
|
2658
2657
|
this.others++;
|
|
2659
2658
|
const moved2 = await handle.move?.(dir, name2).then(
|
|
@@ -2668,13 +2667,17 @@ var OpfsFs = class {
|
|
|
2668
2667
|
if (handle.kind === "file") {
|
|
2669
2668
|
const made2 = await this.io(dir.getFileHandle(name2, { create: true }));
|
|
2670
2669
|
const writable2 = await this.io(made2.createWritable());
|
|
2671
|
-
|
|
2670
|
+
const file = await this.io(handle.getFile());
|
|
2671
|
+
await writable2.write(file);
|
|
2672
2672
|
await writable2.close();
|
|
2673
|
+
copies?.set(rest2, { before: copies.get(rest2)?.before ?? file.lastModified, made: made2 });
|
|
2673
2674
|
return;
|
|
2674
2675
|
}
|
|
2675
2676
|
const target = await this.io(dir.getDirectoryHandle(name2, { create: true }));
|
|
2676
2677
|
this.others++;
|
|
2677
|
-
for await (const child of handle.values())
|
|
2678
|
+
for await (const child of handle.values()) {
|
|
2679
|
+
await this.copy(child, target, child.name, copies, `${rest2}/${child.name}`);
|
|
2680
|
+
}
|
|
2678
2681
|
}
|
|
2679
2682
|
async symlink(target, path, owner) {
|
|
2680
2683
|
const parent = await this.locate(parentOf3(path), true);
|
|
@@ -7095,7 +7098,7 @@ function satisfies(version, range2) {
|
|
|
7095
7098
|
}
|
|
7096
7099
|
|
|
7097
7100
|
// src/version.ts
|
|
7098
|
-
var KERNEL_VERSION = true ? "1.134.
|
|
7101
|
+
var KERNEL_VERSION = true ? "1.134.3" : "0.0.0-dev";
|
|
7099
7102
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7100
7103
|
function procVersion() {
|
|
7101
7104
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -24766,6 +24769,9 @@ var WasmMemories = class {
|
|
|
24766
24769
|
const source = this.learned ? "learned" : ceiling === void 0 ? "none" : "default";
|
|
24767
24770
|
return { live: this.live, ceiling: ceiling ?? 0, source };
|
|
24768
24771
|
}
|
|
24772
|
+
started() {
|
|
24773
|
+
this.progress();
|
|
24774
|
+
}
|
|
24769
24775
|
ended() {
|
|
24770
24776
|
this.live = Math.max(0, this.live - 1);
|
|
24771
24777
|
this.progress();
|
|
@@ -28082,6 +28088,7 @@ var Launcher = class {
|
|
|
28082
28088
|
});
|
|
28083
28089
|
const counted2 = (handle2) => {
|
|
28084
28090
|
void handle2.exited.finally(() => this.memories.ended());
|
|
28091
|
+
void Promise.resolve(handle2.ready).then(() => this.memories.started());
|
|
28085
28092
|
return handle2;
|
|
28086
28093
|
};
|
|
28087
28094
|
if (!this.memories.near()) {
|