@ai-ecoverse/slicc-kernel 1.66.0 → 1.67.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/README.md +2 -2
- package/dist/driver-worker.js +7 -2
- package/dist/driver-worker.js.map +3 -3
- package/dist/driver.js +6 -1
- package/dist/driver.js.map +3 -3
- package/dist/index.js +8 -3
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +307 -59
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +7 -2
- package/dist/node-driver-worker.js.map +3 -3
- package/dist/node-process-worker.js +67 -20
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +308 -60
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +149 -102
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -1339,6 +1339,11 @@ function versionError(theirs) {
|
|
|
1339
1339
|
return `slicc-kernel client protocol ${named} is not supported: this side speaks ${PROTOCOL.join(".")}`;
|
|
1340
1340
|
}
|
|
1341
1341
|
|
|
1342
|
+
// src/bytes.ts
|
|
1343
|
+
function fresh(bytes, start2 = 0, end = bytes.length) {
|
|
1344
|
+
return new Uint8Array(bytes.subarray(start2, end));
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1342
1347
|
// src/fs/walk.ts
|
|
1343
1348
|
var MAX_LINKS2 = 40;
|
|
1344
1349
|
function parentOf4(path) {
|
|
@@ -3002,7 +3007,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
3002
3007
|
}
|
|
3003
3008
|
if (typeof data === "string") peer.postMessage({ net: "ws-message", nid, data });
|
|
3004
3009
|
else {
|
|
3005
|
-
const bytes = data
|
|
3010
|
+
const bytes = fresh(data);
|
|
3006
3011
|
peer.postMessage({ net: "ws-message", nid, data: bytes }, [bytes.buffer]);
|
|
3007
3012
|
}
|
|
3008
3013
|
flow.inflight += payloadSize(data);
|
|
@@ -3040,7 +3045,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
3040
3045
|
open.delete(nid);
|
|
3041
3046
|
peer.postMessage({ net: "end", nid });
|
|
3042
3047
|
} else {
|
|
3043
|
-
const bytes = next2.value
|
|
3048
|
+
const bytes = fresh(next2.value);
|
|
3044
3049
|
peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
|
|
3045
3050
|
}
|
|
3046
3051
|
} catch (e) {
|
|
@@ -3334,7 +3339,7 @@ var UserDb = class {
|
|
|
3334
3339
|
joined(name2, extra);
|
|
3335
3340
|
group.push({ name: name2, gid: uid, members: [] });
|
|
3336
3341
|
passwd.push(row);
|
|
3337
|
-
const
|
|
3342
|
+
const fresh2 = !await this.fs.exists(home);
|
|
3338
3343
|
await this.fs.mkdir(home, { recursive: true });
|
|
3339
3344
|
try {
|
|
3340
3345
|
await this.provision(row);
|
|
@@ -3342,7 +3347,7 @@ var UserDb = class {
|
|
|
3342
3347
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
3343
3348
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
3344
3349
|
} catch (err) {
|
|
3345
|
-
if (
|
|
3350
|
+
if (fresh2) await this.fs.rm(home, { recursive: true, force: true });
|
|
3346
3351
|
throw err;
|
|
3347
3352
|
}
|
|
3348
3353
|
remember();
|
|
@@ -3460,7 +3465,7 @@ async function fsCall(fs, method, args, owner, g) {
|
|
|
3460
3465
|
}
|
|
3461
3466
|
switch (method) {
|
|
3462
3467
|
case "readFile": {
|
|
3463
|
-
const bytes = (await fs.readFileBuffer(path(0)))
|
|
3468
|
+
const bytes = fresh(await fs.readFileBuffer(path(0)));
|
|
3464
3469
|
return { result: bytes, transfer: [bytes.buffer] };
|
|
3465
3470
|
}
|
|
3466
3471
|
case "writeFile":
|
|
@@ -7103,11 +7108,11 @@ var ChildTable = class {
|
|
|
7103
7108
|
return [...this.children.keys()];
|
|
7104
7109
|
}
|
|
7105
7110
|
captured(pid, slot2) {
|
|
7106
|
-
const
|
|
7107
|
-
const chunks =
|
|
7108
|
-
if (!
|
|
7109
|
-
|
|
7110
|
-
if (
|
|
7111
|
+
const slots2 = this.leftovers.get(pid);
|
|
7112
|
+
const chunks = slots2?.get(slot2);
|
|
7113
|
+
if (!slots2 || !chunks) return new Uint8Array(0);
|
|
7114
|
+
slots2.delete(slot2);
|
|
7115
|
+
if (slots2.size === 0) this.leftovers.delete(pid);
|
|
7111
7116
|
return concat3(chunks);
|
|
7112
7117
|
}
|
|
7113
7118
|
};
|
|
@@ -7294,9 +7299,9 @@ var HeldPaths = class extends Map {
|
|
|
7294
7299
|
return this.keptHandles.get(handle);
|
|
7295
7300
|
}
|
|
7296
7301
|
keep(path, file) {
|
|
7297
|
-
const
|
|
7298
|
-
for (const id2 of
|
|
7299
|
-
this.uses.set(file, Math.max(
|
|
7302
|
+
const fresh2 = this.handlesAt(path).filter((id2) => !this.keptHandles.has(id2));
|
|
7303
|
+
for (const id2 of fresh2) this.keptHandles.set(id2, file);
|
|
7304
|
+
this.uses.set(file, Math.max(fresh2.length, 1));
|
|
7300
7305
|
this.unlinked.set(path, file);
|
|
7301
7306
|
}
|
|
7302
7307
|
unkeep(path, file) {
|
|
@@ -7852,7 +7857,7 @@ var MountFs = class {
|
|
|
7852
7857
|
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
7853
7858
|
try {
|
|
7854
7859
|
for (let offset = 0; offset < bytes.length; offset += chunk2) {
|
|
7855
|
-
const part = bytes
|
|
7860
|
+
const part = fresh(bytes, offset, offset + chunk2);
|
|
7856
7861
|
await mount.conn.call({ op: "write", fh, offset, bytes: part }, [part.buffer]);
|
|
7857
7862
|
}
|
|
7858
7863
|
} finally {
|
|
@@ -7949,7 +7954,7 @@ var MountFs = class {
|
|
|
7949
7954
|
async writeRuns(mount, fh, offset, bytes, transfer) {
|
|
7950
7955
|
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
7951
7956
|
for (let at = 0; at < bytes.length; at += chunk2) {
|
|
7952
|
-
const part = handed(bytes, transfer, chunk2) ? bytes : bytes
|
|
7957
|
+
const part = handed(bytes, transfer, chunk2) ? bytes : fresh(bytes, at, at + chunk2);
|
|
7953
7958
|
await mount.conn.call({ op: "write", fh, offset: offset + at, bytes: part }, [part.buffer]);
|
|
7954
7959
|
}
|
|
7955
7960
|
}
|
|
@@ -8181,8 +8186,8 @@ var MountFs = class {
|
|
|
8181
8186
|
}
|
|
8182
8187
|
this.writable(mount, real);
|
|
8183
8188
|
const { uid, gid, mode } = change;
|
|
8184
|
-
const
|
|
8185
|
-
const set2 =
|
|
8189
|
+
const fresh2 = change.kind === "new" && { uid, gid, mode };
|
|
8190
|
+
const set2 = fresh2 ? await this.driverOwner(found, real, fresh2, false) : change;
|
|
8186
8191
|
this.table.forget(mount, real);
|
|
8187
8192
|
const attrs = Object.entries({ uid: set2.uid, gid: set2.gid, mode: set2.mode });
|
|
8188
8193
|
await mount.conn.call({
|
|
@@ -8579,7 +8584,9 @@ async function dispatchOne(entry, req) {
|
|
|
8579
8584
|
|
|
8580
8585
|
// src/realm/sync-sab-wire.ts
|
|
8581
8586
|
var SAB_HEADER_I32 = 16;
|
|
8582
|
-
var
|
|
8587
|
+
var SAB_CLOCK_OFFSET = SAB_HEADER_I32 * 4;
|
|
8588
|
+
var SAB_CLOCK_I64 = 3;
|
|
8589
|
+
var SAB_HEADER_BYTES = SAB_CLOCK_OFFSET + SAB_CLOCK_I64 * 8;
|
|
8583
8590
|
var SAB_I_STATE = 0;
|
|
8584
8591
|
var SAB_I_SEQ = 1;
|
|
8585
8592
|
var SAB_I_STATUS = 2;
|
|
@@ -8729,6 +8736,146 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
8729
8736
|
};
|
|
8730
8737
|
}
|
|
8731
8738
|
|
|
8739
|
+
// src/kernel/cpu-clock.ts
|
|
8740
|
+
var IDLE_OPS = /* @__PURE__ */ new Set([
|
|
8741
|
+
"fd-select",
|
|
8742
|
+
"proc-wait",
|
|
8743
|
+
"proc-exec",
|
|
8744
|
+
"sig-pause",
|
|
8745
|
+
"sock-accept",
|
|
8746
|
+
"sock-connect"
|
|
8747
|
+
]);
|
|
8748
|
+
var SYS_CAP_US = 2e4;
|
|
8749
|
+
var LOCAL = SAB_CLOCK_OFFSET;
|
|
8750
|
+
var IDLE = 1;
|
|
8751
|
+
function epochMicros() {
|
|
8752
|
+
return Math.floor((performance.timeOrigin + performance.now()) * 1e3);
|
|
8753
|
+
}
|
|
8754
|
+
function slots(sab) {
|
|
8755
|
+
return new BigInt64Array(sab, LOCAL, SAB_CLOCK_I64);
|
|
8756
|
+
}
|
|
8757
|
+
var rawWait = Atomics.wait.bind(Atomics);
|
|
8758
|
+
function localIdle(sab, now) {
|
|
8759
|
+
const state = Number(Atomics.load(slots(sab), IDLE));
|
|
8760
|
+
if (state >= 0) return { idle: state, waiting: false };
|
|
8761
|
+
return { idle: Math.max(0, now + state), waiting: true };
|
|
8762
|
+
}
|
|
8763
|
+
var CpuClock = class {
|
|
8764
|
+
start;
|
|
8765
|
+
sys = 0;
|
|
8766
|
+
idle = 0;
|
|
8767
|
+
since = 0;
|
|
8768
|
+
kind = "sys";
|
|
8769
|
+
stopped = false;
|
|
8770
|
+
last = { utime: 0, stime: 0 };
|
|
8771
|
+
sab;
|
|
8772
|
+
now;
|
|
8773
|
+
constructor(sab, now = epochMicros) {
|
|
8774
|
+
this.sab = sab;
|
|
8775
|
+
this.now = now;
|
|
8776
|
+
this.start = now();
|
|
8777
|
+
}
|
|
8778
|
+
enter(op) {
|
|
8779
|
+
this.since = this.now();
|
|
8780
|
+
this.kind = this.stopped || IDLE_OPS.has(op) ? "idle" : "sys";
|
|
8781
|
+
}
|
|
8782
|
+
leave() {
|
|
8783
|
+
if (this.since === 0) return;
|
|
8784
|
+
this.add((this.frozen ?? this.now()) - this.since);
|
|
8785
|
+
this.since = 0;
|
|
8786
|
+
}
|
|
8787
|
+
stop(stopped) {
|
|
8788
|
+
if (stopped === this.stopped) return;
|
|
8789
|
+
this.stopped = stopped;
|
|
8790
|
+
if (this.since === 0 || !stopped || this.frozen !== void 0) return;
|
|
8791
|
+
const now = this.now();
|
|
8792
|
+
this.add(now - this.since);
|
|
8793
|
+
this.since = now;
|
|
8794
|
+
this.kind = "idle";
|
|
8795
|
+
}
|
|
8796
|
+
frozen;
|
|
8797
|
+
freeze() {
|
|
8798
|
+
this.frozen ??= this.now();
|
|
8799
|
+
}
|
|
8800
|
+
running() {
|
|
8801
|
+
if (this.frozen !== void 0) return false;
|
|
8802
|
+
const now = this.now();
|
|
8803
|
+
const busy = this.since === 0 || this.kind === "sys" && now - this.since < SYS_CAP_US;
|
|
8804
|
+
return busy && !localIdle(this.sab, now).waiting;
|
|
8805
|
+
}
|
|
8806
|
+
times() {
|
|
8807
|
+
const now = this.frozen ?? this.now();
|
|
8808
|
+
const open = this.since === 0 ? 0 : Math.max(0, now - this.since);
|
|
8809
|
+
const busy = this.kind === "sys" ? Math.min(open, SYS_CAP_US) : 0;
|
|
8810
|
+
const sys = this.sys + busy;
|
|
8811
|
+
const idle = this.idle + (open - busy) + localIdle(this.sab, now).idle;
|
|
8812
|
+
const user = Math.max(0, now - this.start - sys - idle);
|
|
8813
|
+
this.last = {
|
|
8814
|
+
utime: Math.max(this.last.utime, Math.floor(user / 1e3)),
|
|
8815
|
+
stime: Math.max(this.last.stime, Math.floor(sys / 1e3))
|
|
8816
|
+
};
|
|
8817
|
+
return this.last;
|
|
8818
|
+
}
|
|
8819
|
+
add(micros) {
|
|
8820
|
+
const spent = Math.max(0, micros);
|
|
8821
|
+
const busy = this.kind === "sys" ? Math.min(spent, SYS_CAP_US) : 0;
|
|
8822
|
+
this.sys += busy;
|
|
8823
|
+
this.idle += spent - busy;
|
|
8824
|
+
}
|
|
8825
|
+
};
|
|
8826
|
+
var ProcessClocks = class {
|
|
8827
|
+
main;
|
|
8828
|
+
threads = /* @__PURE__ */ new Map();
|
|
8829
|
+
ended = { utime: 0, stime: 0 };
|
|
8830
|
+
enabled;
|
|
8831
|
+
constructor(sab, enabled = true, states) {
|
|
8832
|
+
this.main = new CpuClock(sab);
|
|
8833
|
+
this.enabled = enabled;
|
|
8834
|
+
states?.onState((state) => this.stop(state === "stopped"));
|
|
8835
|
+
}
|
|
8836
|
+
thread(tid, sab) {
|
|
8837
|
+
const clock = new CpuClock(sab);
|
|
8838
|
+
this.threads.set(tid, clock);
|
|
8839
|
+
return clock;
|
|
8840
|
+
}
|
|
8841
|
+
threadEnded(tid) {
|
|
8842
|
+
const spent = this.threads.get(tid)?.times();
|
|
8843
|
+
this.threads.delete(tid);
|
|
8844
|
+
if (!spent) return;
|
|
8845
|
+
this.ended.utime += spent.utime;
|
|
8846
|
+
this.ended.stime += spent.stime;
|
|
8847
|
+
}
|
|
8848
|
+
stop(stopped) {
|
|
8849
|
+
for (const c of this.all()) c.stop(stopped);
|
|
8850
|
+
}
|
|
8851
|
+
freeze() {
|
|
8852
|
+
for (const c of this.all()) c.freeze();
|
|
8853
|
+
}
|
|
8854
|
+
times() {
|
|
8855
|
+
if (!this.enabled) return void 0;
|
|
8856
|
+
const sum = { ...this.ended };
|
|
8857
|
+
for (const c of this.all()) {
|
|
8858
|
+
const t = c.times();
|
|
8859
|
+
sum.utime += t.utime;
|
|
8860
|
+
sum.stime += t.stime;
|
|
8861
|
+
}
|
|
8862
|
+
return sum;
|
|
8863
|
+
}
|
|
8864
|
+
running() {
|
|
8865
|
+
return this.enabled ? this.all().filter((c) => c.running()).length : 0;
|
|
8866
|
+
}
|
|
8867
|
+
timed(clock, dispatch2) {
|
|
8868
|
+
const c = clock ?? this.main;
|
|
8869
|
+
return (req) => {
|
|
8870
|
+
c.enter(req.op);
|
|
8871
|
+
return dispatch2(req).finally(() => c.leave());
|
|
8872
|
+
};
|
|
8873
|
+
}
|
|
8874
|
+
all() {
|
|
8875
|
+
return [this.main, ...this.threads.values()];
|
|
8876
|
+
}
|
|
8877
|
+
};
|
|
8878
|
+
|
|
8732
8879
|
// src/fs/pages.ts
|
|
8733
8880
|
var PAGE = 64 * 1024;
|
|
8734
8881
|
var READAHEAD = 1024 * 1024;
|
|
@@ -8785,9 +8932,9 @@ var Pages = class {
|
|
|
8785
8932
|
const page = (start2 + at) / PAGE;
|
|
8786
8933
|
if (this.pages.has(page)) continue;
|
|
8787
8934
|
const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
|
|
8788
|
-
const
|
|
8789
|
-
|
|
8790
|
-
this.pages.set(page,
|
|
8935
|
+
const fresh2 = this.take(part.length);
|
|
8936
|
+
fresh2.set(part);
|
|
8937
|
+
this.pages.set(page, fresh2);
|
|
8791
8938
|
}
|
|
8792
8939
|
}
|
|
8793
8940
|
read(at, length2) {
|
|
@@ -9013,8 +9160,8 @@ function pidStat(info, boot) {
|
|
|
9013
9160
|
0,
|
|
9014
9161
|
0,
|
|
9015
9162
|
0,
|
|
9016
|
-
0,
|
|
9017
|
-
0,
|
|
9163
|
+
ticks(info.utime ?? 0),
|
|
9164
|
+
ticks(info.stime ?? 0),
|
|
9018
9165
|
0,
|
|
9019
9166
|
0,
|
|
9020
9167
|
20,
|
|
@@ -9108,19 +9255,23 @@ function systemFile(name2, listing, now, memory) {
|
|
|
9108
9255
|
if (name2 === "meminfo") {
|
|
9109
9256
|
return memoryInfo(
|
|
9110
9257
|
memory,
|
|
9111
|
-
listing.processes.reduce((
|
|
9258
|
+
listing.processes.reduce((sum2, p) => sum2 + p.memory, 0)
|
|
9112
9259
|
);
|
|
9113
9260
|
}
|
|
9114
9261
|
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
9115
9262
|
if (name2 === "loadavg") {
|
|
9116
9263
|
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
9117
|
-
|
|
9264
|
+
const [one, five, fifteen] = (listing.load ?? [0, 0, 0]).map((n) => n.toFixed(2));
|
|
9265
|
+
return `${one} ${five} ${fifteen} 1/${live.length} ${last}
|
|
9118
9266
|
`;
|
|
9119
9267
|
}
|
|
9120
|
-
const
|
|
9268
|
+
const sum = (key) => listing.cpu?.[key] ?? listing.processes.reduce((n, p) => n + (p[key] ?? 0), 0);
|
|
9269
|
+
const user = ticks(sum("utime"));
|
|
9270
|
+
const system = ticks(sum("stime"));
|
|
9271
|
+
const idle = listing.cpu ? ticks(listing.cpu.idle) : Math.max(0, ticks(now - listing.boot) - user - system);
|
|
9121
9272
|
return [
|
|
9122
|
-
`cpu
|
|
9123
|
-
`cpu0
|
|
9273
|
+
`cpu ${user} 0 ${system} ${idle} 0 0 0 0 0 0`,
|
|
9274
|
+
`cpu0 ${user} 0 ${system} ${idle} 0 0 0 0 0 0`,
|
|
9124
9275
|
"intr 0",
|
|
9125
9276
|
"ctxt 0",
|
|
9126
9277
|
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
@@ -11565,10 +11716,10 @@ var WasmProcess = class {
|
|
|
11565
11716
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
11566
11717
|
} else if (req.create) {
|
|
11567
11718
|
await nodes.onEntry(path, async () => {
|
|
11568
|
-
const
|
|
11719
|
+
const fresh2 = this.options.owners && !await present2(this.options.fs, path, true);
|
|
11569
11720
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path)));
|
|
11570
11721
|
await this.fds.get(fd).file.stat?.();
|
|
11571
|
-
if (
|
|
11722
|
+
if (fresh2) await this.options.fs.chown?.(path, { ...this.newOwner(), kind: "new" });
|
|
11572
11723
|
});
|
|
11573
11724
|
} else {
|
|
11574
11725
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path)));
|
|
@@ -12259,6 +12410,9 @@ function killThread(thread, caught, sig) {
|
|
|
12259
12410
|
blocked.abort();
|
|
12260
12411
|
return true;
|
|
12261
12412
|
}
|
|
12413
|
+
function threadSignalsOf(sab) {
|
|
12414
|
+
return { header: new Int32Array(sab, 0, SAB_HEADER_I32), interrupt: new AbortController() };
|
|
12415
|
+
}
|
|
12262
12416
|
function threadCancel(thread) {
|
|
12263
12417
|
return Atomics.load(thread.header, SAB_I_SIGNALS) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
12264
12418
|
}
|
|
@@ -12384,6 +12538,22 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
12384
12538
|
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header3, SAB_I_SIGNALS) } : {}
|
|
12385
12539
|
};
|
|
12386
12540
|
}
|
|
12541
|
+
function threadInit(opts, program, sab, cred, thread) {
|
|
12542
|
+
return {
|
|
12543
|
+
type: WASM_THREAD_INIT,
|
|
12544
|
+
pid: opts.shownPid ?? opts.pid,
|
|
12545
|
+
program,
|
|
12546
|
+
argv0: opts.argv0,
|
|
12547
|
+
args: opts.args,
|
|
12548
|
+
env: opts.env,
|
|
12549
|
+
cwd: opts.cwd,
|
|
12550
|
+
sab,
|
|
12551
|
+
cred: copyCred(cred),
|
|
12552
|
+
owners: opts.owners === true,
|
|
12553
|
+
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
12554
|
+
thread
|
|
12555
|
+
};
|
|
12556
|
+
}
|
|
12387
12557
|
function spawnWasmProcess(opts) {
|
|
12388
12558
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
12389
12559
|
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
@@ -12416,7 +12586,10 @@ function spawnWasmProcess(opts) {
|
|
|
12416
12586
|
const worker = opts.createWorker();
|
|
12417
12587
|
const dying = new Dying();
|
|
12418
12588
|
const dispatch2 = (req) => dying.serving(() => isWasmSyscall(req) ? process.syscall(req) : dispatchSyncFs(req));
|
|
12419
|
-
const
|
|
12589
|
+
const clocks = new ProcessClocks(sab, opts.program.abi !== "js", process);
|
|
12590
|
+
const responder = attachSyncSabResponder(worker, sab, token, {
|
|
12591
|
+
dispatch: clocks.timed(void 0, dispatch2)
|
|
12592
|
+
});
|
|
12420
12593
|
const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
|
|
12421
12594
|
const { promise: exited, resolve: settle3 } = Promise.withResolvers();
|
|
12422
12595
|
let done4 = false;
|
|
@@ -12424,6 +12597,7 @@ function spawnWasmProcess(opts) {
|
|
|
12424
12597
|
const finish = (code, sig) => {
|
|
12425
12598
|
if (done4) return;
|
|
12426
12599
|
done4 = true;
|
|
12600
|
+
clocks.freeze();
|
|
12427
12601
|
dying.clear();
|
|
12428
12602
|
endedBy = sig ?? process.execTermsig;
|
|
12429
12603
|
worker.removeEventListener("message", onMessage);
|
|
@@ -12464,6 +12638,7 @@ function spawnWasmProcess(opts) {
|
|
|
12464
12638
|
const endThread = (tid) => {
|
|
12465
12639
|
const end = threads.get(tid);
|
|
12466
12640
|
threads.delete(tid);
|
|
12641
|
+
clocks.threadEnded(tid);
|
|
12467
12642
|
process.threadEnded(tid);
|
|
12468
12643
|
end?.();
|
|
12469
12644
|
};
|
|
@@ -12477,15 +12652,14 @@ function spawnWasmProcess(opts) {
|
|
|
12477
12652
|
}
|
|
12478
12653
|
const tsab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
12479
12654
|
const tw = opts.createWorker();
|
|
12480
|
-
const tsignals =
|
|
12481
|
-
header: new Int32Array(tsab, 0, SAB_HEADER_I32),
|
|
12482
|
-
interrupt: new AbortController()
|
|
12483
|
-
};
|
|
12655
|
+
const tsignals = threadSignalsOf(tsab);
|
|
12484
12656
|
threadSignals.set(thread.tid, tsignals);
|
|
12485
12657
|
const tdispatch = (req) => dying.serving(
|
|
12486
12658
|
() => isWasmSyscall(req) ? process.syscall(req, threadCancel(tsignals)) : dispatchSyncFs(req)
|
|
12487
12659
|
);
|
|
12488
|
-
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
12660
|
+
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
12661
|
+
dispatch: clocks.timed(clocks.thread(thread.tid, tsab), tdispatch)
|
|
12662
|
+
});
|
|
12489
12663
|
const onThreadMessage = (event) => {
|
|
12490
12664
|
const data = event.data;
|
|
12491
12665
|
if (data?.type === WASM_THREAD_EXIT) endThread(thread.tid);
|
|
@@ -12500,21 +12674,7 @@ function spawnWasmProcess(opts) {
|
|
|
12500
12674
|
tresponder.dispose();
|
|
12501
12675
|
tw.terminate();
|
|
12502
12676
|
});
|
|
12503
|
-
|
|
12504
|
-
type: WASM_THREAD_INIT,
|
|
12505
|
-
pid: opts.shownPid ?? opts.pid,
|
|
12506
|
-
program,
|
|
12507
|
-
argv0: opts.argv0,
|
|
12508
|
-
args: opts.args,
|
|
12509
|
-
env: opts.env,
|
|
12510
|
-
cwd: opts.cwd,
|
|
12511
|
-
sab: tsab,
|
|
12512
|
-
cred: copyCred(process.cred),
|
|
12513
|
-
owners: opts.owners === true,
|
|
12514
|
-
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
12515
|
-
thread
|
|
12516
|
-
};
|
|
12517
|
-
tw.postMessage(tinit);
|
|
12677
|
+
tw.postMessage(threadInit(opts, program, tsab, process.cred, thread));
|
|
12518
12678
|
};
|
|
12519
12679
|
worker.postMessage(
|
|
12520
12680
|
processInit(opts, sab, process.umask, copyCred(process.cred), lane?.lane),
|
|
@@ -12539,7 +12699,9 @@ function spawnWasmProcess(opts) {
|
|
|
12539
12699
|
signalMasks: () => process.signalMasks(),
|
|
12540
12700
|
umask: () => process.umask,
|
|
12541
12701
|
cred: () => copyCred(process.cred),
|
|
12542
|
-
writesBack: () => opts.program.abi === "wasi" && !done4
|
|
12702
|
+
writesBack: () => opts.program.abi === "wasi" && !done4,
|
|
12703
|
+
times: () => clocks.times(),
|
|
12704
|
+
running: () => clocks.running()
|
|
12543
12705
|
};
|
|
12544
12706
|
}
|
|
12545
12707
|
|
|
@@ -13012,7 +13174,7 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
13012
13174
|
(result) => {
|
|
13013
13175
|
if (result instanceof Uint8Array) {
|
|
13014
13176
|
const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;
|
|
13015
|
-
const bytes = options.owned && whole ? result : result
|
|
13177
|
+
const bytes = options.owned && whole ? result : fresh(result);
|
|
13016
13178
|
reply({ id: data.id, result: bytes }, [bytes.buffer]);
|
|
13017
13179
|
} else reply({ id: data.id, result: result ?? null });
|
|
13018
13180
|
},
|
|
@@ -13500,14 +13662,14 @@ var RESTORE_AGAIN_MS = 3e4;
|
|
|
13500
13662
|
function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
13501
13663
|
const handles = /* @__PURE__ */ new Map();
|
|
13502
13664
|
let nextFh = 0;
|
|
13503
|
-
const
|
|
13665
|
+
const fresh2 = (remote) => {
|
|
13504
13666
|
if (remote.client.token === remote.token && !remote.client.gone) return remote;
|
|
13505
13667
|
throw fsError2("ESTALE", "the folder was granted again, so this open file is gone");
|
|
13506
13668
|
};
|
|
13507
13669
|
const live = (fh) => {
|
|
13508
13670
|
const remote = handles.get(fh);
|
|
13509
13671
|
if (!remote) throw fsError2("EBADF", `handle ${fh}`);
|
|
13510
|
-
return
|
|
13672
|
+
return fresh2(remote);
|
|
13511
13673
|
};
|
|
13512
13674
|
const call = (op, body = {}) => current().call(op, body);
|
|
13513
13675
|
const same = (was, mode, seen) => seen?.mode === (mode | 128) && (was.ino !== void 0 && seen.ino !== void 0 ? seen.ino === was.ino : seen.size === was.size && seen.mtime === was.mtime);
|
|
@@ -13589,7 +13751,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
13589
13751
|
if (!remote) throw fsError2("EBADF", `handle ${fh}`);
|
|
13590
13752
|
handles.delete(fh);
|
|
13591
13753
|
try {
|
|
13592
|
-
await
|
|
13754
|
+
await fresh2(remote).client.call("release", { fh: remote.fh }, true);
|
|
13593
13755
|
} finally {
|
|
13594
13756
|
if (remote.restore) await settle3(current(), remote.restore);
|
|
13595
13757
|
}
|
|
@@ -14855,6 +15017,8 @@ var LAYOUT = [
|
|
|
14855
15017
|
["/usr", 493],
|
|
14856
15018
|
["/usr/local", 493]
|
|
14857
15019
|
];
|
|
15020
|
+
var LOAD_SAMPLE_MS = 5e3;
|
|
15021
|
+
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
14858
15022
|
var encoder3 = new TextEncoder();
|
|
14859
15023
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
14860
15024
|
function usersMode(mode = "off") {
|
|
@@ -15383,6 +15547,7 @@ var Launcher = class {
|
|
|
15383
15547
|
return this.jobs.sessionOf(pgid);
|
|
15384
15548
|
}
|
|
15385
15549
|
start(req) {
|
|
15550
|
+
this.sampling();
|
|
15386
15551
|
if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
|
|
15387
15552
|
throw fsError("ESRCH", `no process group ${req.pgid}`);
|
|
15388
15553
|
}
|
|
@@ -15423,7 +15588,12 @@ var Launcher = class {
|
|
|
15423
15588
|
forker: this.forker(pid, req),
|
|
15424
15589
|
kill: (target, sig) => this.kill(target, sig, this.credOf(pid), pid),
|
|
15425
15590
|
writesBack: (target) => this.processes.get(target)?.writesBack() === true,
|
|
15426
|
-
processes: () => ({
|
|
15591
|
+
processes: () => ({
|
|
15592
|
+
boot: this.boot,
|
|
15593
|
+
processes: this.list(this.credOf(pid)),
|
|
15594
|
+
load: this.loadAverage(),
|
|
15595
|
+
cpu: this.cpuTotal()
|
|
15596
|
+
}),
|
|
15427
15597
|
sudo: (call, signal) => this.sudo(pid, call, signal),
|
|
15428
15598
|
openFiles: this.openFiles,
|
|
15429
15599
|
nodes: this.nodes,
|
|
@@ -15457,7 +15627,14 @@ var Launcher = class {
|
|
|
15457
15627
|
started: Date.now()
|
|
15458
15628
|
});
|
|
15459
15629
|
void handle.exited.then(() => {
|
|
15630
|
+
const spent = handle.times?.();
|
|
15631
|
+
if (spent) this.spent.set(pid, spent);
|
|
15460
15632
|
this.processes.delete(pid);
|
|
15633
|
+
if (this.processes.size === 0) {
|
|
15634
|
+
clearInterval(this.sampler);
|
|
15635
|
+
this.sampler = void 0;
|
|
15636
|
+
this.idleSince = Date.now();
|
|
15637
|
+
}
|
|
15461
15638
|
this.settling.settled(pid);
|
|
15462
15639
|
if (req.ppid === void 0 || this.orphans.delete(pid)) this.forget(pid);
|
|
15463
15640
|
else this.zombies.add(pid);
|
|
@@ -15473,6 +15650,12 @@ var Launcher = class {
|
|
|
15473
15650
|
forget(pid) {
|
|
15474
15651
|
this.jobs.remove(pid);
|
|
15475
15652
|
this.described.delete(pid);
|
|
15653
|
+
const spent = this.spent.get(pid);
|
|
15654
|
+
if (spent) {
|
|
15655
|
+
this.reapedTimes.utime += spent.utime;
|
|
15656
|
+
this.reapedTimes.stime += spent.stime;
|
|
15657
|
+
}
|
|
15658
|
+
this.spent.delete(pid);
|
|
15476
15659
|
this.creds.delete(pid);
|
|
15477
15660
|
this.tags.delete(pid);
|
|
15478
15661
|
this.granted.delete(pid);
|
|
@@ -15481,6 +15664,70 @@ var Launcher = class {
|
|
|
15481
15664
|
if (this.zombies.delete(pid)) this.forget(pid);
|
|
15482
15665
|
else this.orphans.add(pid);
|
|
15483
15666
|
}
|
|
15667
|
+
load = [0, 0, 0];
|
|
15668
|
+
sampler;
|
|
15669
|
+
reapedTimes = { utime: 0, stime: 0 };
|
|
15670
|
+
idleAt = { wall: this.boot, busy: 0, idle: 0 };
|
|
15671
|
+
cpuTotal(now = Date.now()) {
|
|
15672
|
+
const total = { ...this.reapedTimes };
|
|
15673
|
+
const add = (t) => {
|
|
15674
|
+
total.utime += t?.utime ?? 0;
|
|
15675
|
+
total.stime += t?.stime ?? 0;
|
|
15676
|
+
};
|
|
15677
|
+
for (const handle of this.processes.values()) add(handle.times?.());
|
|
15678
|
+
for (const t of this.spent.values()) add(t);
|
|
15679
|
+
const busy = total.utime + total.stime;
|
|
15680
|
+
const at = this.idleAt;
|
|
15681
|
+
at.idle += Math.max(0, now - at.wall - (busy - at.busy));
|
|
15682
|
+
at.wall = Math.max(at.wall, now);
|
|
15683
|
+
at.busy = Math.max(at.busy, busy);
|
|
15684
|
+
return { ...total, idle: at.idle };
|
|
15685
|
+
}
|
|
15686
|
+
loadAverage() {
|
|
15687
|
+
return this.load;
|
|
15688
|
+
}
|
|
15689
|
+
sampledAt = Date.now();
|
|
15690
|
+
sampleLoad(now = Date.now()) {
|
|
15691
|
+
let running = 0;
|
|
15692
|
+
for (const handle of this.processes.values()) running += handle.running?.() ?? 0;
|
|
15693
|
+
const elapsed = Math.max(LOAD_SAMPLE_MS, now - this.sampledAt);
|
|
15694
|
+
this.sampledAt = Math.max(this.sampledAt, now);
|
|
15695
|
+
this.load = this.load.map((avg, i) => {
|
|
15696
|
+
const window = LOAD_WINDOWS_MS[i];
|
|
15697
|
+
const fresh2 = 1 - Math.exp(-LOAD_SAMPLE_MS / window);
|
|
15698
|
+
return avg * Math.exp(-elapsed / window) + running * fresh2;
|
|
15699
|
+
});
|
|
15700
|
+
}
|
|
15701
|
+
idleSince;
|
|
15702
|
+
sampling() {
|
|
15703
|
+
if (this.sampler) return;
|
|
15704
|
+
if (this.idleSince !== void 0) {
|
|
15705
|
+
const empty = Math.max(0, Date.now() - this.idleSince);
|
|
15706
|
+
this.load = this.load.map(
|
|
15707
|
+
(avg, i) => avg * Math.exp(-empty / LOAD_WINDOWS_MS[i])
|
|
15708
|
+
);
|
|
15709
|
+
}
|
|
15710
|
+
this.sampledAt = Date.now();
|
|
15711
|
+
this.sampler = setInterval(() => this.sampleLoad(), LOAD_SAMPLE_MS);
|
|
15712
|
+
this.sampler.unref?.();
|
|
15713
|
+
}
|
|
15714
|
+
spent = /* @__PURE__ */ new Map();
|
|
15715
|
+
timesAt(pid) {
|
|
15716
|
+
return this.processes.get(pid)?.times?.() ?? this.spent.get(pid);
|
|
15717
|
+
}
|
|
15718
|
+
timesOf(member, members) {
|
|
15719
|
+
let utime = 0;
|
|
15720
|
+
let stime = 0;
|
|
15721
|
+
let timed2 = false;
|
|
15722
|
+
for (let at = member; at; at = members.get(at.execParent ?? -1)) {
|
|
15723
|
+
const t = this.timesAt(at.pid);
|
|
15724
|
+
if (!t) continue;
|
|
15725
|
+
timed2 = true;
|
|
15726
|
+
utime += t.utime;
|
|
15727
|
+
stime += t.stime;
|
|
15728
|
+
}
|
|
15729
|
+
return timed2 ? { utime, stime } : {};
|
|
15730
|
+
}
|
|
15484
15731
|
list(viewer = ROOT) {
|
|
15485
15732
|
const members = new Map(this.jobs.list().map((member) => [member.pid, member]));
|
|
15486
15733
|
const rootOf = (member) => {
|
|
@@ -15512,6 +15759,7 @@ var Launcher = class {
|
|
|
15512
15759
|
started: (this.described.get(root.pid) ?? described2).started,
|
|
15513
15760
|
state: this.processes.has(member.pid) ? "S" : "Z",
|
|
15514
15761
|
memory: this.processes.get(member.pid)?.memory() ?? 0,
|
|
15762
|
+
...this.timesOf(member, members),
|
|
15515
15763
|
umask: this.umaskOf(member.pid),
|
|
15516
15764
|
cred,
|
|
15517
15765
|
...this.signalMasksOf(member.pid)
|
|
@@ -15771,8 +16019,8 @@ var Launcher = class {
|
|
|
15771
16019
|
];
|
|
15772
16020
|
for (const [path, mode] of layout) {
|
|
15773
16021
|
const real = await this.realLayoutPath(path);
|
|
15774
|
-
const
|
|
15775
|
-
if (
|
|
16022
|
+
const fresh2 = real !== void 0 && !await this.base.hasOwner?.(real);
|
|
16023
|
+
if (fresh2) await this.base.chown?.(real, { uid: 0, gid: 0, mode, follow: false });
|
|
15776
16024
|
}
|
|
15777
16025
|
}
|
|
15778
16026
|
async realLayoutPath(given) {
|