/** * 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; 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} c * @param {string} lockPath * @param {{ resolve: (v: unknown) => void, timer: ReturnType | null, owner: string, wantWrite: boolean }} entry */ export function bareOsRemoveFcntlWaiter(c, lockPath, entry) { const m = /** @type {Record} */ (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} c * @param {string} lockPath */ export function bareOsDrainFcntlLockWaiters(c, lockPath) { const locks = /** @type {Record; writer: string | null }>} */ ( c.bareOsCooperativeLocks ) const slot = locks?.[lockPath] if (!slot) return const m = /** @type {Record} */ (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 | 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] }