@ai-ecoverse/slicc-kernel 1.96.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 +3 -1
- package/dist/index.js.map +2 -2
- 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/kernel-worker.js
CHANGED
|
@@ -7695,10 +7695,10 @@ function envOf(pkg, raw) {
|
|
|
7695
7695
|
}
|
|
7696
7696
|
return env;
|
|
7697
7697
|
}
|
|
7698
|
-
function envFields(
|
|
7698
|
+
function envFields(merged2) {
|
|
7699
7699
|
const env = {};
|
|
7700
7700
|
const unset = [];
|
|
7701
|
-
for (const [key, value] of Object.entries(
|
|
7701
|
+
for (const [key, value] of Object.entries(merged2)) {
|
|
7702
7702
|
if (value === null) unset.push(key);
|
|
7703
7703
|
else env[key] = value;
|
|
7704
7704
|
}
|
|
@@ -12054,7 +12054,7 @@ function mountTable(mounts = []) {
|
|
|
12054
12054
|
}
|
|
12055
12055
|
|
|
12056
12056
|
// src/version.ts
|
|
12057
|
-
var KERNEL_VERSION = true ? "1.
|
|
12057
|
+
var KERNEL_VERSION = true ? "1.97.1" : "0.0.0-dev";
|
|
12058
12058
|
var OS_RELEASE = "6.0.0-slicc";
|
|
12059
12059
|
function procVersion() {
|
|
12060
12060
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -12731,23 +12731,115 @@ async function epollSyscall(req, proc) {
|
|
|
12731
12731
|
}
|
|
12732
12732
|
}
|
|
12733
12733
|
|
|
12734
|
-
// src/kernel/
|
|
12735
|
-
var
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
"
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
"
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
"async-settle",
|
|
12745
|
-
"async-close"
|
|
12746
|
-
];
|
|
12747
|
-
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
12748
|
-
var done2 = { ok: true, kind: "void" };
|
|
12734
|
+
// src/kernel/locks.ts
|
|
12735
|
+
var overlaps = (a, b) => a.start < b.end && b.start < a.end;
|
|
12736
|
+
var clashes = (lock, owner, want) => lock.owner !== owner && overlaps(lock, want) && (lock.kind === "write" || want.kind === "write");
|
|
12737
|
+
function lockRange(start2, len) {
|
|
12738
|
+
if (!Number.isSafeInteger(start2) || !Number.isSafeInteger(len)) throw new KernelError("EINVAL");
|
|
12739
|
+
const from = len < 0 ? start2 + len : start2;
|
|
12740
|
+
const end = len === 0 ? Number.POSITIVE_INFINITY : len < 0 ? start2 : start2 + len;
|
|
12741
|
+
if (from < 0) throw new KernelError("EINVAL");
|
|
12742
|
+
return { start: from, end };
|
|
12743
|
+
}
|
|
12749
12744
|
var LockTable = class {
|
|
12745
|
+
records = /* @__PURE__ */ new Map();
|
|
12746
|
+
blocked = /* @__PURE__ */ new Map();
|
|
12747
|
+
wakers = /* @__PURE__ */ new Map();
|
|
12750
12748
|
held = /* @__PURE__ */ new Map();
|
|
12749
|
+
holder(key, owner, want) {
|
|
12750
|
+
return this.records.get(key)?.find((lock) => clashes(lock, owner, want));
|
|
12751
|
+
}
|
|
12752
|
+
set(key, owner, kind, start2, end) {
|
|
12753
|
+
if (kind !== "unlock" && this.holder(key, owner, { key, kind, start: start2, end })) return false;
|
|
12754
|
+
const range = { start: start2, end };
|
|
12755
|
+
const kept = [];
|
|
12756
|
+
for (const lock of this.records.get(key) ?? []) {
|
|
12757
|
+
if (lock.owner !== owner || !overlaps(lock, range)) kept.push(lock);
|
|
12758
|
+
else {
|
|
12759
|
+
if (lock.start < start2) kept.push({ ...lock, end: start2 });
|
|
12760
|
+
if (lock.end > end) kept.push({ ...lock, start: end });
|
|
12761
|
+
}
|
|
12762
|
+
}
|
|
12763
|
+
if (kind !== "unlock") kept.push({ owner, kind, start: start2, end });
|
|
12764
|
+
this.store(key, merged(kept));
|
|
12765
|
+
this.wake(key);
|
|
12766
|
+
return true;
|
|
12767
|
+
}
|
|
12768
|
+
async wait(key, owner, kind, range, blocking) {
|
|
12769
|
+
const want = { key, kind, ...range };
|
|
12770
|
+
let signal;
|
|
12771
|
+
for (; ; ) {
|
|
12772
|
+
const holder = this.holder(key, owner, want);
|
|
12773
|
+
if (!holder) {
|
|
12774
|
+
this.set(key, owner, kind, range.start, range.end);
|
|
12775
|
+
return;
|
|
12776
|
+
}
|
|
12777
|
+
if (this.waitsOn(holder.owner, owner)) throw new KernelError("EDEADLK");
|
|
12778
|
+
signal ??= blocking();
|
|
12779
|
+
if (signal.aborted) throw new KernelError("EINTR");
|
|
12780
|
+
this.blocked.set(owner, want);
|
|
12781
|
+
try {
|
|
12782
|
+
await this.changed(key, signal);
|
|
12783
|
+
} finally {
|
|
12784
|
+
this.blocked.delete(owner);
|
|
12785
|
+
}
|
|
12786
|
+
}
|
|
12787
|
+
}
|
|
12788
|
+
waitsOn(from, target) {
|
|
12789
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12790
|
+
for (let at = from; at !== void 0 && !seen.has(at); ) {
|
|
12791
|
+
seen.add(at);
|
|
12792
|
+
const want = this.blocked.get(at);
|
|
12793
|
+
if (!want) return false;
|
|
12794
|
+
const holder = this.holder(want.key, at, want);
|
|
12795
|
+
if (!holder) return false;
|
|
12796
|
+
if (holder.owner === target) return true;
|
|
12797
|
+
at = holder.owner;
|
|
12798
|
+
}
|
|
12799
|
+
return false;
|
|
12800
|
+
}
|
|
12801
|
+
changed(key, signal) {
|
|
12802
|
+
return new Promise((resolve2, reject) => {
|
|
12803
|
+
const set2 = this.wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
12804
|
+
this.wakers.set(key, set2);
|
|
12805
|
+
const done4 = () => {
|
|
12806
|
+
set2.delete(wake);
|
|
12807
|
+
if (set2.size === 0 && this.wakers.get(key) === set2) this.wakers.delete(key);
|
|
12808
|
+
signal.removeEventListener("abort", abort);
|
|
12809
|
+
};
|
|
12810
|
+
const wake = () => {
|
|
12811
|
+
done4();
|
|
12812
|
+
resolve2();
|
|
12813
|
+
};
|
|
12814
|
+
const abort = () => {
|
|
12815
|
+
done4();
|
|
12816
|
+
reject(new KernelError("EINTR"));
|
|
12817
|
+
};
|
|
12818
|
+
set2.add(wake);
|
|
12819
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
12820
|
+
});
|
|
12821
|
+
}
|
|
12822
|
+
wake(key) {
|
|
12823
|
+
for (const wake of [...this.wakers.get(key) ?? []]) wake();
|
|
12824
|
+
}
|
|
12825
|
+
store(key, locks) {
|
|
12826
|
+
if (locks.length === 0) this.records.delete(key);
|
|
12827
|
+
else this.records.set(key, locks);
|
|
12828
|
+
}
|
|
12829
|
+
holds(owner) {
|
|
12830
|
+
for (const locks of this.records.values())
|
|
12831
|
+
if (locks.some((l) => l.owner === owner)) return true;
|
|
12832
|
+
return false;
|
|
12833
|
+
}
|
|
12834
|
+
dropFile(key, owner) {
|
|
12835
|
+
const locks = this.records.get(key);
|
|
12836
|
+
if (!locks?.some((l) => l.owner === owner)) return;
|
|
12837
|
+
this.store(
|
|
12838
|
+
key,
|
|
12839
|
+
locks.filter((l) => l.owner !== owner)
|
|
12840
|
+
);
|
|
12841
|
+
this.wake(key);
|
|
12842
|
+
}
|
|
12751
12843
|
lock(pid, path, exclusive, fd) {
|
|
12752
12844
|
const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
|
|
12753
12845
|
for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
@@ -12771,8 +12863,39 @@ var LockTable = class {
|
|
|
12771
12863
|
}
|
|
12772
12864
|
release(pid) {
|
|
12773
12865
|
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
12866
|
+
for (const key of [...this.records.keys()]) this.dropFile(key, pid);
|
|
12774
12867
|
}
|
|
12775
12868
|
};
|
|
12869
|
+
function merged(locks) {
|
|
12870
|
+
const sorted = [...locks].sort((a, b) => a.owner - b.owner || a.start - b.start);
|
|
12871
|
+
const out = [];
|
|
12872
|
+
for (const lock of sorted) {
|
|
12873
|
+
const last = out[out.length - 1];
|
|
12874
|
+
if (last && last.owner === lock.owner && last.kind === lock.kind && last.end >= lock.start) {
|
|
12875
|
+
last.end = Math.max(last.end, lock.end);
|
|
12876
|
+
} else out.push({ ...lock });
|
|
12877
|
+
}
|
|
12878
|
+
return out;
|
|
12879
|
+
}
|
|
12880
|
+
|
|
12881
|
+
// src/kernel/host-ops.ts
|
|
12882
|
+
var HOST_OPS = [
|
|
12883
|
+
"lock",
|
|
12884
|
+
"unlock",
|
|
12885
|
+
"lk-set",
|
|
12886
|
+
"lk-get",
|
|
12887
|
+
"lk-close",
|
|
12888
|
+
"async-submit",
|
|
12889
|
+
"async-wait",
|
|
12890
|
+
"async-take",
|
|
12891
|
+
"async-resolve",
|
|
12892
|
+
"async-hold",
|
|
12893
|
+
"async-cancel",
|
|
12894
|
+
"async-settle",
|
|
12895
|
+
"async-close"
|
|
12896
|
+
];
|
|
12897
|
+
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
12898
|
+
var done2 = { ok: true, kind: "void" };
|
|
12776
12899
|
var KEPT_OPS = /* @__PURE__ */ new Set(["fd-write"]);
|
|
12777
12900
|
var unknownSettled = false;
|
|
12778
12901
|
var AsyncOps = class {
|
|
@@ -12909,6 +13032,10 @@ async function hostSyscall(req, ctx) {
|
|
|
12909
13032
|
case "unlock":
|
|
12910
13033
|
ctx.locks?.unlock(ctx.pid, req.path);
|
|
12911
13034
|
return done2;
|
|
13035
|
+
case "lk-set":
|
|
13036
|
+
case "lk-get":
|
|
13037
|
+
case "lk-close":
|
|
13038
|
+
return recordLock2(req, ctx);
|
|
12912
13039
|
case "async-submit":
|
|
12913
13040
|
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
12914
13041
|
if (req.ack) ctx.ops.ack(req.ack);
|
|
@@ -12931,6 +13058,33 @@ async function hostSyscall(req, ctx) {
|
|
|
12931
13058
|
return done2;
|
|
12932
13059
|
}
|
|
12933
13060
|
}
|
|
13061
|
+
async function recordLock2(req, ctx) {
|
|
13062
|
+
const { locks, fileKey } = ctx;
|
|
13063
|
+
if (!locks || !fileKey) throw new KernelError("ENOLCK");
|
|
13064
|
+
const owner = ctx.owner?.() ?? ctx.pid;
|
|
13065
|
+
const target = {
|
|
13066
|
+
...req.path !== void 0 ? { path: req.path } : {},
|
|
13067
|
+
...req.fd !== void 0 ? { fd: req.fd } : {}
|
|
13068
|
+
};
|
|
13069
|
+
if (req.op === "lk-close") {
|
|
13070
|
+
locks.dropFile(await fileKey(target, "close"), owner);
|
|
13071
|
+
return done2;
|
|
13072
|
+
}
|
|
13073
|
+
const range = lockRange(req.start, req.len);
|
|
13074
|
+
const key = await fileKey(target, req.kind);
|
|
13075
|
+
if (req.op === "lk-get") {
|
|
13076
|
+
const held = locks.holder(key, owner, { key, kind: req.kind, ...range });
|
|
13077
|
+
if (!held) return json3(null);
|
|
13078
|
+
const len = held.end === Number.POSITIVE_INFINITY ? 0 : held.end - held.start;
|
|
13079
|
+
return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
|
|
13080
|
+
}
|
|
13081
|
+
if (req.kind !== "unlock" && req.wait) {
|
|
13082
|
+
await locks.wait(key, owner, req.kind, range, ctx.blocking);
|
|
13083
|
+
return done2;
|
|
13084
|
+
}
|
|
13085
|
+
if (!locks.set(key, owner, req.kind, range.start, range.end)) throw new KernelError("EAGAIN");
|
|
13086
|
+
return done2;
|
|
13087
|
+
}
|
|
12934
13088
|
|
|
12935
13089
|
// src/kernel/net/loopback-transport.ts
|
|
12936
13090
|
var LOOPBACK_TRAITS = {
|
|
@@ -15461,6 +15615,8 @@ var WasmProcess = class {
|
|
|
15461
15615
|
if (isHostSyscall(req)) {
|
|
15462
15616
|
return await hostSyscall(req, {
|
|
15463
15617
|
pid: this.pid,
|
|
15618
|
+
owner: () => this.lockOwner(),
|
|
15619
|
+
fileKey: (target, kind) => this.lockKey(target, kind),
|
|
15464
15620
|
locks: this.options.locks,
|
|
15465
15621
|
ops: this.asyncOps,
|
|
15466
15622
|
blocking: () => this.blockingSignal(cancelled),
|
|
@@ -15487,6 +15643,44 @@ var WasmProcess = class {
|
|
|
15487
15643
|
throw e;
|
|
15488
15644
|
}
|
|
15489
15645
|
}
|
|
15646
|
+
lockOwners = /* @__PURE__ */ new Set();
|
|
15647
|
+
lockChecked = /* @__PURE__ */ new Set();
|
|
15648
|
+
lockOwner() {
|
|
15649
|
+
const owner = this.options.jobs?.shown(this.pid) ?? this.pid;
|
|
15650
|
+
this.lockOwners.add(owner);
|
|
15651
|
+
return owner;
|
|
15652
|
+
}
|
|
15653
|
+
async lockPath(target, want) {
|
|
15654
|
+
if (target.fd !== void 0) {
|
|
15655
|
+
const st = await this.fds.get(target.fd).file.stat?.();
|
|
15656
|
+
if (!st || st.orphan) throw new KernelError("EBADF");
|
|
15657
|
+
return st.path;
|
|
15658
|
+
}
|
|
15659
|
+
if (target.path === void 0) throw new KernelError("EINVAL");
|
|
15660
|
+
if (!target.path.startsWith("/")) throw new KernelError("EINVAL");
|
|
15661
|
+
const path = target.path;
|
|
15662
|
+
const g = this.guarded();
|
|
15663
|
+
const checked = `${want}:${path}`;
|
|
15664
|
+
if (g && want !== 0 && !this.lockChecked.has(checked)) {
|
|
15665
|
+
await openable(g, "lock", path, want, false);
|
|
15666
|
+
this.lockChecked.add(checked);
|
|
15667
|
+
}
|
|
15668
|
+
return path;
|
|
15669
|
+
}
|
|
15670
|
+
async lockKey(target, kind) {
|
|
15671
|
+
const want = kind === "read" ? R_OK : kind === "write" ? W_OK : 0;
|
|
15672
|
+
const path = await this.lockPath(target, want);
|
|
15673
|
+
const st = await this.options.fs.stat?.(path);
|
|
15674
|
+
if (!st) throw new KernelError("ENOENT");
|
|
15675
|
+
return st.ino === void 0 ? path : `${st.dev ?? 0}:${st.ino}`;
|
|
15676
|
+
}
|
|
15677
|
+
async dropRecordLocks(fd) {
|
|
15678
|
+
const { locks } = this.options;
|
|
15679
|
+
const owner = this.options.jobs?.shown(this.pid) ?? this.pid;
|
|
15680
|
+
if (!locks?.holds(owner) || !this.fds.has(fd)) return;
|
|
15681
|
+
const key = await this.lockKey({ fd }, "close").catch(() => void 0);
|
|
15682
|
+
if (key !== void 0) locks.dropFile(key, owner);
|
|
15683
|
+
}
|
|
15490
15684
|
refuseIfPending(restart) {
|
|
15491
15685
|
if (restart && this.options.hasPending?.()) throw new KernelError("EINTR");
|
|
15492
15686
|
}
|
|
@@ -15798,6 +15992,7 @@ var WasmProcess = class {
|
|
|
15798
15992
|
};
|
|
15799
15993
|
case "fd-close": {
|
|
15800
15994
|
this.options.locks?.closed(this.pid, req.fd);
|
|
15995
|
+
await this.dropRecordLocks(req.fd);
|
|
15801
15996
|
const channel = this.fds.get(req.fd).file.clipboard;
|
|
15802
15997
|
if (channel) channel.stamp = await this.clipboardStamp();
|
|
15803
15998
|
await Promise.resolve(this.fds.close(req.fd)).catch(async (err) => {
|
|
@@ -16390,6 +16585,7 @@ var WasmProcess = class {
|
|
|
16390
16585
|
this.clearAlarm();
|
|
16391
16586
|
this.interrupt.abort();
|
|
16392
16587
|
this.options.locks?.release(this.pid);
|
|
16588
|
+
for (const owner of this.lockOwners) this.options.locks?.release(owner);
|
|
16393
16589
|
this.asyncOps.close();
|
|
16394
16590
|
for (const [target, sig] of this.deathSignals) this.sendDeath(target, sig);
|
|
16395
16591
|
this.deathSignals.clear();
|