- Sync declared POSIX profile, compliance matrix, syscalls examples, dashboard - Extend holepunch clone sync reporting; bump protomux/hyperswarm lock fixture schema - Optional shell read builtin (BARE_OS_SHELL_READ_*); host env passthrough - Expand bareOsGetconfSysconf / getconf; pathconf for acct/union/mirror - Wasm optional bare_os_monotonic_ms; replication live snapshot hints schema - Socket bridge SO_RCVBUF/SO_SNDBUF; mq priority + FIFO ordering + tests - Extract cooperative fcntl lock helpers; FIFO waiter drain tests - Peer admission audit helpers, rate limit + redaction tests; security_posture schema - CI: verify-ctx requires CHANGELOG row, d.ts version mention, compatibility matrix - Warm-cache microbench (vfs suite); boot budget / metrics cohesion (prior work) - Handbook, KERNEL_CONTRACT, kernel-program, env appendix, README, users-manual, schemas Kernel bundle + seeder rsync + coreutils build verified via npm test.
78 lines
2.4 KiB
JavaScript
78 lines
2.4 KiB
JavaScript
/**
|
|
* Cooperative advisory **`fcntl`** lock slot + **`F_SETLKW`** waiter drain (**FIFO** per path).
|
|
* Used by **`packages/bare-os-booter/index.js`** **`bareOsSyscall('fcntl')`**.
|
|
*/
|
|
|
|
/**
|
|
* @param {{ readers: Set<string>; writer: string | null }} slot
|
|
* @param {string} owner
|
|
* @param {boolean} wantWrite
|
|
*/
|
|
export function bareOsTryAcquireCooperativeLock(slot, owner, wantWrite) {
|
|
if (wantWrite) {
|
|
if (slot.writer && slot.writer !== owner) return false
|
|
if (
|
|
slot.readers.size > 0 &&
|
|
[...slot.readers].some((sid) => sid !== owner)
|
|
) {
|
|
return false
|
|
}
|
|
slot.readers.clear()
|
|
slot.writer = owner
|
|
return true
|
|
}
|
|
if (slot.writer && slot.writer !== owner) return false
|
|
slot.readers.add(owner)
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* @param {Record<string, unknown>} c
|
|
* @param {string} lockPath
|
|
* @param {{ resolve: (v: unknown) => void, timer: ReturnType<typeof setTimeout> | null, owner: string, wantWrite: boolean }} entry
|
|
*/
|
|
export function bareOsRemoveFcntlWaiter(c, lockPath, entry) {
|
|
const m = /** @type {Record<string, unknown>} */ (c)
|
|
const qm = m.bareOsFcntlLockWaitQueues
|
|
if (!qm || typeof qm !== 'object') return
|
|
const q = /** @type {unknown[]} */ (qm[lockPath])
|
|
if (!Array.isArray(q)) return
|
|
const i = q.indexOf(entry)
|
|
if (i >= 0) q.splice(i, 1)
|
|
if (q.length === 0) delete qm[lockPath]
|
|
}
|
|
|
|
/**
|
|
* @param {Record<string, unknown>} c
|
|
* @param {string} lockPath
|
|
*/
|
|
export function bareOsDrainFcntlLockWaiters(c, lockPath) {
|
|
const locks = /** @type {Record<string, { readers: Set<string>; writer: string | null }>} */ (
|
|
c.bareOsCooperativeLocks
|
|
)
|
|
const slot = locks?.[lockPath]
|
|
if (!slot) return
|
|
const m = /** @type {Record<string, unknown>} */ (c)
|
|
const qm = m.bareOsFcntlLockWaitQueues
|
|
const q = qm?.[lockPath]
|
|
if (!Array.isArray(q) || q.length === 0) return
|
|
while (q.length > 0) {
|
|
const w = /** @type {{ resolve: (v: unknown) => void, timer: ReturnType<typeof setTimeout> | null, owner: string, wantWrite: boolean }} */ (
|
|
q[0]
|
|
)
|
|
if (!bareOsTryAcquireCooperativeLock(slot, w.owner, w.wantWrite)) break
|
|
q.shift()
|
|
if (w.timer) clearTimeout(w.timer)
|
|
w.resolve({
|
|
ok: true,
|
|
op: 'fcntl',
|
|
cmd: 'F_SETLKW',
|
|
path: lockPath,
|
|
cooperative: true,
|
|
locked: w.wantWrite ? 'write' : 'read',
|
|
blockedWait: true
|
|
})
|
|
}
|
|
if (q.length === 0 && qm && typeof qm === 'object') delete qm[lockPath]
|
|
}
|