@ai-ecoverse/slicc-kernel 1.118.0 → 1.119.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 +13 -4
- package/dist/index.js.map +1 -1
- package/dist/kernel-worker.js +357 -6
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-process-worker.js +5 -1
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +357 -6
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +5 -1
- package/dist/process-worker.js.map +2 -2
- package/dist/types/fs/opfs.d.ts +1 -0
- package/dist/types/fs/types.d.ts +1 -0
- package/dist/types/kernel/host-ops.d.ts +3 -2
- package/dist/types/kernel/host.d.ts +2 -2
- package/dist/types/kernel/lock-service.d.ts +92 -0
- package/dist/types/kernel/locks.d.ts +2 -0
- package/dist/types/kernel/process.d.ts +3 -2
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -4303,12 +4303,14 @@ var OpfsFs = class {
|
|
|
4303
4303
|
mounts = {};
|
|
4304
4304
|
locks;
|
|
4305
4305
|
lockPrefix;
|
|
4306
|
+
rootName;
|
|
4306
4307
|
constructor(root, meta = new MemoryMeta(), channel, options = {}) {
|
|
4307
4308
|
this.root = root;
|
|
4308
4309
|
this.meta = sidecar(meta);
|
|
4309
4310
|
this.ranged = options.ranged === true;
|
|
4310
4311
|
this.locks = options.locks === void 0 ? lockManager() : options.locks ?? void 0;
|
|
4311
4312
|
this.lockPrefix = `slicc-excl:${channel ?? ""}:`;
|
|
4313
|
+
this.rootName = channel;
|
|
4312
4314
|
this.channel = channel === void 0 ? void 0 : new BroadcastChannel(channel);
|
|
4313
4315
|
this.remote = channel === void 0 ? void 0 : new RemoteWatch(`${channel}:watch`);
|
|
4314
4316
|
if (this.remote) this.remote.quiet = () => this.quiet();
|
|
@@ -6735,7 +6737,7 @@ function satisfies(version, range2) {
|
|
|
6735
6737
|
}
|
|
6736
6738
|
|
|
6737
6739
|
// src/version.ts
|
|
6738
|
-
var KERNEL_VERSION = true ? "1.
|
|
6740
|
+
var KERNEL_VERSION = true ? "1.119.0" : "0.0.0-dev";
|
|
6739
6741
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6740
6742
|
function procVersion() {
|
|
6741
6743
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -13398,6 +13400,12 @@ var FlockTable = class {
|
|
|
13398
13400
|
await changedAt(this.wakers, key, signal);
|
|
13399
13401
|
}
|
|
13400
13402
|
}
|
|
13403
|
+
entries() {
|
|
13404
|
+
const out = [];
|
|
13405
|
+
for (const [key, holders] of this.held)
|
|
13406
|
+
for (const [owner, kind] of holders) out.push([key, owner, kind]);
|
|
13407
|
+
return out;
|
|
13408
|
+
}
|
|
13401
13409
|
drop(owner) {
|
|
13402
13410
|
const key = this.keys.get(owner);
|
|
13403
13411
|
if (key === void 0) return;
|
|
@@ -13476,6 +13484,9 @@ var LockTable = class {
|
|
|
13476
13484
|
if (locks.length === 0) this.records.delete(key);
|
|
13477
13485
|
else this.records.set(key, locks);
|
|
13478
13486
|
}
|
|
13487
|
+
entries() {
|
|
13488
|
+
return [...this.records].map(([key, locks]) => [key, locks.map((l) => ({ ...l }))]);
|
|
13489
|
+
}
|
|
13479
13490
|
holds(owner) {
|
|
13480
13491
|
for (const locks of this.records.values())
|
|
13481
13492
|
if (locks.some((l) => l.owner === owner)) return true;
|
|
@@ -13720,7 +13731,7 @@ async function flock(req, ctx) {
|
|
|
13720
13731
|
const { key, owner } = await flockOf(req.fd);
|
|
13721
13732
|
if (req.kind !== "unlock" && req.wait)
|
|
13722
13733
|
await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
|
|
13723
|
-
else if (!locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
13734
|
+
else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
13724
13735
|
return done2;
|
|
13725
13736
|
}
|
|
13726
13737
|
async function recordLock2(req, ctx) {
|
|
@@ -13738,7 +13749,7 @@ async function recordLock2(req, ctx) {
|
|
|
13738
13749
|
const range2 = lockRange(req.start, req.len);
|
|
13739
13750
|
const key = await fileKey(target, req.kind, req.op === "lk-set" && req.fd !== void 0);
|
|
13740
13751
|
if (req.op === "lk-get") {
|
|
13741
|
-
const held = locks.holder(key, owner, { key, kind: req.kind, ...range2 });
|
|
13752
|
+
const held = await locks.holder(key, owner, { key, kind: req.kind, ...range2 });
|
|
13742
13753
|
if (!held) return json3(null);
|
|
13743
13754
|
const len = held.end === Number.POSITIVE_INFINITY ? 0 : held.end - held.start;
|
|
13744
13755
|
return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
|
|
@@ -13747,7 +13758,8 @@ async function recordLock2(req, ctx) {
|
|
|
13747
13758
|
await locks.wait(key, owner, req.kind, range2, ctx.blocking);
|
|
13748
13759
|
return done2;
|
|
13749
13760
|
}
|
|
13750
|
-
if (!locks.set(key, owner, req.kind, range2.start, range2.end))
|
|
13761
|
+
if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
|
|
13762
|
+
throw new KernelError("EAGAIN");
|
|
13751
13763
|
return done2;
|
|
13752
13764
|
}
|
|
13753
13765
|
|
|
@@ -18699,7 +18711,8 @@ var WasmProcess = class {
|
|
|
18699
18711
|
...file.read && !file.write ? { access: "read" } : {},
|
|
18700
18712
|
...file.write && !file.read ? { access: "write" } : {},
|
|
18701
18713
|
...file.tty?.name ? { name: file.tty.name } : file.pty ? { name: "/dev/ptmx" } : {},
|
|
18702
|
-
...terminal ? { terminal } : {}
|
|
18714
|
+
...terminal ? { terminal } : {},
|
|
18715
|
+
...file.fifo !== void 0 ? { fifo: file.fifo } : {}
|
|
18703
18716
|
};
|
|
18704
18717
|
}
|
|
18705
18718
|
ttySyscall(req) {
|
|
@@ -19739,6 +19752,343 @@ var JobTable = class {
|
|
|
19739
19752
|
}
|
|
19740
19753
|
};
|
|
19741
19754
|
|
|
19755
|
+
// src/kernel/lock-service.ts
|
|
19756
|
+
var PRUNE_MS = 1e3;
|
|
19757
|
+
var LOCKS_PROTOCOL = "v1";
|
|
19758
|
+
var LockService = class {
|
|
19759
|
+
kernel = crypto.randomUUID();
|
|
19760
|
+
table = new LockTable();
|
|
19761
|
+
leader = false;
|
|
19762
|
+
role;
|
|
19763
|
+
channel;
|
|
19764
|
+
locks;
|
|
19765
|
+
root;
|
|
19766
|
+
pending = /* @__PURE__ */ new Map();
|
|
19767
|
+
next = 0;
|
|
19768
|
+
owners = /* @__PURE__ */ new Map();
|
|
19769
|
+
ownerOf = /* @__PURE__ */ new Map();
|
|
19770
|
+
nextRemote = -1;
|
|
19771
|
+
tokens = /* @__PURE__ */ new Map();
|
|
19772
|
+
flockIds = /* @__PURE__ */ new WeakMap();
|
|
19773
|
+
flockOwners = /* @__PURE__ */ new Map();
|
|
19774
|
+
nextFlock = 1;
|
|
19775
|
+
granted = /* @__PURE__ */ new Map();
|
|
19776
|
+
waiting = /* @__PURE__ */ new Map();
|
|
19777
|
+
settled = Promise.resolve();
|
|
19778
|
+
pruner;
|
|
19779
|
+
flocks;
|
|
19780
|
+
constructor(options) {
|
|
19781
|
+
this.root = options.root;
|
|
19782
|
+
this.locks = options.locks;
|
|
19783
|
+
this.channel = (options.channel ?? ((n) => new BroadcastChannel(n)))(
|
|
19784
|
+
`slicc-locks:${LOCKS_PROTOCOL}:${this.root}`
|
|
19785
|
+
);
|
|
19786
|
+
this.channel.unref?.();
|
|
19787
|
+
this.channel.onmessage = ({ data }) => {
|
|
19788
|
+
if (isMessage(data)) void this.receive(data);
|
|
19789
|
+
};
|
|
19790
|
+
void this.locks.request(this.aliveOf(this.kernel), () => new Promise(() => {
|
|
19791
|
+
}));
|
|
19792
|
+
this.role = this.elect();
|
|
19793
|
+
this.flocks = {
|
|
19794
|
+
set: (key, owner, kind) => this.flockSet(key, owner, kind),
|
|
19795
|
+
wait: (key, owner, kind, blocking) => this.flockWait(key, owner, kind, blocking),
|
|
19796
|
+
drop: (owner) => this.flockDrop(owner)
|
|
19797
|
+
};
|
|
19798
|
+
}
|
|
19799
|
+
aliveOf(kernel) {
|
|
19800
|
+
return `slicc-locks-alive:${LOCKS_PROTOCOL}:${this.root}:${kernel}`;
|
|
19801
|
+
}
|
|
19802
|
+
elect() {
|
|
19803
|
+
const name2 = `slicc-locks-leader:${LOCKS_PROTOCOL}:${this.root}`;
|
|
19804
|
+
return new Promise((decided) => {
|
|
19805
|
+
void this.locks.request(name2, { ifAvailable: true }, async (lock) => {
|
|
19806
|
+
this.leader = lock !== null;
|
|
19807
|
+
decided();
|
|
19808
|
+
if (this.leader) await new Promise(() => {
|
|
19809
|
+
});
|
|
19810
|
+
});
|
|
19811
|
+
}).then(() => {
|
|
19812
|
+
if (this.leader) return;
|
|
19813
|
+
void this.locks.request(name2, async () => {
|
|
19814
|
+
await this.lead();
|
|
19815
|
+
await new Promise(() => {
|
|
19816
|
+
});
|
|
19817
|
+
});
|
|
19818
|
+
});
|
|
19819
|
+
}
|
|
19820
|
+
async lead() {
|
|
19821
|
+
this.leader = true;
|
|
19822
|
+
this.settled = new Promise((resolve2) => setTimeout(resolve2, ANNOUNCE_WAIT_MS));
|
|
19823
|
+
this.channel.postMessage({ reassert: true, from: this.kernel });
|
|
19824
|
+
const pending = [...this.pending.entries()];
|
|
19825
|
+
this.pending.clear();
|
|
19826
|
+
await this.settled;
|
|
19827
|
+
for (const [, p] of pending) void this.serve(p.ask, this.kernel).then(p.resolve, p.reject);
|
|
19828
|
+
}
|
|
19829
|
+
async receive(data) {
|
|
19830
|
+
if (data.reassert && data.from !== this.kernel) return this.reassert();
|
|
19831
|
+
if (data.to !== void 0 && data.to !== this.kernel) return;
|
|
19832
|
+
if (data.id !== void 0 && (data.ok !== void 0 || data.errno !== void 0) && data.to === this.kernel) {
|
|
19833
|
+
return this.answered(data);
|
|
19834
|
+
}
|
|
19835
|
+
if (!this.leader || data.from === void 0) return;
|
|
19836
|
+
if (data.adopt) return this.adopt(data.from, data.adopt);
|
|
19837
|
+
if (data.cancel !== void 0) return void this.waiting.get(data.cancel)?.abort();
|
|
19838
|
+
if (data.ask && data.id !== void 0) await this.request(data.from, data.id, data.ask);
|
|
19839
|
+
}
|
|
19840
|
+
answered(data) {
|
|
19841
|
+
const p = this.pending.get(data.id);
|
|
19842
|
+
if (!p) return;
|
|
19843
|
+
this.pending.delete(data.id);
|
|
19844
|
+
if (data.errno !== void 0) p.reject(new KernelError(data.errno));
|
|
19845
|
+
else p.resolve(data.ok);
|
|
19846
|
+
}
|
|
19847
|
+
async request(from, id2, ask) {
|
|
19848
|
+
const known = this.granted.get(id2);
|
|
19849
|
+
if (known) return void this.channel.postMessage({ id: id2, to: from, ...known });
|
|
19850
|
+
await this.settled;
|
|
19851
|
+
let reply;
|
|
19852
|
+
try {
|
|
19853
|
+
reply = { ok: await this.serve(ask, from, id2) ?? null };
|
|
19854
|
+
} catch (err) {
|
|
19855
|
+
reply = { errno: err.code ?? "EIO" };
|
|
19856
|
+
}
|
|
19857
|
+
this.granted.set(id2, reply);
|
|
19858
|
+
if (this.granted.size > 4096) this.granted.delete(this.granted.keys().next().value);
|
|
19859
|
+
this.channel.postMessage({ id: id2, to: from, ...reply });
|
|
19860
|
+
}
|
|
19861
|
+
ownerFor(kernel, owner) {
|
|
19862
|
+
if (kernel === this.kernel) return owner;
|
|
19863
|
+
const name2 = `${kernel}:${owner}`;
|
|
19864
|
+
let id2 = this.owners.get(name2);
|
|
19865
|
+
if (id2 === void 0) {
|
|
19866
|
+
id2 = this.nextRemote--;
|
|
19867
|
+
this.owners.set(name2, id2);
|
|
19868
|
+
this.ownerOf.set(id2, { kernel, owner });
|
|
19869
|
+
this.watchRemotes();
|
|
19870
|
+
}
|
|
19871
|
+
return id2;
|
|
19872
|
+
}
|
|
19873
|
+
tokenFor(kernel, owner) {
|
|
19874
|
+
if (kernel === this.kernel) return this.flockOwners.get(owner) ?? {};
|
|
19875
|
+
const name2 = `${kernel}:${owner}`;
|
|
19876
|
+
let token = this.tokens.get(name2);
|
|
19877
|
+
if (!token) {
|
|
19878
|
+
token = { kernel, owner };
|
|
19879
|
+
this.tokens.set(name2, token);
|
|
19880
|
+
this.watchRemotes();
|
|
19881
|
+
}
|
|
19882
|
+
return token;
|
|
19883
|
+
}
|
|
19884
|
+
async serve(ask, from, id2) {
|
|
19885
|
+
const t = this.table;
|
|
19886
|
+
switch (ask.op) {
|
|
19887
|
+
case "set":
|
|
19888
|
+
return t.set(ask.key, this.ownerFor(from, ask.owner), ask.kind, ask.start, ask.end);
|
|
19889
|
+
case "holder": {
|
|
19890
|
+
const held = t.holder(ask.key, this.ownerFor(from, ask.owner), ask);
|
|
19891
|
+
if (!held) return void 0;
|
|
19892
|
+
return { ...held, owner: this.ownerOf.get(held.owner)?.owner ?? held.owner };
|
|
19893
|
+
}
|
|
19894
|
+
case "wait":
|
|
19895
|
+
return this.blockFor(
|
|
19896
|
+
id2,
|
|
19897
|
+
() => t.wait(ask.key, this.ownerFor(from, ask.owner), ask.kind, ask, () => this.signalOf(id2))
|
|
19898
|
+
);
|
|
19899
|
+
case "drop":
|
|
19900
|
+
return t.dropFile(ask.key, this.ownerFor(from, ask.owner));
|
|
19901
|
+
case "release":
|
|
19902
|
+
return t.release(this.ownerFor(from, ask.owner));
|
|
19903
|
+
case "fset":
|
|
19904
|
+
return t.flocks.set(ask.key, this.tokenFor(from, ask.owner), ask.kind);
|
|
19905
|
+
case "fwait":
|
|
19906
|
+
return this.blockFor(
|
|
19907
|
+
id2,
|
|
19908
|
+
() => t.flocks.wait(ask.key, this.tokenFor(from, ask.owner), ask.kind, () => this.signalOf(id2))
|
|
19909
|
+
);
|
|
19910
|
+
case "fdrop":
|
|
19911
|
+
return t.flocks.drop(this.tokenFor(from, ask.owner));
|
|
19912
|
+
}
|
|
19913
|
+
}
|
|
19914
|
+
signalOf(id2) {
|
|
19915
|
+
if (id2 === void 0) return new AbortController().signal;
|
|
19916
|
+
let c = this.waiting.get(id2);
|
|
19917
|
+
if (!c) {
|
|
19918
|
+
c = new AbortController();
|
|
19919
|
+
this.waiting.set(id2, c);
|
|
19920
|
+
}
|
|
19921
|
+
return c.signal;
|
|
19922
|
+
}
|
|
19923
|
+
async blockFor(id2, run2) {
|
|
19924
|
+
try {
|
|
19925
|
+
await run2();
|
|
19926
|
+
} finally {
|
|
19927
|
+
if (id2 !== void 0) this.waiting.delete(id2);
|
|
19928
|
+
}
|
|
19929
|
+
}
|
|
19930
|
+
watchRemotes() {
|
|
19931
|
+
if (this.pruner || this.ownerOf.size === 0 && this.tokens.size === 0) return;
|
|
19932
|
+
this.pruner = setInterval(() => void this.prune(), PRUNE_MS);
|
|
19933
|
+
this.pruner.unref?.();
|
|
19934
|
+
}
|
|
19935
|
+
async prune() {
|
|
19936
|
+
const held = new Set(((await this.locks.query()).held ?? []).map((l) => l.name));
|
|
19937
|
+
for (const [id2, { kernel, owner }] of [...this.ownerOf]) {
|
|
19938
|
+
if (held.has(this.aliveOf(kernel))) continue;
|
|
19939
|
+
this.table.release(id2);
|
|
19940
|
+
this.ownerOf.delete(id2);
|
|
19941
|
+
this.owners.delete(`${kernel}:${owner}`);
|
|
19942
|
+
}
|
|
19943
|
+
for (const [name2, token] of [...this.tokens]) {
|
|
19944
|
+
if (held.has(this.aliveOf(name2.slice(0, name2.lastIndexOf(":"))))) continue;
|
|
19945
|
+
this.table.flocks.drop(token);
|
|
19946
|
+
this.tokens.delete(name2);
|
|
19947
|
+
}
|
|
19948
|
+
if (this.pruner && this.ownerOf.size === 0 && this.tokens.size === 0) {
|
|
19949
|
+
clearInterval(this.pruner);
|
|
19950
|
+
this.pruner = void 0;
|
|
19951
|
+
}
|
|
19952
|
+
}
|
|
19953
|
+
reassert() {
|
|
19954
|
+
const records = this.table.entries();
|
|
19955
|
+
const flocks = this.table.flocks.entries().map(([key, owner, kind]) => [key, this.flockIdOf(owner), kind]);
|
|
19956
|
+
this.channel.postMessage({ adopt: { records, flocks }, from: this.kernel });
|
|
19957
|
+
for (const [id2, p] of this.pending)
|
|
19958
|
+
this.channel.postMessage({ id: id2, from: this.kernel, ask: p.ask });
|
|
19959
|
+
}
|
|
19960
|
+
adopt(from, held) {
|
|
19961
|
+
for (const [key, locks] of held.records)
|
|
19962
|
+
for (const l of locks)
|
|
19963
|
+
this.table.set(key, this.ownerFor(from, l.owner), l.kind, l.start, l.end);
|
|
19964
|
+
for (const [key, owner, kind] of held.flocks)
|
|
19965
|
+
this.table.flocks.set(key, this.tokenFor(from, owner), kind);
|
|
19966
|
+
}
|
|
19967
|
+
flockIdOf(owner) {
|
|
19968
|
+
let id2 = this.flockIds.get(owner);
|
|
19969
|
+
if (id2 === void 0) {
|
|
19970
|
+
id2 = this.nextFlock++;
|
|
19971
|
+
this.flockIds.set(owner, id2);
|
|
19972
|
+
this.flockOwners.set(id2, owner);
|
|
19973
|
+
}
|
|
19974
|
+
return id2;
|
|
19975
|
+
}
|
|
19976
|
+
async ask(ask, signal) {
|
|
19977
|
+
await this.role;
|
|
19978
|
+
await this.settled;
|
|
19979
|
+
if (this.leader) return this.serve(ask, this.kernel);
|
|
19980
|
+
const id2 = `${this.kernel}:${this.next++}`;
|
|
19981
|
+
return new Promise((resolve2, reject) => {
|
|
19982
|
+
this.pending.set(id2, { ask, resolve: resolve2, reject });
|
|
19983
|
+
this.channel.postMessage({ id: id2, from: this.kernel, ask });
|
|
19984
|
+
signal?.addEventListener(
|
|
19985
|
+
"abort",
|
|
19986
|
+
() => {
|
|
19987
|
+
if (!this.pending.delete(id2)) return;
|
|
19988
|
+
this.channel.postMessage({ cancel: id2, from: this.kernel });
|
|
19989
|
+
reject(new KernelError("EINTR"));
|
|
19990
|
+
},
|
|
19991
|
+
{ once: true }
|
|
19992
|
+
);
|
|
19993
|
+
});
|
|
19994
|
+
}
|
|
19995
|
+
async holder(key, owner, want) {
|
|
19996
|
+
return await this.ask({
|
|
19997
|
+
op: "holder",
|
|
19998
|
+
key,
|
|
19999
|
+
owner,
|
|
20000
|
+
kind: want.kind,
|
|
20001
|
+
start: want.start,
|
|
20002
|
+
end: want.end
|
|
20003
|
+
}) ?? void 0;
|
|
20004
|
+
}
|
|
20005
|
+
async set(key, owner, kind, start2, end) {
|
|
20006
|
+
const ok4 = await this.ask({ op: "set", key, owner, kind, start: start2, end }) === true;
|
|
20007
|
+
if (ok4 && !this.leader) this.table.set(key, owner, kind, start2, end);
|
|
20008
|
+
return ok4;
|
|
20009
|
+
}
|
|
20010
|
+
async wait(key, owner, kind, range2, blocking) {
|
|
20011
|
+
await this.role;
|
|
20012
|
+
await this.settled;
|
|
20013
|
+
if (this.leader) return this.table.wait(key, owner, kind, range2, blocking);
|
|
20014
|
+
if (await this.set(key, owner, kind, range2.start, range2.end)) return;
|
|
20015
|
+
await this.ask({ op: "wait", key, owner, kind, ...range2 }, blocking());
|
|
20016
|
+
if (!this.leader) this.table.set(key, owner, kind, range2.start, range2.end);
|
|
20017
|
+
}
|
|
20018
|
+
holds(owner) {
|
|
20019
|
+
return this.table.holds(owner);
|
|
20020
|
+
}
|
|
20021
|
+
dropFile(key, owner) {
|
|
20022
|
+
if (!this.leader) this.table.dropFile(key, owner);
|
|
20023
|
+
void this.ask({ op: "drop", key, owner }).catch(() => void 0);
|
|
20024
|
+
}
|
|
20025
|
+
release(pid) {
|
|
20026
|
+
if (!this.leader) this.table.release(pid);
|
|
20027
|
+
void this.ask({ op: "release", owner: pid }).catch(() => void 0);
|
|
20028
|
+
}
|
|
20029
|
+
async flockSet(key, owner, kind) {
|
|
20030
|
+
await this.role;
|
|
20031
|
+
await this.settled;
|
|
20032
|
+
if (this.leader) return this.table.flocks.set(key, owner, kind);
|
|
20033
|
+
const ok4 = await this.ask({ op: "fset", key, owner: this.flockIdOf(owner), kind }) === true;
|
|
20034
|
+
if (ok4) this.table.flocks.set(key, owner, kind);
|
|
20035
|
+
return ok4;
|
|
20036
|
+
}
|
|
20037
|
+
async flockWait(key, owner, kind, blocking) {
|
|
20038
|
+
await this.role;
|
|
20039
|
+
await this.settled;
|
|
20040
|
+
if (this.leader) return this.table.flocks.wait(key, owner, kind, blocking);
|
|
20041
|
+
if (await this.flockSet(key, owner, kind)) return;
|
|
20042
|
+
await this.ask({ op: "fwait", key, owner: this.flockIdOf(owner), kind }, blocking());
|
|
20043
|
+
if (!this.leader) this.table.flocks.set(key, owner, kind);
|
|
20044
|
+
}
|
|
20045
|
+
flockDrop(owner) {
|
|
20046
|
+
if (!this.leader) this.table.flocks.drop(owner);
|
|
20047
|
+
void this.ask({ op: "fdrop", owner: this.flockIdOf(owner) }).catch(() => void 0);
|
|
20048
|
+
}
|
|
20049
|
+
lock(pid, path, exclusive, fd) {
|
|
20050
|
+
return this.table.lock(pid, path, exclusive, fd);
|
|
20051
|
+
}
|
|
20052
|
+
unlock(pid, path) {
|
|
20053
|
+
this.table.unlock(pid, path);
|
|
20054
|
+
}
|
|
20055
|
+
closed(pid, fd) {
|
|
20056
|
+
this.table.closed(pid, fd);
|
|
20057
|
+
}
|
|
20058
|
+
};
|
|
20059
|
+
function kernelLocks(root) {
|
|
20060
|
+
const locks = globalThis.navigator?.locks;
|
|
20061
|
+
if (root === void 0 || !locks || typeof BroadcastChannel !== "function")
|
|
20062
|
+
return new LockTable();
|
|
20063
|
+
return new LockService({ root, locks });
|
|
20064
|
+
}
|
|
20065
|
+
var ASK_OPS = /* @__PURE__ */ new Set([
|
|
20066
|
+
"set",
|
|
20067
|
+
"wait",
|
|
20068
|
+
"holder",
|
|
20069
|
+
"drop",
|
|
20070
|
+
"release",
|
|
20071
|
+
"fset",
|
|
20072
|
+
"fwait",
|
|
20073
|
+
"fdrop"
|
|
20074
|
+
]);
|
|
20075
|
+
function askOk(ask) {
|
|
20076
|
+
if (typeof ask !== "object" || ask === null) return false;
|
|
20077
|
+
const a = ask;
|
|
20078
|
+
if (!ASK_OPS.has(String(a.op)) || typeof a.owner !== "number") return false;
|
|
20079
|
+
return a.key === void 0 || typeof a.key === "string";
|
|
20080
|
+
}
|
|
20081
|
+
function isMessage(data) {
|
|
20082
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) return false;
|
|
20083
|
+
const m = data;
|
|
20084
|
+
for (const field4 of ["id", "from", "to", "cancel", "errno"])
|
|
20085
|
+
if (m[field4] !== void 0 && typeof m[field4] !== "string") return false;
|
|
20086
|
+
if (m.ask !== void 0 && !askOk(m.ask)) return false;
|
|
20087
|
+
const adopt = m.adopt;
|
|
20088
|
+
if (adopt === void 0) return true;
|
|
20089
|
+
return adopt !== null && Array.isArray(adopt.records) && Array.isArray(adopt.flocks);
|
|
20090
|
+
}
|
|
20091
|
+
|
|
19742
20092
|
// src/kernel/net/hosts-file.ts
|
|
19743
20093
|
var HOSTS_PATH = "/etc/hosts";
|
|
19744
20094
|
function parseHosts(text) {
|
|
@@ -23110,7 +23460,7 @@ var Launcher = class {
|
|
|
23110
23460
|
users;
|
|
23111
23461
|
sudoer;
|
|
23112
23462
|
jobs = new JobTable();
|
|
23113
|
-
locks
|
|
23463
|
+
locks;
|
|
23114
23464
|
fifos = new FifoTable();
|
|
23115
23465
|
sems = new SemTable();
|
|
23116
23466
|
settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
|
|
@@ -23166,6 +23516,7 @@ var Launcher = class {
|
|
|
23166
23516
|
constructor(options) {
|
|
23167
23517
|
this.usersMode = usersMode(options.users);
|
|
23168
23518
|
this.rootFs = options.fs;
|
|
23519
|
+
this.locks = kernelLocks(options.fs.rootName);
|
|
23169
23520
|
this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
|
|
23170
23521
|
if (this.dac) this.dac.tagOf = (pid) => this.tagOf(pid);
|
|
23171
23522
|
this.clipboard = new ClipboardBroker(
|