@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/kernel-worker.js
CHANGED
|
@@ -1183,12 +1183,14 @@ var OpfsFs = class {
|
|
|
1183
1183
|
mounts = {};
|
|
1184
1184
|
locks;
|
|
1185
1185
|
lockPrefix;
|
|
1186
|
+
rootName;
|
|
1186
1187
|
constructor(root, meta = new MemoryMeta(), channel, options = {}) {
|
|
1187
1188
|
this.root = root;
|
|
1188
1189
|
this.meta = sidecar(meta);
|
|
1189
1190
|
this.ranged = options.ranged === true;
|
|
1190
1191
|
this.locks = options.locks === void 0 ? lockManager() : options.locks ?? void 0;
|
|
1191
1192
|
this.lockPrefix = `slicc-excl:${channel ?? ""}:`;
|
|
1193
|
+
this.rootName = channel;
|
|
1192
1194
|
this.channel = channel === void 0 ? void 0 : new BroadcastChannel(channel);
|
|
1193
1195
|
this.remote = channel === void 0 ? void 0 : new RemoteWatch(`${channel}:watch`);
|
|
1194
1196
|
if (this.remote) this.remote.quiet = () => this.quiet();
|
|
@@ -6364,7 +6366,7 @@ function satisfies(version, range2) {
|
|
|
6364
6366
|
}
|
|
6365
6367
|
|
|
6366
6368
|
// src/version.ts
|
|
6367
|
-
var KERNEL_VERSION = true ? "1.
|
|
6369
|
+
var KERNEL_VERSION = true ? "1.119.0" : "0.0.0-dev";
|
|
6368
6370
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6369
6371
|
function procVersion() {
|
|
6370
6372
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -13302,6 +13304,12 @@ var FlockTable = class {
|
|
|
13302
13304
|
await changedAt(this.wakers, key, signal);
|
|
13303
13305
|
}
|
|
13304
13306
|
}
|
|
13307
|
+
entries() {
|
|
13308
|
+
const out = [];
|
|
13309
|
+
for (const [key, holders] of this.held)
|
|
13310
|
+
for (const [owner, kind] of holders) out.push([key, owner, kind]);
|
|
13311
|
+
return out;
|
|
13312
|
+
}
|
|
13305
13313
|
drop(owner) {
|
|
13306
13314
|
const key = this.keys.get(owner);
|
|
13307
13315
|
if (key === void 0) return;
|
|
@@ -13380,6 +13388,9 @@ var LockTable = class {
|
|
|
13380
13388
|
if (locks.length === 0) this.records.delete(key);
|
|
13381
13389
|
else this.records.set(key, locks);
|
|
13382
13390
|
}
|
|
13391
|
+
entries() {
|
|
13392
|
+
return [...this.records].map(([key, locks]) => [key, locks.map((l) => ({ ...l }))]);
|
|
13393
|
+
}
|
|
13383
13394
|
holds(owner) {
|
|
13384
13395
|
for (const locks of this.records.values())
|
|
13385
13396
|
if (locks.some((l) => l.owner === owner)) return true;
|
|
@@ -13624,7 +13635,7 @@ async function flock(req, ctx) {
|
|
|
13624
13635
|
const { key, owner } = await flockOf(req.fd);
|
|
13625
13636
|
if (req.kind !== "unlock" && req.wait)
|
|
13626
13637
|
await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
|
|
13627
|
-
else if (!locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
13638
|
+
else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
13628
13639
|
return done2;
|
|
13629
13640
|
}
|
|
13630
13641
|
async function recordLock2(req, ctx) {
|
|
@@ -13642,7 +13653,7 @@ async function recordLock2(req, ctx) {
|
|
|
13642
13653
|
const range2 = lockRange(req.start, req.len);
|
|
13643
13654
|
const key = await fileKey(target, req.kind, req.op === "lk-set" && req.fd !== void 0);
|
|
13644
13655
|
if (req.op === "lk-get") {
|
|
13645
|
-
const held = locks.holder(key, owner, { key, kind: req.kind, ...range2 });
|
|
13656
|
+
const held = await locks.holder(key, owner, { key, kind: req.kind, ...range2 });
|
|
13646
13657
|
if (!held) return json3(null);
|
|
13647
13658
|
const len = held.end === Number.POSITIVE_INFINITY ? 0 : held.end - held.start;
|
|
13648
13659
|
return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
|
|
@@ -13651,7 +13662,8 @@ async function recordLock2(req, ctx) {
|
|
|
13651
13662
|
await locks.wait(key, owner, req.kind, range2, ctx.blocking);
|
|
13652
13663
|
return done2;
|
|
13653
13664
|
}
|
|
13654
|
-
if (!locks.set(key, owner, req.kind, range2.start, range2.end))
|
|
13665
|
+
if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
|
|
13666
|
+
throw new KernelError("EAGAIN");
|
|
13655
13667
|
return done2;
|
|
13656
13668
|
}
|
|
13657
13669
|
|
|
@@ -18761,7 +18773,8 @@ var WasmProcess = class {
|
|
|
18761
18773
|
...file.read && !file.write ? { access: "read" } : {},
|
|
18762
18774
|
...file.write && !file.read ? { access: "write" } : {},
|
|
18763
18775
|
...file.tty?.name ? { name: file.tty.name } : file.pty ? { name: "/dev/ptmx" } : {},
|
|
18764
|
-
...terminal ? { terminal } : {}
|
|
18776
|
+
...terminal ? { terminal } : {},
|
|
18777
|
+
...file.fifo !== void 0 ? { fifo: file.fifo } : {}
|
|
18765
18778
|
};
|
|
18766
18779
|
}
|
|
18767
18780
|
ttySyscall(req) {
|
|
@@ -19801,6 +19814,343 @@ var JobTable = class {
|
|
|
19801
19814
|
}
|
|
19802
19815
|
};
|
|
19803
19816
|
|
|
19817
|
+
// src/kernel/lock-service.ts
|
|
19818
|
+
var PRUNE_MS = 1e3;
|
|
19819
|
+
var LOCKS_PROTOCOL = "v1";
|
|
19820
|
+
var LockService = class {
|
|
19821
|
+
kernel = crypto.randomUUID();
|
|
19822
|
+
table = new LockTable();
|
|
19823
|
+
leader = false;
|
|
19824
|
+
role;
|
|
19825
|
+
channel;
|
|
19826
|
+
locks;
|
|
19827
|
+
root;
|
|
19828
|
+
pending = /* @__PURE__ */ new Map();
|
|
19829
|
+
next = 0;
|
|
19830
|
+
owners = /* @__PURE__ */ new Map();
|
|
19831
|
+
ownerOf = /* @__PURE__ */ new Map();
|
|
19832
|
+
nextRemote = -1;
|
|
19833
|
+
tokens = /* @__PURE__ */ new Map();
|
|
19834
|
+
flockIds = /* @__PURE__ */ new WeakMap();
|
|
19835
|
+
flockOwners = /* @__PURE__ */ new Map();
|
|
19836
|
+
nextFlock = 1;
|
|
19837
|
+
granted = /* @__PURE__ */ new Map();
|
|
19838
|
+
waiting = /* @__PURE__ */ new Map();
|
|
19839
|
+
settled = Promise.resolve();
|
|
19840
|
+
pruner;
|
|
19841
|
+
flocks;
|
|
19842
|
+
constructor(options) {
|
|
19843
|
+
this.root = options.root;
|
|
19844
|
+
this.locks = options.locks;
|
|
19845
|
+
this.channel = (options.channel ?? ((n) => new BroadcastChannel(n)))(
|
|
19846
|
+
`slicc-locks:${LOCKS_PROTOCOL}:${this.root}`
|
|
19847
|
+
);
|
|
19848
|
+
this.channel.unref?.();
|
|
19849
|
+
this.channel.onmessage = ({ data }) => {
|
|
19850
|
+
if (isMessage(data)) void this.receive(data);
|
|
19851
|
+
};
|
|
19852
|
+
void this.locks.request(this.aliveOf(this.kernel), () => new Promise(() => {
|
|
19853
|
+
}));
|
|
19854
|
+
this.role = this.elect();
|
|
19855
|
+
this.flocks = {
|
|
19856
|
+
set: (key, owner, kind) => this.flockSet(key, owner, kind),
|
|
19857
|
+
wait: (key, owner, kind, blocking) => this.flockWait(key, owner, kind, blocking),
|
|
19858
|
+
drop: (owner) => this.flockDrop(owner)
|
|
19859
|
+
};
|
|
19860
|
+
}
|
|
19861
|
+
aliveOf(kernel) {
|
|
19862
|
+
return `slicc-locks-alive:${LOCKS_PROTOCOL}:${this.root}:${kernel}`;
|
|
19863
|
+
}
|
|
19864
|
+
elect() {
|
|
19865
|
+
const name2 = `slicc-locks-leader:${LOCKS_PROTOCOL}:${this.root}`;
|
|
19866
|
+
return new Promise((decided) => {
|
|
19867
|
+
void this.locks.request(name2, { ifAvailable: true }, async (lock) => {
|
|
19868
|
+
this.leader = lock !== null;
|
|
19869
|
+
decided();
|
|
19870
|
+
if (this.leader) await new Promise(() => {
|
|
19871
|
+
});
|
|
19872
|
+
});
|
|
19873
|
+
}).then(() => {
|
|
19874
|
+
if (this.leader) return;
|
|
19875
|
+
void this.locks.request(name2, async () => {
|
|
19876
|
+
await this.lead();
|
|
19877
|
+
await new Promise(() => {
|
|
19878
|
+
});
|
|
19879
|
+
});
|
|
19880
|
+
});
|
|
19881
|
+
}
|
|
19882
|
+
async lead() {
|
|
19883
|
+
this.leader = true;
|
|
19884
|
+
this.settled = new Promise((resolve2) => setTimeout(resolve2, ANNOUNCE_WAIT_MS));
|
|
19885
|
+
this.channel.postMessage({ reassert: true, from: this.kernel });
|
|
19886
|
+
const pending = [...this.pending.entries()];
|
|
19887
|
+
this.pending.clear();
|
|
19888
|
+
await this.settled;
|
|
19889
|
+
for (const [, p] of pending) void this.serve(p.ask, this.kernel).then(p.resolve, p.reject);
|
|
19890
|
+
}
|
|
19891
|
+
async receive(data) {
|
|
19892
|
+
if (data.reassert && data.from !== this.kernel) return this.reassert();
|
|
19893
|
+
if (data.to !== void 0 && data.to !== this.kernel) return;
|
|
19894
|
+
if (data.id !== void 0 && (data.ok !== void 0 || data.errno !== void 0) && data.to === this.kernel) {
|
|
19895
|
+
return this.answered(data);
|
|
19896
|
+
}
|
|
19897
|
+
if (!this.leader || data.from === void 0) return;
|
|
19898
|
+
if (data.adopt) return this.adopt(data.from, data.adopt);
|
|
19899
|
+
if (data.cancel !== void 0) return void this.waiting.get(data.cancel)?.abort();
|
|
19900
|
+
if (data.ask && data.id !== void 0) await this.request(data.from, data.id, data.ask);
|
|
19901
|
+
}
|
|
19902
|
+
answered(data) {
|
|
19903
|
+
const p = this.pending.get(data.id);
|
|
19904
|
+
if (!p) return;
|
|
19905
|
+
this.pending.delete(data.id);
|
|
19906
|
+
if (data.errno !== void 0) p.reject(new KernelError(data.errno));
|
|
19907
|
+
else p.resolve(data.ok);
|
|
19908
|
+
}
|
|
19909
|
+
async request(from, id2, ask) {
|
|
19910
|
+
const known = this.granted.get(id2);
|
|
19911
|
+
if (known) return void this.channel.postMessage({ id: id2, to: from, ...known });
|
|
19912
|
+
await this.settled;
|
|
19913
|
+
let reply;
|
|
19914
|
+
try {
|
|
19915
|
+
reply = { ok: await this.serve(ask, from, id2) ?? null };
|
|
19916
|
+
} catch (err) {
|
|
19917
|
+
reply = { errno: err.code ?? "EIO" };
|
|
19918
|
+
}
|
|
19919
|
+
this.granted.set(id2, reply);
|
|
19920
|
+
if (this.granted.size > 4096) this.granted.delete(this.granted.keys().next().value);
|
|
19921
|
+
this.channel.postMessage({ id: id2, to: from, ...reply });
|
|
19922
|
+
}
|
|
19923
|
+
ownerFor(kernel, owner) {
|
|
19924
|
+
if (kernel === this.kernel) return owner;
|
|
19925
|
+
const name2 = `${kernel}:${owner}`;
|
|
19926
|
+
let id2 = this.owners.get(name2);
|
|
19927
|
+
if (id2 === void 0) {
|
|
19928
|
+
id2 = this.nextRemote--;
|
|
19929
|
+
this.owners.set(name2, id2);
|
|
19930
|
+
this.ownerOf.set(id2, { kernel, owner });
|
|
19931
|
+
this.watchRemotes();
|
|
19932
|
+
}
|
|
19933
|
+
return id2;
|
|
19934
|
+
}
|
|
19935
|
+
tokenFor(kernel, owner) {
|
|
19936
|
+
if (kernel === this.kernel) return this.flockOwners.get(owner) ?? {};
|
|
19937
|
+
const name2 = `${kernel}:${owner}`;
|
|
19938
|
+
let token = this.tokens.get(name2);
|
|
19939
|
+
if (!token) {
|
|
19940
|
+
token = { kernel, owner };
|
|
19941
|
+
this.tokens.set(name2, token);
|
|
19942
|
+
this.watchRemotes();
|
|
19943
|
+
}
|
|
19944
|
+
return token;
|
|
19945
|
+
}
|
|
19946
|
+
async serve(ask, from, id2) {
|
|
19947
|
+
const t = this.table;
|
|
19948
|
+
switch (ask.op) {
|
|
19949
|
+
case "set":
|
|
19950
|
+
return t.set(ask.key, this.ownerFor(from, ask.owner), ask.kind, ask.start, ask.end);
|
|
19951
|
+
case "holder": {
|
|
19952
|
+
const held = t.holder(ask.key, this.ownerFor(from, ask.owner), ask);
|
|
19953
|
+
if (!held) return void 0;
|
|
19954
|
+
return { ...held, owner: this.ownerOf.get(held.owner)?.owner ?? held.owner };
|
|
19955
|
+
}
|
|
19956
|
+
case "wait":
|
|
19957
|
+
return this.blockFor(
|
|
19958
|
+
id2,
|
|
19959
|
+
() => t.wait(ask.key, this.ownerFor(from, ask.owner), ask.kind, ask, () => this.signalOf(id2))
|
|
19960
|
+
);
|
|
19961
|
+
case "drop":
|
|
19962
|
+
return t.dropFile(ask.key, this.ownerFor(from, ask.owner));
|
|
19963
|
+
case "release":
|
|
19964
|
+
return t.release(this.ownerFor(from, ask.owner));
|
|
19965
|
+
case "fset":
|
|
19966
|
+
return t.flocks.set(ask.key, this.tokenFor(from, ask.owner), ask.kind);
|
|
19967
|
+
case "fwait":
|
|
19968
|
+
return this.blockFor(
|
|
19969
|
+
id2,
|
|
19970
|
+
() => t.flocks.wait(ask.key, this.tokenFor(from, ask.owner), ask.kind, () => this.signalOf(id2))
|
|
19971
|
+
);
|
|
19972
|
+
case "fdrop":
|
|
19973
|
+
return t.flocks.drop(this.tokenFor(from, ask.owner));
|
|
19974
|
+
}
|
|
19975
|
+
}
|
|
19976
|
+
signalOf(id2) {
|
|
19977
|
+
if (id2 === void 0) return new AbortController().signal;
|
|
19978
|
+
let c = this.waiting.get(id2);
|
|
19979
|
+
if (!c) {
|
|
19980
|
+
c = new AbortController();
|
|
19981
|
+
this.waiting.set(id2, c);
|
|
19982
|
+
}
|
|
19983
|
+
return c.signal;
|
|
19984
|
+
}
|
|
19985
|
+
async blockFor(id2, run2) {
|
|
19986
|
+
try {
|
|
19987
|
+
await run2();
|
|
19988
|
+
} finally {
|
|
19989
|
+
if (id2 !== void 0) this.waiting.delete(id2);
|
|
19990
|
+
}
|
|
19991
|
+
}
|
|
19992
|
+
watchRemotes() {
|
|
19993
|
+
if (this.pruner || this.ownerOf.size === 0 && this.tokens.size === 0) return;
|
|
19994
|
+
this.pruner = setInterval(() => void this.prune(), PRUNE_MS);
|
|
19995
|
+
this.pruner.unref?.();
|
|
19996
|
+
}
|
|
19997
|
+
async prune() {
|
|
19998
|
+
const held = new Set(((await this.locks.query()).held ?? []).map((l) => l.name));
|
|
19999
|
+
for (const [id2, { kernel, owner }] of [...this.ownerOf]) {
|
|
20000
|
+
if (held.has(this.aliveOf(kernel))) continue;
|
|
20001
|
+
this.table.release(id2);
|
|
20002
|
+
this.ownerOf.delete(id2);
|
|
20003
|
+
this.owners.delete(`${kernel}:${owner}`);
|
|
20004
|
+
}
|
|
20005
|
+
for (const [name2, token] of [...this.tokens]) {
|
|
20006
|
+
if (held.has(this.aliveOf(name2.slice(0, name2.lastIndexOf(":"))))) continue;
|
|
20007
|
+
this.table.flocks.drop(token);
|
|
20008
|
+
this.tokens.delete(name2);
|
|
20009
|
+
}
|
|
20010
|
+
if (this.pruner && this.ownerOf.size === 0 && this.tokens.size === 0) {
|
|
20011
|
+
clearInterval(this.pruner);
|
|
20012
|
+
this.pruner = void 0;
|
|
20013
|
+
}
|
|
20014
|
+
}
|
|
20015
|
+
reassert() {
|
|
20016
|
+
const records = this.table.entries();
|
|
20017
|
+
const flocks = this.table.flocks.entries().map(([key, owner, kind]) => [key, this.flockIdOf(owner), kind]);
|
|
20018
|
+
this.channel.postMessage({ adopt: { records, flocks }, from: this.kernel });
|
|
20019
|
+
for (const [id2, p] of this.pending)
|
|
20020
|
+
this.channel.postMessage({ id: id2, from: this.kernel, ask: p.ask });
|
|
20021
|
+
}
|
|
20022
|
+
adopt(from, held) {
|
|
20023
|
+
for (const [key, locks] of held.records)
|
|
20024
|
+
for (const l of locks)
|
|
20025
|
+
this.table.set(key, this.ownerFor(from, l.owner), l.kind, l.start, l.end);
|
|
20026
|
+
for (const [key, owner, kind] of held.flocks)
|
|
20027
|
+
this.table.flocks.set(key, this.tokenFor(from, owner), kind);
|
|
20028
|
+
}
|
|
20029
|
+
flockIdOf(owner) {
|
|
20030
|
+
let id2 = this.flockIds.get(owner);
|
|
20031
|
+
if (id2 === void 0) {
|
|
20032
|
+
id2 = this.nextFlock++;
|
|
20033
|
+
this.flockIds.set(owner, id2);
|
|
20034
|
+
this.flockOwners.set(id2, owner);
|
|
20035
|
+
}
|
|
20036
|
+
return id2;
|
|
20037
|
+
}
|
|
20038
|
+
async ask(ask, signal) {
|
|
20039
|
+
await this.role;
|
|
20040
|
+
await this.settled;
|
|
20041
|
+
if (this.leader) return this.serve(ask, this.kernel);
|
|
20042
|
+
const id2 = `${this.kernel}:${this.next++}`;
|
|
20043
|
+
return new Promise((resolve2, reject) => {
|
|
20044
|
+
this.pending.set(id2, { ask, resolve: resolve2, reject });
|
|
20045
|
+
this.channel.postMessage({ id: id2, from: this.kernel, ask });
|
|
20046
|
+
signal?.addEventListener(
|
|
20047
|
+
"abort",
|
|
20048
|
+
() => {
|
|
20049
|
+
if (!this.pending.delete(id2)) return;
|
|
20050
|
+
this.channel.postMessage({ cancel: id2, from: this.kernel });
|
|
20051
|
+
reject(new KernelError("EINTR"));
|
|
20052
|
+
},
|
|
20053
|
+
{ once: true }
|
|
20054
|
+
);
|
|
20055
|
+
});
|
|
20056
|
+
}
|
|
20057
|
+
async holder(key, owner, want) {
|
|
20058
|
+
return await this.ask({
|
|
20059
|
+
op: "holder",
|
|
20060
|
+
key,
|
|
20061
|
+
owner,
|
|
20062
|
+
kind: want.kind,
|
|
20063
|
+
start: want.start,
|
|
20064
|
+
end: want.end
|
|
20065
|
+
}) ?? void 0;
|
|
20066
|
+
}
|
|
20067
|
+
async set(key, owner, kind, start2, end) {
|
|
20068
|
+
const ok4 = await this.ask({ op: "set", key, owner, kind, start: start2, end }) === true;
|
|
20069
|
+
if (ok4 && !this.leader) this.table.set(key, owner, kind, start2, end);
|
|
20070
|
+
return ok4;
|
|
20071
|
+
}
|
|
20072
|
+
async wait(key, owner, kind, range2, blocking) {
|
|
20073
|
+
await this.role;
|
|
20074
|
+
await this.settled;
|
|
20075
|
+
if (this.leader) return this.table.wait(key, owner, kind, range2, blocking);
|
|
20076
|
+
if (await this.set(key, owner, kind, range2.start, range2.end)) return;
|
|
20077
|
+
await this.ask({ op: "wait", key, owner, kind, ...range2 }, blocking());
|
|
20078
|
+
if (!this.leader) this.table.set(key, owner, kind, range2.start, range2.end);
|
|
20079
|
+
}
|
|
20080
|
+
holds(owner) {
|
|
20081
|
+
return this.table.holds(owner);
|
|
20082
|
+
}
|
|
20083
|
+
dropFile(key, owner) {
|
|
20084
|
+
if (!this.leader) this.table.dropFile(key, owner);
|
|
20085
|
+
void this.ask({ op: "drop", key, owner }).catch(() => void 0);
|
|
20086
|
+
}
|
|
20087
|
+
release(pid) {
|
|
20088
|
+
if (!this.leader) this.table.release(pid);
|
|
20089
|
+
void this.ask({ op: "release", owner: pid }).catch(() => void 0);
|
|
20090
|
+
}
|
|
20091
|
+
async flockSet(key, owner, kind) {
|
|
20092
|
+
await this.role;
|
|
20093
|
+
await this.settled;
|
|
20094
|
+
if (this.leader) return this.table.flocks.set(key, owner, kind);
|
|
20095
|
+
const ok4 = await this.ask({ op: "fset", key, owner: this.flockIdOf(owner), kind }) === true;
|
|
20096
|
+
if (ok4) this.table.flocks.set(key, owner, kind);
|
|
20097
|
+
return ok4;
|
|
20098
|
+
}
|
|
20099
|
+
async flockWait(key, owner, kind, blocking) {
|
|
20100
|
+
await this.role;
|
|
20101
|
+
await this.settled;
|
|
20102
|
+
if (this.leader) return this.table.flocks.wait(key, owner, kind, blocking);
|
|
20103
|
+
if (await this.flockSet(key, owner, kind)) return;
|
|
20104
|
+
await this.ask({ op: "fwait", key, owner: this.flockIdOf(owner), kind }, blocking());
|
|
20105
|
+
if (!this.leader) this.table.flocks.set(key, owner, kind);
|
|
20106
|
+
}
|
|
20107
|
+
flockDrop(owner) {
|
|
20108
|
+
if (!this.leader) this.table.flocks.drop(owner);
|
|
20109
|
+
void this.ask({ op: "fdrop", owner: this.flockIdOf(owner) }).catch(() => void 0);
|
|
20110
|
+
}
|
|
20111
|
+
lock(pid, path, exclusive, fd) {
|
|
20112
|
+
return this.table.lock(pid, path, exclusive, fd);
|
|
20113
|
+
}
|
|
20114
|
+
unlock(pid, path) {
|
|
20115
|
+
this.table.unlock(pid, path);
|
|
20116
|
+
}
|
|
20117
|
+
closed(pid, fd) {
|
|
20118
|
+
this.table.closed(pid, fd);
|
|
20119
|
+
}
|
|
20120
|
+
};
|
|
20121
|
+
function kernelLocks(root) {
|
|
20122
|
+
const locks = globalThis.navigator?.locks;
|
|
20123
|
+
if (root === void 0 || !locks || typeof BroadcastChannel !== "function")
|
|
20124
|
+
return new LockTable();
|
|
20125
|
+
return new LockService({ root, locks });
|
|
20126
|
+
}
|
|
20127
|
+
var ASK_OPS = /* @__PURE__ */ new Set([
|
|
20128
|
+
"set",
|
|
20129
|
+
"wait",
|
|
20130
|
+
"holder",
|
|
20131
|
+
"drop",
|
|
20132
|
+
"release",
|
|
20133
|
+
"fset",
|
|
20134
|
+
"fwait",
|
|
20135
|
+
"fdrop"
|
|
20136
|
+
]);
|
|
20137
|
+
function askOk(ask) {
|
|
20138
|
+
if (typeof ask !== "object" || ask === null) return false;
|
|
20139
|
+
const a = ask;
|
|
20140
|
+
if (!ASK_OPS.has(String(a.op)) || typeof a.owner !== "number") return false;
|
|
20141
|
+
return a.key === void 0 || typeof a.key === "string";
|
|
20142
|
+
}
|
|
20143
|
+
function isMessage(data) {
|
|
20144
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) return false;
|
|
20145
|
+
const m = data;
|
|
20146
|
+
for (const field4 of ["id", "from", "to", "cancel", "errno"])
|
|
20147
|
+
if (m[field4] !== void 0 && typeof m[field4] !== "string") return false;
|
|
20148
|
+
if (m.ask !== void 0 && !askOk(m.ask)) return false;
|
|
20149
|
+
const adopt = m.adopt;
|
|
20150
|
+
if (adopt === void 0) return true;
|
|
20151
|
+
return adopt !== null && Array.isArray(adopt.records) && Array.isArray(adopt.flocks);
|
|
20152
|
+
}
|
|
20153
|
+
|
|
19804
20154
|
// src/kernel/net/hosts-file.ts
|
|
19805
20155
|
var HOSTS_PATH = "/etc/hosts";
|
|
19806
20156
|
function parseHosts(text) {
|
|
@@ -23104,7 +23454,7 @@ var Launcher = class {
|
|
|
23104
23454
|
users;
|
|
23105
23455
|
sudoer;
|
|
23106
23456
|
jobs = new JobTable();
|
|
23107
|
-
locks
|
|
23457
|
+
locks;
|
|
23108
23458
|
fifos = new FifoTable();
|
|
23109
23459
|
sems = new SemTable();
|
|
23110
23460
|
settling = new SettlingChildren((pid) => this.jobs.pgidOf(pid));
|
|
@@ -23160,6 +23510,7 @@ var Launcher = class {
|
|
|
23160
23510
|
constructor(options) {
|
|
23161
23511
|
this.usersMode = usersMode(options.users);
|
|
23162
23512
|
this.rootFs = options.fs;
|
|
23513
|
+
this.locks = kernelLocks(options.fs.rootName);
|
|
23163
23514
|
this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
|
|
23164
23515
|
if (this.dac) this.dac.tagOf = (pid) => this.tagOf(pid);
|
|
23165
23516
|
this.clipboard = new ClipboardBroker(
|