@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/node.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// src/node.ts
|
|
2
2
|
import { MessageChannel as MessageChannel2, Worker } from "node:worker_threads";
|
|
3
3
|
|
|
4
|
+
// src/bytes.ts
|
|
5
|
+
function fresh(bytes, start2 = 0, end = bytes.length) {
|
|
6
|
+
return new Uint8Array(bytes.subarray(start2, end));
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
// src/cdp/port.ts
|
|
5
10
|
function serveCdpPort(port, hook, request, onDone) {
|
|
6
11
|
let conn;
|
|
@@ -2034,7 +2039,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2034
2039
|
}
|
|
2035
2040
|
if (typeof data === "string") peer.postMessage({ net: "ws-message", nid, data });
|
|
2036
2041
|
else {
|
|
2037
|
-
const bytes = data
|
|
2042
|
+
const bytes = fresh(data);
|
|
2038
2043
|
peer.postMessage({ net: "ws-message", nid, data: bytes }, [bytes.buffer]);
|
|
2039
2044
|
}
|
|
2040
2045
|
flow.inflight += payloadSize(data);
|
|
@@ -2072,7 +2077,7 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
|
|
|
2072
2077
|
open.delete(nid);
|
|
2073
2078
|
peer.postMessage({ net: "end", nid });
|
|
2074
2079
|
} else {
|
|
2075
|
-
const bytes = next2.value
|
|
2080
|
+
const bytes = fresh(next2.value);
|
|
2076
2081
|
peer.postMessage({ net: "chunk", nid, bytes }, [bytes.buffer]);
|
|
2077
2082
|
}
|
|
2078
2083
|
} catch (e) {
|
|
@@ -2366,7 +2371,7 @@ var UserDb = class {
|
|
|
2366
2371
|
joined(name2, extra);
|
|
2367
2372
|
group.push({ name: name2, gid: uid, members: [] });
|
|
2368
2373
|
passwd.push(row);
|
|
2369
|
-
const
|
|
2374
|
+
const fresh2 = !await this.fs.exists(home);
|
|
2370
2375
|
await this.fs.mkdir(home, { recursive: true });
|
|
2371
2376
|
try {
|
|
2372
2377
|
await this.provision(row);
|
|
@@ -2374,7 +2379,7 @@ var UserDb = class {
|
|
|
2374
2379
|
await this.fs.mkdir("/etc", { recursive: true });
|
|
2375
2380
|
await this.commit(formatPasswd(passwd), formatGroup(group));
|
|
2376
2381
|
} catch (err) {
|
|
2377
|
-
if (
|
|
2382
|
+
if (fresh2) await this.fs.rm(home, { recursive: true, force: true });
|
|
2378
2383
|
throw err;
|
|
2379
2384
|
}
|
|
2380
2385
|
remember();
|
|
@@ -2519,7 +2524,7 @@ async function fsCall(fs, method, args, owner, g) {
|
|
|
2519
2524
|
}
|
|
2520
2525
|
switch (method) {
|
|
2521
2526
|
case "readFile": {
|
|
2522
|
-
const bytes = (await fs.readFileBuffer(path(0)))
|
|
2527
|
+
const bytes = fresh(await fs.readFileBuffer(path(0)));
|
|
2523
2528
|
return { result: bytes, transfer: [bytes.buffer] };
|
|
2524
2529
|
}
|
|
2525
2530
|
case "writeFile":
|
|
@@ -5530,11 +5535,11 @@ var ChildTable = class {
|
|
|
5530
5535
|
return [...this.children.keys()];
|
|
5531
5536
|
}
|
|
5532
5537
|
captured(pid, slot2) {
|
|
5533
|
-
const
|
|
5534
|
-
const chunks2 =
|
|
5535
|
-
if (!
|
|
5536
|
-
|
|
5537
|
-
if (
|
|
5538
|
+
const slots2 = this.leftovers.get(pid);
|
|
5539
|
+
const chunks2 = slots2?.get(slot2);
|
|
5540
|
+
if (!slots2 || !chunks2) return new Uint8Array(0);
|
|
5541
|
+
slots2.delete(slot2);
|
|
5542
|
+
if (slots2.size === 0) this.leftovers.delete(pid);
|
|
5538
5543
|
return concat2(chunks2);
|
|
5539
5544
|
}
|
|
5540
5545
|
};
|
|
@@ -5721,9 +5726,9 @@ var HeldPaths = class extends Map {
|
|
|
5721
5726
|
return this.keptHandles.get(handle);
|
|
5722
5727
|
}
|
|
5723
5728
|
keep(path, file) {
|
|
5724
|
-
const
|
|
5725
|
-
for (const id2 of
|
|
5726
|
-
this.uses.set(file, Math.max(
|
|
5729
|
+
const fresh2 = this.handlesAt(path).filter((id2) => !this.keptHandles.has(id2));
|
|
5730
|
+
for (const id2 of fresh2) this.keptHandles.set(id2, file);
|
|
5731
|
+
this.uses.set(file, Math.max(fresh2.length, 1));
|
|
5727
5732
|
this.unlinked.set(path, file);
|
|
5728
5733
|
}
|
|
5729
5734
|
unkeep(path, file) {
|
|
@@ -6279,7 +6284,7 @@ var MountFs = class {
|
|
|
6279
6284
|
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
6280
6285
|
try {
|
|
6281
6286
|
for (let offset = 0; offset < bytes.length; offset += chunk2) {
|
|
6282
|
-
const part = bytes
|
|
6287
|
+
const part = fresh(bytes, offset, offset + chunk2);
|
|
6283
6288
|
await mount.conn.call({ op: "write", fh, offset, bytes: part }, [part.buffer]);
|
|
6284
6289
|
}
|
|
6285
6290
|
} finally {
|
|
@@ -6376,7 +6381,7 @@ var MountFs = class {
|
|
|
6376
6381
|
async writeRuns(mount, fh, offset, bytes, transfer) {
|
|
6377
6382
|
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
6378
6383
|
for (let at = 0; at < bytes.length; at += chunk2) {
|
|
6379
|
-
const part = handed(bytes, transfer, chunk2) ? bytes : bytes
|
|
6384
|
+
const part = handed(bytes, transfer, chunk2) ? bytes : fresh(bytes, at, at + chunk2);
|
|
6380
6385
|
await mount.conn.call({ op: "write", fh, offset: offset + at, bytes: part }, [part.buffer]);
|
|
6381
6386
|
}
|
|
6382
6387
|
}
|
|
@@ -6608,8 +6613,8 @@ var MountFs = class {
|
|
|
6608
6613
|
}
|
|
6609
6614
|
this.writable(mount, real);
|
|
6610
6615
|
const { uid, gid, mode } = change;
|
|
6611
|
-
const
|
|
6612
|
-
const set2 =
|
|
6616
|
+
const fresh2 = change.kind === "new" && { uid, gid, mode };
|
|
6617
|
+
const set2 = fresh2 ? await this.driverOwner(found, real, fresh2, false) : change;
|
|
6613
6618
|
this.table.forget(mount, real);
|
|
6614
6619
|
const attrs = Object.entries({ uid: set2.uid, gid: set2.gid, mode: set2.mode });
|
|
6615
6620
|
await mount.conn.call({
|
|
@@ -7006,7 +7011,9 @@ async function dispatchOne(entry, req) {
|
|
|
7006
7011
|
|
|
7007
7012
|
// src/realm/sync-sab-wire.ts
|
|
7008
7013
|
var SAB_HEADER_I32 = 16;
|
|
7009
|
-
var
|
|
7014
|
+
var SAB_CLOCK_OFFSET = SAB_HEADER_I32 * 4;
|
|
7015
|
+
var SAB_CLOCK_I64 = 3;
|
|
7016
|
+
var SAB_HEADER_BYTES = SAB_CLOCK_OFFSET + SAB_CLOCK_I64 * 8;
|
|
7010
7017
|
var SAB_I_STATE = 0;
|
|
7011
7018
|
var SAB_I_SEQ = 1;
|
|
7012
7019
|
var SAB_I_STATUS = 2;
|
|
@@ -7156,6 +7163,146 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
7156
7163
|
};
|
|
7157
7164
|
}
|
|
7158
7165
|
|
|
7166
|
+
// src/kernel/cpu-clock.ts
|
|
7167
|
+
var IDLE_OPS = /* @__PURE__ */ new Set([
|
|
7168
|
+
"fd-select",
|
|
7169
|
+
"proc-wait",
|
|
7170
|
+
"proc-exec",
|
|
7171
|
+
"sig-pause",
|
|
7172
|
+
"sock-accept",
|
|
7173
|
+
"sock-connect"
|
|
7174
|
+
]);
|
|
7175
|
+
var SYS_CAP_US = 2e4;
|
|
7176
|
+
var LOCAL = SAB_CLOCK_OFFSET;
|
|
7177
|
+
var IDLE = 1;
|
|
7178
|
+
function epochMicros() {
|
|
7179
|
+
return Math.floor((performance.timeOrigin + performance.now()) * 1e3);
|
|
7180
|
+
}
|
|
7181
|
+
function slots(sab) {
|
|
7182
|
+
return new BigInt64Array(sab, LOCAL, SAB_CLOCK_I64);
|
|
7183
|
+
}
|
|
7184
|
+
var rawWait = Atomics.wait.bind(Atomics);
|
|
7185
|
+
function localIdle(sab, now) {
|
|
7186
|
+
const state = Number(Atomics.load(slots(sab), IDLE));
|
|
7187
|
+
if (state >= 0) return { idle: state, waiting: false };
|
|
7188
|
+
return { idle: Math.max(0, now + state), waiting: true };
|
|
7189
|
+
}
|
|
7190
|
+
var CpuClock = class {
|
|
7191
|
+
start;
|
|
7192
|
+
sys = 0;
|
|
7193
|
+
idle = 0;
|
|
7194
|
+
since = 0;
|
|
7195
|
+
kind = "sys";
|
|
7196
|
+
stopped = false;
|
|
7197
|
+
last = { utime: 0, stime: 0 };
|
|
7198
|
+
sab;
|
|
7199
|
+
now;
|
|
7200
|
+
constructor(sab, now = epochMicros) {
|
|
7201
|
+
this.sab = sab;
|
|
7202
|
+
this.now = now;
|
|
7203
|
+
this.start = now();
|
|
7204
|
+
}
|
|
7205
|
+
enter(op) {
|
|
7206
|
+
this.since = this.now();
|
|
7207
|
+
this.kind = this.stopped || IDLE_OPS.has(op) ? "idle" : "sys";
|
|
7208
|
+
}
|
|
7209
|
+
leave() {
|
|
7210
|
+
if (this.since === 0) return;
|
|
7211
|
+
this.add((this.frozen ?? this.now()) - this.since);
|
|
7212
|
+
this.since = 0;
|
|
7213
|
+
}
|
|
7214
|
+
stop(stopped) {
|
|
7215
|
+
if (stopped === this.stopped) return;
|
|
7216
|
+
this.stopped = stopped;
|
|
7217
|
+
if (this.since === 0 || !stopped || this.frozen !== void 0) return;
|
|
7218
|
+
const now = this.now();
|
|
7219
|
+
this.add(now - this.since);
|
|
7220
|
+
this.since = now;
|
|
7221
|
+
this.kind = "idle";
|
|
7222
|
+
}
|
|
7223
|
+
frozen;
|
|
7224
|
+
freeze() {
|
|
7225
|
+
this.frozen ??= this.now();
|
|
7226
|
+
}
|
|
7227
|
+
running() {
|
|
7228
|
+
if (this.frozen !== void 0) return false;
|
|
7229
|
+
const now = this.now();
|
|
7230
|
+
const busy = this.since === 0 || this.kind === "sys" && now - this.since < SYS_CAP_US;
|
|
7231
|
+
return busy && !localIdle(this.sab, now).waiting;
|
|
7232
|
+
}
|
|
7233
|
+
times() {
|
|
7234
|
+
const now = this.frozen ?? this.now();
|
|
7235
|
+
const open = this.since === 0 ? 0 : Math.max(0, now - this.since);
|
|
7236
|
+
const busy = this.kind === "sys" ? Math.min(open, SYS_CAP_US) : 0;
|
|
7237
|
+
const sys = this.sys + busy;
|
|
7238
|
+
const idle = this.idle + (open - busy) + localIdle(this.sab, now).idle;
|
|
7239
|
+
const user = Math.max(0, now - this.start - sys - idle);
|
|
7240
|
+
this.last = {
|
|
7241
|
+
utime: Math.max(this.last.utime, Math.floor(user / 1e3)),
|
|
7242
|
+
stime: Math.max(this.last.stime, Math.floor(sys / 1e3))
|
|
7243
|
+
};
|
|
7244
|
+
return this.last;
|
|
7245
|
+
}
|
|
7246
|
+
add(micros) {
|
|
7247
|
+
const spent = Math.max(0, micros);
|
|
7248
|
+
const busy = this.kind === "sys" ? Math.min(spent, SYS_CAP_US) : 0;
|
|
7249
|
+
this.sys += busy;
|
|
7250
|
+
this.idle += spent - busy;
|
|
7251
|
+
}
|
|
7252
|
+
};
|
|
7253
|
+
var ProcessClocks = class {
|
|
7254
|
+
main;
|
|
7255
|
+
threads = /* @__PURE__ */ new Map();
|
|
7256
|
+
ended = { utime: 0, stime: 0 };
|
|
7257
|
+
enabled;
|
|
7258
|
+
constructor(sab, enabled = true, states) {
|
|
7259
|
+
this.main = new CpuClock(sab);
|
|
7260
|
+
this.enabled = enabled;
|
|
7261
|
+
states?.onState((state) => this.stop(state === "stopped"));
|
|
7262
|
+
}
|
|
7263
|
+
thread(tid, sab) {
|
|
7264
|
+
const clock = new CpuClock(sab);
|
|
7265
|
+
this.threads.set(tid, clock);
|
|
7266
|
+
return clock;
|
|
7267
|
+
}
|
|
7268
|
+
threadEnded(tid) {
|
|
7269
|
+
const spent = this.threads.get(tid)?.times();
|
|
7270
|
+
this.threads.delete(tid);
|
|
7271
|
+
if (!spent) return;
|
|
7272
|
+
this.ended.utime += spent.utime;
|
|
7273
|
+
this.ended.stime += spent.stime;
|
|
7274
|
+
}
|
|
7275
|
+
stop(stopped) {
|
|
7276
|
+
for (const c of this.all()) c.stop(stopped);
|
|
7277
|
+
}
|
|
7278
|
+
freeze() {
|
|
7279
|
+
for (const c of this.all()) c.freeze();
|
|
7280
|
+
}
|
|
7281
|
+
times() {
|
|
7282
|
+
if (!this.enabled) return void 0;
|
|
7283
|
+
const sum = { ...this.ended };
|
|
7284
|
+
for (const c of this.all()) {
|
|
7285
|
+
const t = c.times();
|
|
7286
|
+
sum.utime += t.utime;
|
|
7287
|
+
sum.stime += t.stime;
|
|
7288
|
+
}
|
|
7289
|
+
return sum;
|
|
7290
|
+
}
|
|
7291
|
+
running() {
|
|
7292
|
+
return this.enabled ? this.all().filter((c) => c.running()).length : 0;
|
|
7293
|
+
}
|
|
7294
|
+
timed(clock, dispatch2) {
|
|
7295
|
+
const c = clock ?? this.main;
|
|
7296
|
+
return (req) => {
|
|
7297
|
+
c.enter(req.op);
|
|
7298
|
+
return dispatch2(req).finally(() => c.leave());
|
|
7299
|
+
};
|
|
7300
|
+
}
|
|
7301
|
+
all() {
|
|
7302
|
+
return [this.main, ...this.threads.values()];
|
|
7303
|
+
}
|
|
7304
|
+
};
|
|
7305
|
+
|
|
7159
7306
|
// src/kernel/net/loopback-names.ts
|
|
7160
7307
|
var HOST_LOOPBACK = "host.slicc.internal";
|
|
7161
7308
|
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
@@ -7239,9 +7386,9 @@ var Pages = class {
|
|
|
7239
7386
|
const page = (start2 + at) / PAGE;
|
|
7240
7387
|
if (this.pages.has(page)) continue;
|
|
7241
7388
|
const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
|
|
7242
|
-
const
|
|
7243
|
-
|
|
7244
|
-
this.pages.set(page,
|
|
7389
|
+
const fresh2 = this.take(part.length);
|
|
7390
|
+
fresh2.set(part);
|
|
7391
|
+
this.pages.set(page, fresh2);
|
|
7245
7392
|
}
|
|
7246
7393
|
}
|
|
7247
7394
|
read(at, length2) {
|
|
@@ -7467,8 +7614,8 @@ function pidStat(info, boot) {
|
|
|
7467
7614
|
0,
|
|
7468
7615
|
0,
|
|
7469
7616
|
0,
|
|
7470
|
-
0,
|
|
7471
|
-
0,
|
|
7617
|
+
ticks(info.utime ?? 0),
|
|
7618
|
+
ticks(info.stime ?? 0),
|
|
7472
7619
|
0,
|
|
7473
7620
|
0,
|
|
7474
7621
|
20,
|
|
@@ -7562,19 +7709,23 @@ function systemFile(name2, listing, now, memory) {
|
|
|
7562
7709
|
if (name2 === "meminfo") {
|
|
7563
7710
|
return memoryInfo(
|
|
7564
7711
|
memory,
|
|
7565
|
-
listing.processes.reduce((
|
|
7712
|
+
listing.processes.reduce((sum2, p) => sum2 + p.memory, 0)
|
|
7566
7713
|
);
|
|
7567
7714
|
}
|
|
7568
7715
|
const live = listing.processes.filter((p) => p.state !== "Z");
|
|
7569
7716
|
if (name2 === "loadavg") {
|
|
7570
7717
|
const last = Math.max(0, ...listing.processes.map((p) => p.pid));
|
|
7571
|
-
|
|
7718
|
+
const [one, five, fifteen] = (listing.load ?? [0, 0, 0]).map((n) => n.toFixed(2));
|
|
7719
|
+
return `${one} ${five} ${fifteen} 1/${live.length} ${last}
|
|
7572
7720
|
`;
|
|
7573
7721
|
}
|
|
7574
|
-
const
|
|
7722
|
+
const sum = (key) => listing.cpu?.[key] ?? listing.processes.reduce((n, p) => n + (p[key] ?? 0), 0);
|
|
7723
|
+
const user = ticks(sum("utime"));
|
|
7724
|
+
const system = ticks(sum("stime"));
|
|
7725
|
+
const idle = listing.cpu ? ticks(listing.cpu.idle) : Math.max(0, ticks(now - listing.boot) - user - system);
|
|
7575
7726
|
return [
|
|
7576
|
-
`cpu
|
|
7577
|
-
`cpu0
|
|
7727
|
+
`cpu ${user} 0 ${system} ${idle} 0 0 0 0 0 0`,
|
|
7728
|
+
`cpu0 ${user} 0 ${system} ${idle} 0 0 0 0 0 0`,
|
|
7578
7729
|
"intr 0",
|
|
7579
7730
|
"ctxt 0",
|
|
7580
7731
|
`btime ${Math.floor(listing.boot / 1e3)}`,
|
|
@@ -11340,10 +11491,10 @@ var WasmProcess = class {
|
|
|
11340
11491
|
this.fds.installAt(fd, this.openVfsFile(open));
|
|
11341
11492
|
} else if (req.create) {
|
|
11342
11493
|
await nodes.onEntry(path, async () => {
|
|
11343
|
-
const
|
|
11494
|
+
const fresh2 = this.options.owners && !await present2(this.options.fs, path, true);
|
|
11344
11495
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path)));
|
|
11345
11496
|
await this.fds.get(fd).file.stat?.();
|
|
11346
|
-
if (
|
|
11497
|
+
if (fresh2) await this.options.fs.chown?.(path, { ...this.newOwner(), kind: "new" });
|
|
11347
11498
|
});
|
|
11348
11499
|
} else {
|
|
11349
11500
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path)));
|
|
@@ -12034,6 +12185,9 @@ function killThread(thread, caught, sig) {
|
|
|
12034
12185
|
blocked.abort();
|
|
12035
12186
|
return true;
|
|
12036
12187
|
}
|
|
12188
|
+
function threadSignalsOf(sab) {
|
|
12189
|
+
return { header: new Int32Array(sab, 0, SAB_HEADER_I32), interrupt: new AbortController() };
|
|
12190
|
+
}
|
|
12037
12191
|
function threadCancel(thread) {
|
|
12038
12192
|
return Atomics.load(thread.header, SAB_I_SIGNALS) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
12039
12193
|
}
|
|
@@ -12159,6 +12313,22 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
12159
12313
|
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header4, SAB_I_SIGNALS) } : {}
|
|
12160
12314
|
};
|
|
12161
12315
|
}
|
|
12316
|
+
function threadInit(opts, program, sab, cred, thread) {
|
|
12317
|
+
return {
|
|
12318
|
+
type: WASM_THREAD_INIT,
|
|
12319
|
+
pid: opts.shownPid ?? opts.pid,
|
|
12320
|
+
program,
|
|
12321
|
+
argv0: opts.argv0,
|
|
12322
|
+
args: opts.args,
|
|
12323
|
+
env: opts.env,
|
|
12324
|
+
cwd: opts.cwd,
|
|
12325
|
+
sab,
|
|
12326
|
+
cred: copyCred(cred),
|
|
12327
|
+
owners: opts.owners === true,
|
|
12328
|
+
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
12329
|
+
thread
|
|
12330
|
+
};
|
|
12331
|
+
}
|
|
12162
12332
|
function spawnWasmProcess(opts) {
|
|
12163
12333
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
12164
12334
|
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
@@ -12191,7 +12361,10 @@ function spawnWasmProcess(opts) {
|
|
|
12191
12361
|
const worker = opts.createWorker();
|
|
12192
12362
|
const dying = new Dying();
|
|
12193
12363
|
const dispatch2 = (req) => dying.serving(() => isWasmSyscall(req) ? process2.syscall(req) : dispatchSyncFs(req));
|
|
12194
|
-
const
|
|
12364
|
+
const clocks = new ProcessClocks(sab, opts.program.abi !== "js", process2);
|
|
12365
|
+
const responder = attachSyncSabResponder(worker, sab, token, {
|
|
12366
|
+
dispatch: clocks.timed(void 0, dispatch2)
|
|
12367
|
+
});
|
|
12195
12368
|
const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
|
|
12196
12369
|
const { promise: exited, resolve: settle } = Promise.withResolvers();
|
|
12197
12370
|
let done4 = false;
|
|
@@ -12199,6 +12372,7 @@ function spawnWasmProcess(opts) {
|
|
|
12199
12372
|
const finish = (code, sig) => {
|
|
12200
12373
|
if (done4) return;
|
|
12201
12374
|
done4 = true;
|
|
12375
|
+
clocks.freeze();
|
|
12202
12376
|
dying.clear();
|
|
12203
12377
|
endedBy = sig ?? process2.execTermsig;
|
|
12204
12378
|
worker.removeEventListener("message", onMessage);
|
|
@@ -12239,6 +12413,7 @@ function spawnWasmProcess(opts) {
|
|
|
12239
12413
|
const endThread = (tid) => {
|
|
12240
12414
|
const end = threads.get(tid);
|
|
12241
12415
|
threads.delete(tid);
|
|
12416
|
+
clocks.threadEnded(tid);
|
|
12242
12417
|
process2.threadEnded(tid);
|
|
12243
12418
|
end?.();
|
|
12244
12419
|
};
|
|
@@ -12252,15 +12427,14 @@ function spawnWasmProcess(opts) {
|
|
|
12252
12427
|
}
|
|
12253
12428
|
const tsab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
12254
12429
|
const tw = opts.createWorker();
|
|
12255
|
-
const tsignals =
|
|
12256
|
-
header: new Int32Array(tsab, 0, SAB_HEADER_I32),
|
|
12257
|
-
interrupt: new AbortController()
|
|
12258
|
-
};
|
|
12430
|
+
const tsignals = threadSignalsOf(tsab);
|
|
12259
12431
|
threadSignals.set(thread.tid, tsignals);
|
|
12260
12432
|
const tdispatch = (req) => dying.serving(
|
|
12261
12433
|
() => isWasmSyscall(req) ? process2.syscall(req, threadCancel(tsignals)) : dispatchSyncFs(req)
|
|
12262
12434
|
);
|
|
12263
|
-
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
12435
|
+
const tresponder = attachSyncSabResponder(tw, tsab, token, {
|
|
12436
|
+
dispatch: clocks.timed(clocks.thread(thread.tid, tsab), tdispatch)
|
|
12437
|
+
});
|
|
12264
12438
|
const onThreadMessage = (event) => {
|
|
12265
12439
|
const data = event.data;
|
|
12266
12440
|
if (data?.type === WASM_THREAD_EXIT) endThread(thread.tid);
|
|
@@ -12275,21 +12449,7 @@ function spawnWasmProcess(opts) {
|
|
|
12275
12449
|
tresponder.dispose();
|
|
12276
12450
|
tw.terminate();
|
|
12277
12451
|
});
|
|
12278
|
-
|
|
12279
|
-
type: WASM_THREAD_INIT,
|
|
12280
|
-
pid: opts.shownPid ?? opts.pid,
|
|
12281
|
-
program,
|
|
12282
|
-
argv0: opts.argv0,
|
|
12283
|
-
args: opts.args,
|
|
12284
|
-
env: opts.env,
|
|
12285
|
-
cwd: opts.cwd,
|
|
12286
|
-
sab: tsab,
|
|
12287
|
-
cred: copyCred(process2.cred),
|
|
12288
|
-
owners: opts.owners === true,
|
|
12289
|
-
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
12290
|
-
thread
|
|
12291
|
-
};
|
|
12292
|
-
tw.postMessage(tinit);
|
|
12452
|
+
tw.postMessage(threadInit(opts, program, tsab, process2.cred, thread));
|
|
12293
12453
|
};
|
|
12294
12454
|
worker.postMessage(
|
|
12295
12455
|
processInit(opts, sab, process2.umask, copyCred(process2.cred), lane?.lane),
|
|
@@ -12314,7 +12474,9 @@ function spawnWasmProcess(opts) {
|
|
|
12314
12474
|
signalMasks: () => process2.signalMasks(),
|
|
12315
12475
|
umask: () => process2.umask,
|
|
12316
12476
|
cred: () => copyCred(process2.cred),
|
|
12317
|
-
writesBack: () => opts.program.abi === "wasi" && !done4
|
|
12477
|
+
writesBack: () => opts.program.abi === "wasi" && !done4,
|
|
12478
|
+
times: () => clocks.times(),
|
|
12479
|
+
running: () => clocks.running()
|
|
12318
12480
|
};
|
|
12319
12481
|
}
|
|
12320
12482
|
|
|
@@ -12787,7 +12949,7 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
12787
12949
|
(result) => {
|
|
12788
12950
|
if (result instanceof Uint8Array) {
|
|
12789
12951
|
const whole = result.byteOffset === 0 && result.byteLength === result.buffer.byteLength;
|
|
12790
|
-
const bytes = options.owned && whole ? result : result
|
|
12952
|
+
const bytes = options.owned && whole ? result : fresh(result);
|
|
12791
12953
|
reply({ id: data.id, result: bytes }, [bytes.buffer]);
|
|
12792
12954
|
} else reply({ id: data.id, result: result ?? null });
|
|
12793
12955
|
},
|
|
@@ -13275,14 +13437,14 @@ var RESTORE_AGAIN_MS = 3e4;
|
|
|
13275
13437
|
function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
13276
13438
|
const handles = /* @__PURE__ */ new Map();
|
|
13277
13439
|
let nextFh = 0;
|
|
13278
|
-
const
|
|
13440
|
+
const fresh2 = (remote) => {
|
|
13279
13441
|
if (remote.client.token === remote.token && !remote.client.gone) return remote;
|
|
13280
13442
|
throw fsError2("ESTALE", "the folder was granted again, so this open file is gone");
|
|
13281
13443
|
};
|
|
13282
13444
|
const live = (fh) => {
|
|
13283
13445
|
const remote = handles.get(fh);
|
|
13284
13446
|
if (!remote) throw fsError2("EBADF", `handle ${fh}`);
|
|
13285
|
-
return
|
|
13447
|
+
return fresh2(remote);
|
|
13286
13448
|
};
|
|
13287
13449
|
const call = (op, body = {}) => current().call(op, body);
|
|
13288
13450
|
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);
|
|
@@ -13364,7 +13526,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
13364
13526
|
if (!remote) throw fsError2("EBADF", `handle ${fh}`);
|
|
13365
13527
|
handles.delete(fh);
|
|
13366
13528
|
try {
|
|
13367
|
-
await
|
|
13529
|
+
await fresh2(remote).client.call("release", { fh: remote.fh }, true);
|
|
13368
13530
|
} finally {
|
|
13369
13531
|
if (remote.restore) await settle(current(), remote.restore);
|
|
13370
13532
|
}
|
|
@@ -14733,6 +14895,8 @@ var LAYOUT = [
|
|
|
14733
14895
|
["/usr", 493],
|
|
14734
14896
|
["/usr/local", 493]
|
|
14735
14897
|
];
|
|
14898
|
+
var LOAD_SAMPLE_MS = 5e3;
|
|
14899
|
+
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
14736
14900
|
var encoder3 = new TextEncoder();
|
|
14737
14901
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
14738
14902
|
function usersMode(mode = "off") {
|
|
@@ -15261,6 +15425,7 @@ var Launcher = class {
|
|
|
15261
15425
|
return this.jobs.sessionOf(pgid);
|
|
15262
15426
|
}
|
|
15263
15427
|
start(req) {
|
|
15428
|
+
this.sampling();
|
|
15264
15429
|
if (req.pgid !== void 0 && this.jobs.sessionOf(req.pgid) === void 0) {
|
|
15265
15430
|
throw fsError("ESRCH", `no process group ${req.pgid}`);
|
|
15266
15431
|
}
|
|
@@ -15301,7 +15466,12 @@ var Launcher = class {
|
|
|
15301
15466
|
forker: this.forker(pid, req),
|
|
15302
15467
|
kill: (target, sig) => this.kill(target, sig, this.credOf(pid), pid),
|
|
15303
15468
|
writesBack: (target) => this.processes.get(target)?.writesBack() === true,
|
|
15304
|
-
processes: () => ({
|
|
15469
|
+
processes: () => ({
|
|
15470
|
+
boot: this.boot,
|
|
15471
|
+
processes: this.list(this.credOf(pid)),
|
|
15472
|
+
load: this.loadAverage(),
|
|
15473
|
+
cpu: this.cpuTotal()
|
|
15474
|
+
}),
|
|
15305
15475
|
sudo: (call, signal) => this.sudo(pid, call, signal),
|
|
15306
15476
|
openFiles: this.openFiles,
|
|
15307
15477
|
nodes: this.nodes,
|
|
@@ -15335,7 +15505,14 @@ var Launcher = class {
|
|
|
15335
15505
|
started: Date.now()
|
|
15336
15506
|
});
|
|
15337
15507
|
void handle.exited.then(() => {
|
|
15508
|
+
const spent = handle.times?.();
|
|
15509
|
+
if (spent) this.spent.set(pid, spent);
|
|
15338
15510
|
this.processes.delete(pid);
|
|
15511
|
+
if (this.processes.size === 0) {
|
|
15512
|
+
clearInterval(this.sampler);
|
|
15513
|
+
this.sampler = void 0;
|
|
15514
|
+
this.idleSince = Date.now();
|
|
15515
|
+
}
|
|
15339
15516
|
this.settling.settled(pid);
|
|
15340
15517
|
if (req.ppid === void 0 || this.orphans.delete(pid)) this.forget(pid);
|
|
15341
15518
|
else this.zombies.add(pid);
|
|
@@ -15351,6 +15528,12 @@ var Launcher = class {
|
|
|
15351
15528
|
forget(pid) {
|
|
15352
15529
|
this.jobs.remove(pid);
|
|
15353
15530
|
this.described.delete(pid);
|
|
15531
|
+
const spent = this.spent.get(pid);
|
|
15532
|
+
if (spent) {
|
|
15533
|
+
this.reapedTimes.utime += spent.utime;
|
|
15534
|
+
this.reapedTimes.stime += spent.stime;
|
|
15535
|
+
}
|
|
15536
|
+
this.spent.delete(pid);
|
|
15354
15537
|
this.creds.delete(pid);
|
|
15355
15538
|
this.tags.delete(pid);
|
|
15356
15539
|
this.granted.delete(pid);
|
|
@@ -15359,6 +15542,70 @@ var Launcher = class {
|
|
|
15359
15542
|
if (this.zombies.delete(pid)) this.forget(pid);
|
|
15360
15543
|
else this.orphans.add(pid);
|
|
15361
15544
|
}
|
|
15545
|
+
load = [0, 0, 0];
|
|
15546
|
+
sampler;
|
|
15547
|
+
reapedTimes = { utime: 0, stime: 0 };
|
|
15548
|
+
idleAt = { wall: this.boot, busy: 0, idle: 0 };
|
|
15549
|
+
cpuTotal(now = Date.now()) {
|
|
15550
|
+
const total = { ...this.reapedTimes };
|
|
15551
|
+
const add = (t) => {
|
|
15552
|
+
total.utime += t?.utime ?? 0;
|
|
15553
|
+
total.stime += t?.stime ?? 0;
|
|
15554
|
+
};
|
|
15555
|
+
for (const handle of this.processes.values()) add(handle.times?.());
|
|
15556
|
+
for (const t of this.spent.values()) add(t);
|
|
15557
|
+
const busy = total.utime + total.stime;
|
|
15558
|
+
const at = this.idleAt;
|
|
15559
|
+
at.idle += Math.max(0, now - at.wall - (busy - at.busy));
|
|
15560
|
+
at.wall = Math.max(at.wall, now);
|
|
15561
|
+
at.busy = Math.max(at.busy, busy);
|
|
15562
|
+
return { ...total, idle: at.idle };
|
|
15563
|
+
}
|
|
15564
|
+
loadAverage() {
|
|
15565
|
+
return this.load;
|
|
15566
|
+
}
|
|
15567
|
+
sampledAt = Date.now();
|
|
15568
|
+
sampleLoad(now = Date.now()) {
|
|
15569
|
+
let running = 0;
|
|
15570
|
+
for (const handle of this.processes.values()) running += handle.running?.() ?? 0;
|
|
15571
|
+
const elapsed = Math.max(LOAD_SAMPLE_MS, now - this.sampledAt);
|
|
15572
|
+
this.sampledAt = Math.max(this.sampledAt, now);
|
|
15573
|
+
this.load = this.load.map((avg, i) => {
|
|
15574
|
+
const window = LOAD_WINDOWS_MS[i];
|
|
15575
|
+
const fresh2 = 1 - Math.exp(-LOAD_SAMPLE_MS / window);
|
|
15576
|
+
return avg * Math.exp(-elapsed / window) + running * fresh2;
|
|
15577
|
+
});
|
|
15578
|
+
}
|
|
15579
|
+
idleSince;
|
|
15580
|
+
sampling() {
|
|
15581
|
+
if (this.sampler) return;
|
|
15582
|
+
if (this.idleSince !== void 0) {
|
|
15583
|
+
const empty = Math.max(0, Date.now() - this.idleSince);
|
|
15584
|
+
this.load = this.load.map(
|
|
15585
|
+
(avg, i) => avg * Math.exp(-empty / LOAD_WINDOWS_MS[i])
|
|
15586
|
+
);
|
|
15587
|
+
}
|
|
15588
|
+
this.sampledAt = Date.now();
|
|
15589
|
+
this.sampler = setInterval(() => this.sampleLoad(), LOAD_SAMPLE_MS);
|
|
15590
|
+
this.sampler.unref?.();
|
|
15591
|
+
}
|
|
15592
|
+
spent = /* @__PURE__ */ new Map();
|
|
15593
|
+
timesAt(pid) {
|
|
15594
|
+
return this.processes.get(pid)?.times?.() ?? this.spent.get(pid);
|
|
15595
|
+
}
|
|
15596
|
+
timesOf(member, members) {
|
|
15597
|
+
let utime = 0;
|
|
15598
|
+
let stime = 0;
|
|
15599
|
+
let timed2 = false;
|
|
15600
|
+
for (let at = member; at; at = members.get(at.execParent ?? -1)) {
|
|
15601
|
+
const t = this.timesAt(at.pid);
|
|
15602
|
+
if (!t) continue;
|
|
15603
|
+
timed2 = true;
|
|
15604
|
+
utime += t.utime;
|
|
15605
|
+
stime += t.stime;
|
|
15606
|
+
}
|
|
15607
|
+
return timed2 ? { utime, stime } : {};
|
|
15608
|
+
}
|
|
15362
15609
|
list(viewer = ROOT) {
|
|
15363
15610
|
const members = new Map(this.jobs.list().map((member) => [member.pid, member]));
|
|
15364
15611
|
const rootOf = (member) => {
|
|
@@ -15390,6 +15637,7 @@ var Launcher = class {
|
|
|
15390
15637
|
started: (this.described.get(root.pid) ?? described2).started,
|
|
15391
15638
|
state: this.processes.has(member.pid) ? "S" : "Z",
|
|
15392
15639
|
memory: this.processes.get(member.pid)?.memory() ?? 0,
|
|
15640
|
+
...this.timesOf(member, members),
|
|
15393
15641
|
umask: this.umaskOf(member.pid),
|
|
15394
15642
|
cred,
|
|
15395
15643
|
...this.signalMasksOf(member.pid)
|
|
@@ -15649,8 +15897,8 @@ var Launcher = class {
|
|
|
15649
15897
|
];
|
|
15650
15898
|
for (const [path, mode] of layout) {
|
|
15651
15899
|
const real = await this.realLayoutPath(path);
|
|
15652
|
-
const
|
|
15653
|
-
if (
|
|
15900
|
+
const fresh2 = real !== void 0 && !await this.base.hasOwner?.(real);
|
|
15901
|
+
if (fresh2) await this.base.chown?.(real, { uid: 0, gid: 0, mode, follow: false });
|
|
15654
15902
|
}
|
|
15655
15903
|
}
|
|
15656
15904
|
async realLayoutPath(given) {
|
|
@@ -16395,7 +16643,7 @@ function dialStream(port, onClose) {
|
|
|
16395
16643
|
const writable2 = new WritableStream({
|
|
16396
16644
|
write(chunk2) {
|
|
16397
16645
|
if (closed) throw errorWithCode("EPIPE: the connection is closed");
|
|
16398
|
-
const copy = chunk2
|
|
16646
|
+
const copy = fresh(chunk2);
|
|
16399
16647
|
const acked = new Promise((resolve, reject) => acks.push({ resolve, reject }));
|
|
16400
16648
|
port.postMessage(copy, [copy.buffer]);
|
|
16401
16649
|
return acked;
|