@ai-ecoverse/slicc-kernel 1.97.0 → 1.97.1
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 -1
- package/dist/kernel-worker.js +214 -18
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +221 -67
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +218 -22
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +232 -78
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -6168,10 +6168,10 @@ function envOf(pkg, raw) {
|
|
|
6168
6168
|
}
|
|
6169
6169
|
return env;
|
|
6170
6170
|
}
|
|
6171
|
-
function envFields(
|
|
6171
|
+
function envFields(merged2) {
|
|
6172
6172
|
const env = {};
|
|
6173
6173
|
const unset = [];
|
|
6174
|
-
for (const [key, value] of Object.entries(
|
|
6174
|
+
for (const [key, value] of Object.entries(merged2)) {
|
|
6175
6175
|
if (value === null) unset.push(key);
|
|
6176
6176
|
else env[key] = value;
|
|
6177
6177
|
}
|
|
@@ -11047,7 +11047,7 @@ function mountTable(mounts = []) {
|
|
|
11047
11047
|
}
|
|
11048
11048
|
|
|
11049
11049
|
// src/version.ts
|
|
11050
|
-
var KERNEL_VERSION = true ? "1.97.
|
|
11050
|
+
var KERNEL_VERSION = true ? "1.97.1" : "0.0.0-dev";
|
|
11051
11051
|
var OS_RELEASE = "6.0.0-slicc";
|
|
11052
11052
|
function procVersion() {
|
|
11053
11053
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -11724,23 +11724,115 @@ async function epollSyscall(req, proc) {
|
|
|
11724
11724
|
}
|
|
11725
11725
|
}
|
|
11726
11726
|
|
|
11727
|
-
// src/kernel/
|
|
11728
|
-
var
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
"
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
"
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
"async-settle",
|
|
11738
|
-
"async-close"
|
|
11739
|
-
];
|
|
11740
|
-
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
11741
|
-
var done2 = { ok: true, kind: "void" };
|
|
11727
|
+
// src/kernel/locks.ts
|
|
11728
|
+
var overlaps = (a, b) => a.start < b.end && b.start < a.end;
|
|
11729
|
+
var clashes = (lock, owner, want) => lock.owner !== owner && overlaps(lock, want) && (lock.kind === "write" || want.kind === "write");
|
|
11730
|
+
function lockRange(start2, len) {
|
|
11731
|
+
if (!Number.isSafeInteger(start2) || !Number.isSafeInteger(len)) throw new KernelError("EINVAL");
|
|
11732
|
+
const from = len < 0 ? start2 + len : start2;
|
|
11733
|
+
const end = len === 0 ? Number.POSITIVE_INFINITY : len < 0 ? start2 : start2 + len;
|
|
11734
|
+
if (from < 0) throw new KernelError("EINVAL");
|
|
11735
|
+
return { start: from, end };
|
|
11736
|
+
}
|
|
11742
11737
|
var LockTable = class {
|
|
11738
|
+
records = /* @__PURE__ */ new Map();
|
|
11739
|
+
blocked = /* @__PURE__ */ new Map();
|
|
11740
|
+
wakers = /* @__PURE__ */ new Map();
|
|
11743
11741
|
held = /* @__PURE__ */ new Map();
|
|
11742
|
+
holder(key, owner, want) {
|
|
11743
|
+
return this.records.get(key)?.find((lock) => clashes(lock, owner, want));
|
|
11744
|
+
}
|
|
11745
|
+
set(key, owner, kind, start2, end) {
|
|
11746
|
+
if (kind !== "unlock" && this.holder(key, owner, { key, kind, start: start2, end })) return false;
|
|
11747
|
+
const range = { start: start2, end };
|
|
11748
|
+
const kept = [];
|
|
11749
|
+
for (const lock of this.records.get(key) ?? []) {
|
|
11750
|
+
if (lock.owner !== owner || !overlaps(lock, range)) kept.push(lock);
|
|
11751
|
+
else {
|
|
11752
|
+
if (lock.start < start2) kept.push({ ...lock, end: start2 });
|
|
11753
|
+
if (lock.end > end) kept.push({ ...lock, start: end });
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11756
|
+
if (kind !== "unlock") kept.push({ owner, kind, start: start2, end });
|
|
11757
|
+
this.store(key, merged(kept));
|
|
11758
|
+
this.wake(key);
|
|
11759
|
+
return true;
|
|
11760
|
+
}
|
|
11761
|
+
async wait(key, owner, kind, range, blocking) {
|
|
11762
|
+
const want = { key, kind, ...range };
|
|
11763
|
+
let signal;
|
|
11764
|
+
for (; ; ) {
|
|
11765
|
+
const holder = this.holder(key, owner, want);
|
|
11766
|
+
if (!holder) {
|
|
11767
|
+
this.set(key, owner, kind, range.start, range.end);
|
|
11768
|
+
return;
|
|
11769
|
+
}
|
|
11770
|
+
if (this.waitsOn(holder.owner, owner)) throw new KernelError("EDEADLK");
|
|
11771
|
+
signal ??= blocking();
|
|
11772
|
+
if (signal.aborted) throw new KernelError("EINTR");
|
|
11773
|
+
this.blocked.set(owner, want);
|
|
11774
|
+
try {
|
|
11775
|
+
await this.changed(key, signal);
|
|
11776
|
+
} finally {
|
|
11777
|
+
this.blocked.delete(owner);
|
|
11778
|
+
}
|
|
11779
|
+
}
|
|
11780
|
+
}
|
|
11781
|
+
waitsOn(from, target) {
|
|
11782
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11783
|
+
for (let at = from; at !== void 0 && !seen.has(at); ) {
|
|
11784
|
+
seen.add(at);
|
|
11785
|
+
const want = this.blocked.get(at);
|
|
11786
|
+
if (!want) return false;
|
|
11787
|
+
const holder = this.holder(want.key, at, want);
|
|
11788
|
+
if (!holder) return false;
|
|
11789
|
+
if (holder.owner === target) return true;
|
|
11790
|
+
at = holder.owner;
|
|
11791
|
+
}
|
|
11792
|
+
return false;
|
|
11793
|
+
}
|
|
11794
|
+
changed(key, signal) {
|
|
11795
|
+
return new Promise((resolve2, reject) => {
|
|
11796
|
+
const set2 = this.wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
11797
|
+
this.wakers.set(key, set2);
|
|
11798
|
+
const done4 = () => {
|
|
11799
|
+
set2.delete(wake);
|
|
11800
|
+
if (set2.size === 0 && this.wakers.get(key) === set2) this.wakers.delete(key);
|
|
11801
|
+
signal.removeEventListener("abort", abort);
|
|
11802
|
+
};
|
|
11803
|
+
const wake = () => {
|
|
11804
|
+
done4();
|
|
11805
|
+
resolve2();
|
|
11806
|
+
};
|
|
11807
|
+
const abort = () => {
|
|
11808
|
+
done4();
|
|
11809
|
+
reject(new KernelError("EINTR"));
|
|
11810
|
+
};
|
|
11811
|
+
set2.add(wake);
|
|
11812
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
11813
|
+
});
|
|
11814
|
+
}
|
|
11815
|
+
wake(key) {
|
|
11816
|
+
for (const wake of [...this.wakers.get(key) ?? []]) wake();
|
|
11817
|
+
}
|
|
11818
|
+
store(key, locks) {
|
|
11819
|
+
if (locks.length === 0) this.records.delete(key);
|
|
11820
|
+
else this.records.set(key, locks);
|
|
11821
|
+
}
|
|
11822
|
+
holds(owner) {
|
|
11823
|
+
for (const locks of this.records.values())
|
|
11824
|
+
if (locks.some((l) => l.owner === owner)) return true;
|
|
11825
|
+
return false;
|
|
11826
|
+
}
|
|
11827
|
+
dropFile(key, owner) {
|
|
11828
|
+
const locks = this.records.get(key);
|
|
11829
|
+
if (!locks?.some((l) => l.owner === owner)) return;
|
|
11830
|
+
this.store(
|
|
11831
|
+
key,
|
|
11832
|
+
locks.filter((l) => l.owner !== owner)
|
|
11833
|
+
);
|
|
11834
|
+
this.wake(key);
|
|
11835
|
+
}
|
|
11744
11836
|
lock(pid, path, exclusive, fd) {
|
|
11745
11837
|
const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
|
|
11746
11838
|
for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
@@ -11764,8 +11856,39 @@ var LockTable = class {
|
|
|
11764
11856
|
}
|
|
11765
11857
|
release(pid) {
|
|
11766
11858
|
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
11859
|
+
for (const key of [...this.records.keys()]) this.dropFile(key, pid);
|
|
11767
11860
|
}
|
|
11768
11861
|
};
|
|
11862
|
+
function merged(locks) {
|
|
11863
|
+
const sorted = [...locks].sort((a, b) => a.owner - b.owner || a.start - b.start);
|
|
11864
|
+
const out = [];
|
|
11865
|
+
for (const lock of sorted) {
|
|
11866
|
+
const last = out[out.length - 1];
|
|
11867
|
+
if (last && last.owner === lock.owner && last.kind === lock.kind && last.end >= lock.start) {
|
|
11868
|
+
last.end = Math.max(last.end, lock.end);
|
|
11869
|
+
} else out.push({ ...lock });
|
|
11870
|
+
}
|
|
11871
|
+
return out;
|
|
11872
|
+
}
|
|
11873
|
+
|
|
11874
|
+
// src/kernel/host-ops.ts
|
|
11875
|
+
var HOST_OPS = [
|
|
11876
|
+
"lock",
|
|
11877
|
+
"unlock",
|
|
11878
|
+
"lk-set",
|
|
11879
|
+
"lk-get",
|
|
11880
|
+
"lk-close",
|
|
11881
|
+
"async-submit",
|
|
11882
|
+
"async-wait",
|
|
11883
|
+
"async-take",
|
|
11884
|
+
"async-resolve",
|
|
11885
|
+
"async-hold",
|
|
11886
|
+
"async-cancel",
|
|
11887
|
+
"async-settle",
|
|
11888
|
+
"async-close"
|
|
11889
|
+
];
|
|
11890
|
+
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
11891
|
+
var done2 = { ok: true, kind: "void" };
|
|
11769
11892
|
var KEPT_OPS = /* @__PURE__ */ new Set(["fd-write"]);
|
|
11770
11893
|
var unknownSettled = false;
|
|
11771
11894
|
var AsyncOps = class {
|
|
@@ -11902,6 +12025,10 @@ async function hostSyscall(req, ctx) {
|
|
|
11902
12025
|
case "unlock":
|
|
11903
12026
|
ctx.locks?.unlock(ctx.pid, req.path);
|
|
11904
12027
|
return done2;
|
|
12028
|
+
case "lk-set":
|
|
12029
|
+
case "lk-get":
|
|
12030
|
+
case "lk-close":
|
|
12031
|
+
return recordLock2(req, ctx);
|
|
11905
12032
|
case "async-submit":
|
|
11906
12033
|
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
11907
12034
|
if (req.ack) ctx.ops.ack(req.ack);
|
|
@@ -11924,6 +12051,33 @@ async function hostSyscall(req, ctx) {
|
|
|
11924
12051
|
return done2;
|
|
11925
12052
|
}
|
|
11926
12053
|
}
|
|
12054
|
+
async function recordLock2(req, ctx) {
|
|
12055
|
+
const { locks, fileKey } = ctx;
|
|
12056
|
+
if (!locks || !fileKey) throw new KernelError("ENOLCK");
|
|
12057
|
+
const owner = ctx.owner?.() ?? ctx.pid;
|
|
12058
|
+
const target = {
|
|
12059
|
+
...req.path !== void 0 ? { path: req.path } : {},
|
|
12060
|
+
...req.fd !== void 0 ? { fd: req.fd } : {}
|
|
12061
|
+
};
|
|
12062
|
+
if (req.op === "lk-close") {
|
|
12063
|
+
locks.dropFile(await fileKey(target, "close"), owner);
|
|
12064
|
+
return done2;
|
|
12065
|
+
}
|
|
12066
|
+
const range = lockRange(req.start, req.len);
|
|
12067
|
+
const key = await fileKey(target, req.kind);
|
|
12068
|
+
if (req.op === "lk-get") {
|
|
12069
|
+
const held = locks.holder(key, owner, { key, kind: req.kind, ...range });
|
|
12070
|
+
if (!held) return json3(null);
|
|
12071
|
+
const len = held.end === Number.POSITIVE_INFINITY ? 0 : held.end - held.start;
|
|
12072
|
+
return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
|
|
12073
|
+
}
|
|
12074
|
+
if (req.kind !== "unlock" && req.wait) {
|
|
12075
|
+
await locks.wait(key, owner, req.kind, range, ctx.blocking);
|
|
12076
|
+
return done2;
|
|
12077
|
+
}
|
|
12078
|
+
if (!locks.set(key, owner, req.kind, range.start, range.end)) throw new KernelError("EAGAIN");
|
|
12079
|
+
return done2;
|
|
12080
|
+
}
|
|
11927
12081
|
|
|
11928
12082
|
// src/kernel/net/loopback-transport.ts
|
|
11929
12083
|
var LOOPBACK_TRAITS = {
|
|
@@ -15118,6 +15272,8 @@ var WasmProcess = class {
|
|
|
15118
15272
|
if (isHostSyscall(req)) {
|
|
15119
15273
|
return await hostSyscall(req, {
|
|
15120
15274
|
pid: this.pid,
|
|
15275
|
+
owner: () => this.lockOwner(),
|
|
15276
|
+
fileKey: (target, kind) => this.lockKey(target, kind),
|
|
15121
15277
|
locks: this.options.locks,
|
|
15122
15278
|
ops: this.asyncOps,
|
|
15123
15279
|
blocking: () => this.blockingSignal(cancelled),
|
|
@@ -15144,6 +15300,44 @@ var WasmProcess = class {
|
|
|
15144
15300
|
throw e;
|
|
15145
15301
|
}
|
|
15146
15302
|
}
|
|
15303
|
+
lockOwners = /* @__PURE__ */ new Set();
|
|
15304
|
+
lockChecked = /* @__PURE__ */ new Set();
|
|
15305
|
+
lockOwner() {
|
|
15306
|
+
const owner = this.options.jobs?.shown(this.pid) ?? this.pid;
|
|
15307
|
+
this.lockOwners.add(owner);
|
|
15308
|
+
return owner;
|
|
15309
|
+
}
|
|
15310
|
+
async lockPath(target, want) {
|
|
15311
|
+
if (target.fd !== void 0) {
|
|
15312
|
+
const st = await this.fds.get(target.fd).file.stat?.();
|
|
15313
|
+
if (!st || st.orphan) throw new KernelError("EBADF");
|
|
15314
|
+
return st.path;
|
|
15315
|
+
}
|
|
15316
|
+
if (target.path === void 0) throw new KernelError("EINVAL");
|
|
15317
|
+
if (!target.path.startsWith("/")) throw new KernelError("EINVAL");
|
|
15318
|
+
const path = target.path;
|
|
15319
|
+
const g = this.guarded();
|
|
15320
|
+
const checked = `${want}:${path}`;
|
|
15321
|
+
if (g && want !== 0 && !this.lockChecked.has(checked)) {
|
|
15322
|
+
await openable(g, "lock", path, want, false);
|
|
15323
|
+
this.lockChecked.add(checked);
|
|
15324
|
+
}
|
|
15325
|
+
return path;
|
|
15326
|
+
}
|
|
15327
|
+
async lockKey(target, kind) {
|
|
15328
|
+
const want = kind === "read" ? R_OK : kind === "write" ? W_OK : 0;
|
|
15329
|
+
const path = await this.lockPath(target, want);
|
|
15330
|
+
const st = await this.options.fs.stat?.(path);
|
|
15331
|
+
if (!st) throw new KernelError("ENOENT");
|
|
15332
|
+
return st.ino === void 0 ? path : `${st.dev ?? 0}:${st.ino}`;
|
|
15333
|
+
}
|
|
15334
|
+
async dropRecordLocks(fd) {
|
|
15335
|
+
const { locks } = this.options;
|
|
15336
|
+
const owner = this.options.jobs?.shown(this.pid) ?? this.pid;
|
|
15337
|
+
if (!locks?.holds(owner) || !this.fds.has(fd)) return;
|
|
15338
|
+
const key = await this.lockKey({ fd }, "close").catch(() => void 0);
|
|
15339
|
+
if (key !== void 0) locks.dropFile(key, owner);
|
|
15340
|
+
}
|
|
15147
15341
|
refuseIfPending(restart) {
|
|
15148
15342
|
if (restart && this.options.hasPending?.()) throw new KernelError("EINTR");
|
|
15149
15343
|
}
|
|
@@ -15455,6 +15649,7 @@ var WasmProcess = class {
|
|
|
15455
15649
|
};
|
|
15456
15650
|
case "fd-close": {
|
|
15457
15651
|
this.options.locks?.closed(this.pid, req.fd);
|
|
15652
|
+
await this.dropRecordLocks(req.fd);
|
|
15458
15653
|
const channel = this.fds.get(req.fd).file.clipboard;
|
|
15459
15654
|
if (channel) channel.stamp = await this.clipboardStamp();
|
|
15460
15655
|
await Promise.resolve(this.fds.close(req.fd)).catch(async (err) => {
|
|
@@ -16047,6 +16242,7 @@ var WasmProcess = class {
|
|
|
16047
16242
|
this.clearAlarm();
|
|
16048
16243
|
this.interrupt.abort();
|
|
16049
16244
|
this.options.locks?.release(this.pid);
|
|
16245
|
+
for (const owner of this.lockOwners) this.options.locks?.release(owner);
|
|
16050
16246
|
this.asyncOps.close();
|
|
16051
16247
|
for (const [target, sig] of this.deathSignals) this.sendDeath(target, sig);
|
|
16052
16248
|
this.deathSignals.clear();
|
|
@@ -21952,10 +22148,10 @@ var Chunks = class {
|
|
|
21952
22148
|
const old = this.blobs[index];
|
|
21953
22149
|
if (from === 0 && n >= (old?.size ?? 0)) this.blobs[index] = new Blob([part]);
|
|
21954
22150
|
else {
|
|
21955
|
-
const
|
|
21956
|
-
if (old)
|
|
21957
|
-
|
|
21958
|
-
this.blobs[index] = new Blob([
|
|
22151
|
+
const merged2 = new Uint8Array(Math.max(old?.size ?? 0, from + n));
|
|
22152
|
+
if (old) merged2.set(new Uint8Array(await old.arrayBuffer()));
|
|
22153
|
+
merged2.set(part, from);
|
|
22154
|
+
this.blobs[index] = new Blob([merged2]);
|
|
21959
22155
|
}
|
|
21960
22156
|
done4 += n;
|
|
21961
22157
|
}
|