@ai-ecoverse/slicc-kernel 1.120.0 → 1.120.2

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/dist/node.js CHANGED
@@ -3998,6 +3998,14 @@ var RemoteWatch = class {
3998
3998
  met;
3999
3999
  settled = false;
4000
4000
  quiet;
4001
+ crowd;
4002
+ told;
4003
+ recount() {
4004
+ const now = this.crowded();
4005
+ if (now === this.told) return;
4006
+ this.told = now;
4007
+ this.crowd?.(now);
4008
+ }
4001
4009
  constructor(name2, options = {}) {
4002
4010
  this.name = name2;
4003
4011
  this.locks = options.locks === void 0 ? lockManager() : options.locks ?? void 0;
@@ -4014,6 +4022,7 @@ var RemoteWatch = class {
4014
4022
  });
4015
4023
  this.joined = granted2.then(() => this.join()).then(() => {
4016
4024
  this.settled = true;
4025
+ this.recount();
4017
4026
  });
4018
4027
  this.channel.postMessage({ hello: this.tab });
4019
4028
  }
@@ -4046,6 +4055,7 @@ var RemoteWatch = class {
4046
4055
  if (data.hello !== void 0) this.greeted(data.hello);
4047
4056
  if (data.here !== void 0 && data.to === this.tab) {
4048
4057
  this.peers.add(data.here);
4058
+ this.recount();
4049
4059
  this.met?.();
4050
4060
  }
4051
4061
  if (data.tab !== void 0 && data.paths !== void 0) this.announced(data);
@@ -4056,6 +4066,7 @@ var RemoteWatch = class {
4056
4066
  }
4057
4067
  greeted(peer) {
4058
4068
  this.peers.add(peer);
4069
+ this.recount();
4059
4070
  const answer = () => {
4060
4071
  this.channel.postMessage({ here: this.tab, to: peer });
4061
4072
  if (this.mine.length > 0) void this.announce(this.mine);
@@ -4066,6 +4077,7 @@ var RemoteWatch = class {
4066
4077
  announced({ tab, paths, seq: seq2 }) {
4067
4078
  const from = tab;
4068
4079
  this.peers.add(from);
4080
+ this.recount();
4069
4081
  if (paths.length > 0) this.others.set(from, paths);
4070
4082
  else this.others.delete(from);
4071
4083
  this.rebuild();
@@ -4091,6 +4103,7 @@ var RemoteWatch = class {
4091
4103
  }
4092
4104
  }
4093
4105
  this.rebuild();
4106
+ this.recount();
4094
4107
  }
4095
4108
  watched() {
4096
4109
  return this.union.size > 0;
@@ -4319,7 +4332,7 @@ var OpfsFs = class {
4319
4332
  this.rootName = channel;
4320
4333
  this.channel = channel === void 0 ? void 0 : new BroadcastChannel(channel);
4321
4334
  this.remote = channel === void 0 ? void 0 : new RemoteWatch(`${channel}:watch`);
4322
- if (this.remote) this.remote.quiet = () => this.quiet();
4335
+ if (this.remote) this.remote.quiet = () => this.quiet().then(() => this.settle?.());
4323
4336
  if (this.channel) {
4324
4337
  const remote = this.remote;
4325
4338
  meta.listen?.(
@@ -4474,6 +4487,22 @@ var OpfsFs = class {
4474
4487
  if (this.unlocked === 0) for (const done4 of this.idle.splice(0)) done4();
4475
4488
  }
4476
4489
  }
4490
+ settle;
4491
+ onPeer(settle) {
4492
+ this.settle = settle;
4493
+ }
4494
+ peers() {
4495
+ const remote = this.remote;
4496
+ if (!remote) return void 0;
4497
+ return {
4498
+ joined: () => remote.peered(),
4499
+ crowded: () => remote.crowded(),
4500
+ watch: (listener) => {
4501
+ remote.crowd = listener;
4502
+ listener(remote.crowded());
4503
+ }
4504
+ };
4505
+ }
4477
4506
  quiet() {
4478
4507
  if (this.unlocked === 0) return Promise.resolve();
4479
4508
  return new Promise((resolve2) => this.idle.push(resolve2));
@@ -6747,7 +6776,7 @@ function satisfies(version, range2) {
6747
6776
  }
6748
6777
 
6749
6778
  // src/version.ts
6750
- var KERNEL_VERSION = true ? "1.120.0" : "0.0.0-dev";
6779
+ var KERNEL_VERSION = true ? "1.120.2" : "0.0.0-dev";
6751
6780
  var OS_RELEASE = "6.0.0-slicc";
6752
6781
  function procVersion() {
6753
6782
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -8750,7 +8779,8 @@ var RING = 1;
8750
8779
  var RING_SIZE = 4096;
8751
8780
  var SLOT = 2;
8752
8781
  var DIRTY = RING + RING_SIZE * SLOT;
8753
- var CHANGES_BYTES = (DIRTY + 1) * 4;
8782
+ var FOREIGN = DIRTY + 1;
8783
+ var CHANGES_BYTES = (FOREIGN + 1) * 4;
8754
8784
  function changeHash(path) {
8755
8785
  let h = 2166136261;
8756
8786
  for (let i = 0; i < path.length; i++) {
@@ -8778,6 +8808,9 @@ var FileChanges = class {
8778
8808
  dirtied(delta) {
8779
8809
  Atomics.add(this.view, DIRTY, delta);
8780
8810
  }
8811
+ foreign(on) {
8812
+ Atomics.store(this.view, FOREIGN, on ? 1 : 0);
8813
+ }
8781
8814
  publish(...paths) {
8782
8815
  for (const path of paths) {
8783
8816
  const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
@@ -13739,10 +13772,14 @@ async function flock(req, ctx) {
13739
13772
  if (!locks || !flockOf) throw new KernelError("ENOLCK");
13740
13773
  if (!FLOCK_KINDS.has(req.kind)) throw new KernelError("EINVAL");
13741
13774
  const { key, owner } = await flockOf(req.fd);
13775
+ const granted2 = req.kind !== "unlock";
13776
+ const shared = locks.shared?.() === true;
13777
+ if (shared && !granted2) await ctx.settle?.(req.fd, false);
13742
13778
  if (req.kind !== "unlock" && req.wait)
13743
13779
  await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
13744
13780
  else if (!await locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
13745
- return done2;
13781
+ if (shared && granted2) await ctx.settle?.(req.fd, true);
13782
+ return shared ? json3(true) : done2;
13746
13783
  }
13747
13784
  async function recordLock2(req, ctx) {
13748
13785
  const { locks, fileKey } = ctx;
@@ -13753,6 +13790,7 @@ async function recordLock2(req, ctx) {
13753
13790
  ...req.fd !== void 0 ? { fd: req.fd } : {}
13754
13791
  };
13755
13792
  if (req.op === "lk-close") {
13793
+ if (req.fd !== void 0 && locks.shared?.()) await ctx.settle?.(req.fd, false);
13756
13794
  locks.dropFile(await fileKey(target, "close"), owner);
13757
13795
  return done2;
13758
13796
  }
@@ -13764,13 +13802,16 @@ async function recordLock2(req, ctx) {
13764
13802
  const len = held.end === Number.POSITIVE_INFINITY ? 0 : held.end - held.start;
13765
13803
  return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
13766
13804
  }
13767
- if (req.kind !== "unlock" && req.wait) {
13805
+ const granted2 = req.kind !== "unlock";
13806
+ const shared = locks.shared?.() === true;
13807
+ const fd = shared ? req.fd : void 0;
13808
+ if (!granted2 && fd !== void 0) await ctx.settle?.(fd, false);
13809
+ if (req.kind !== "unlock" && req.wait)
13768
13810
  await locks.wait(key, owner, req.kind, range2, ctx.blocking);
13769
- return done2;
13770
- }
13771
- if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
13811
+ else if (!await locks.set(key, owner, req.kind, range2.start, range2.end))
13772
13812
  throw new KernelError("EAGAIN");
13773
- return done2;
13813
+ if (granted2 && fd !== void 0) await ctx.settle?.(fd, true);
13814
+ return shared ? json3(true) : done2;
13774
13815
  }
13775
13816
 
13776
13817
  // src/kernel/net/loopback-transport.ts
@@ -16922,6 +16963,11 @@ var VfsNode = class {
16922
16963
  holds() {
16923
16964
  return this.dirty;
16924
16965
  }
16966
+ reread() {
16967
+ if (this.dirty || this.orphaned || this.pin || this.revoked) return;
16968
+ this.data = void 0;
16969
+ this.ranged = void 0;
16970
+ }
16925
16971
  replace(contents2) {
16926
16972
  this.ranged = void 0;
16927
16973
  this.data = new Uint8Array(contents2);
@@ -17549,6 +17595,7 @@ function vfsFile(fs, opts, nodes) {
17549
17595
  })),
17550
17596
  known: () => node.known(),
17551
17597
  flush: () => serial(() => node.flush()),
17598
+ reread: () => serial(async () => node.reread()),
17552
17599
  close: () => node.serial(async () => {
17553
17600
  try {
17554
17601
  takeOpenError();
@@ -18031,6 +18078,7 @@ var WasmProcess = class {
18031
18078
  owner: () => this.lockOwner(),
18032
18079
  fileKey: (target, kind, setting) => this.lockKey(target, kind, setting),
18033
18080
  flockOf: (fd) => this.flockOf(fd),
18081
+ settle: (fd, granted2) => this.settle(fd, granted2),
18034
18082
  locks: this.options.locks,
18035
18083
  ops: this.asyncOps,
18036
18084
  blocking: () => this.blockingSignal(cancelled),
@@ -18114,6 +18162,11 @@ var WasmProcess = class {
18114
18162
  else if (this.pathKeys.size < 4096) this.pathKeys.set(path, key);
18115
18163
  return key;
18116
18164
  }
18165
+ async settle(fd, granted2) {
18166
+ const file = this.fds.has(fd) ? this.fds.get(fd).file : void 0;
18167
+ if (granted2) await file?.reread?.();
18168
+ else await file?.flush?.();
18169
+ }
18117
18170
  async flockOf(fd) {
18118
18171
  const open = this.fds.get(fd);
18119
18172
  const { locks } = this.options;
@@ -19799,13 +19852,20 @@ var LockService = class {
19799
19852
  };
19800
19853
  void this.locks.request(this.aliveOf(this.kernel), () => new Promise(() => {
19801
19854
  }));
19802
- this.role = this.elect();
19855
+ const peers = options.peers;
19856
+ this.role = peers ? Promise.all([this.elect(), peers.joined()]).then(() => void 0) : this.elect();
19857
+ this.peers = options.peers;
19803
19858
  this.flocks = {
19804
19859
  set: (key, owner, kind) => this.flockSet(key, owner, kind),
19805
19860
  wait: (key, owner, kind, blocking) => this.flockWait(key, owner, kind, blocking),
19806
19861
  drop: (owner) => this.flockDrop(owner)
19807
19862
  };
19808
19863
  }
19864
+ peers;
19865
+ shared() {
19866
+ if (!this.leader || this.ownerOf.size > 0 || this.tokens.size > 0) return true;
19867
+ return this.peers?.crowded() === true;
19868
+ }
19809
19869
  aliveOf(kernel) {
19810
19870
  return `slicc-locks-alive:${LOCKS_PROTOCOL}:${this.root}:${kernel}`;
19811
19871
  }
@@ -20066,11 +20126,11 @@ var LockService = class {
20066
20126
  this.table.closed(pid, fd);
20067
20127
  }
20068
20128
  };
20069
- function kernelLocks(root) {
20129
+ function kernelLocks(root, peers) {
20070
20130
  const locks = globalThis.navigator?.locks;
20071
20131
  if (root === void 0 || !locks || typeof BroadcastChannel !== "function")
20072
20132
  return new LockTable();
20073
- return new LockService({ root, locks });
20133
+ return new LockService({ root, locks, ...peers ? { peers } : {} });
20074
20134
  }
20075
20135
  var ASK_OPS = /* @__PURE__ */ new Set([
20076
20136
  "set",
@@ -23526,7 +23586,9 @@ var Launcher = class {
23526
23586
  constructor(options) {
23527
23587
  this.usersMode = usersMode(options.users);
23528
23588
  this.rootFs = options.fs;
23529
- this.locks = kernelLocks(options.fs.rootName);
23589
+ const peers = options.fs.peers?.();
23590
+ this.locks = kernelLocks(options.fs.rootName, peers);
23591
+ peers?.watch((crowded) => this.changes.foreign(crowded));
23530
23592
  this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
23531
23593
  if (this.dac) this.dac.tagOf = (pid) => this.tagOf(pid);
23532
23594
  this.clipboard = new ClipboardBroker(
@@ -23607,6 +23669,7 @@ var Launcher = class {
23607
23669
  this.nodes = new VfsNodes(fs, (path) => this.released(path));
23608
23670
  this.nodes.keepsOnDisk = true;
23609
23671
  this.openFiles.add(this.nodes);
23672
+ options.fs.onPeer?.(() => this.flushOpen());
23610
23673
  const holders = [this.held, this.openFiles];
23611
23674
  this.unlinked = new UnlinkedKeeper(
23612
23675
  fs,
@@ -25267,6 +25330,9 @@ var Launcher = class {
25267
25330
  this.writers ??= this.writerStack();
25268
25331
  return this.writers;
25269
25332
  }
25333
+ async flushOpen() {
25334
+ for (const nodes of this.openFiles) await nodes.flush("/").catch(() => void 0);
25335
+ }
25270
25336
  writerStack() {
25271
25337
  const mounted = this.mounts.wrap(this.unguardedRoot);
25272
25338
  const fs = this.commandFs(this.rooted(mounted));