code wiki / (root) / nx_flock.nx

nx_flock.nx source

↩ module page · 87 lines · 2770 B

1// nx_flock.nx -- BSD-style file locking via flock(2). 2// 3// Two flavors of file locking on Linux: 4// 1. flock(2) -- whole-file advisory lock, simpler, less powerful 5// 2. fcntl(2) F_SETLK -- byte-range lock, more flexible 6// 7// This module covers (1). flock() is what most build tools and 8// daemons use: 9// - Lockfile to prevent two builds from running concurrently 10// - Daemon PID file lock (acquire on startup, release at exit) 11// - Crash-safe single-instance enforcement 12// 13// Linux RV64 syscall: 32 (flock). 14// 15// Lock types: 16// LOCK_SH shared (read) lock 17// LOCK_EX exclusive (write) lock 18// LOCK_UN unlock 19// LOCK_NB non-blocking (OR with one of the above) 20 21// nx_safety_envelope: 22// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 23// sil_target: SIL1 24// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 25// verdict: NOT_YET_EVALUATED 26 27import "syscalls.nx" 28 29const NX_SYS_FLOCK: i64 = 32 30 31const NX_LOCK_SH: i64 = 1 32const NX_LOCK_EX: i64 = 2 33const NX_LOCK_NB: i64 = 4 34const NX_LOCK_UN: i64 = 8 35 36// Acquire a lock on `fd`. Blocks unless NX_LOCK_NB is set. 37// Returns 0 on success, -EWOULDBLOCK (-11) if NB and contended, 38// other negative errno on failure. 39func nx_flock(fd: i64, op: i64) -> i64 { 40 return __syscall(NX_SYS_FLOCK, fd, op, 0, 0, 0, 0) 41} 42 43// Convenience: acquire exclusive blocking. 44func nx_flock_ex(fd: i64) -> i64 { 45 return nx_flock(fd, NX_LOCK_EX) 46} 47 48// Convenience: acquire exclusive non-blocking. Returns 1 if 49// acquired, 0 if contended, negative errno on failure. 50func nx_flock_try_ex(fd: i64) -> i64 { 51 let r: i64 = nx_flock(fd, NX_LOCK_EX | NX_LOCK_NB) 52 if r == 0 { return 1 } 53 if r == 0 - 11 { return 0 } // -EWOULDBLOCK 54 return r 55} 56 57func nx_flock_sh(fd: i64) -> i64 { 58 return nx_flock(fd, NX_LOCK_SH) 59} 60 61func nx_flock_un(fd: i64) -> i64 { 62 return nx_flock(fd, NX_LOCK_UN) 63} 64 65// ---- self-test --------------------------------------------------- 66 67func main() -> i64 { 68 if NX_LOCK_SH != 1 { return __syscall(93, 1, 0, 0, 0, 0, 0) } 69 if NX_LOCK_EX != 2 { return __syscall(93, 2, 0, 0, 0, 0, 0) } 70 if NX_LOCK_NB != 4 { return __syscall(93, 3, 0, 0, 0, 0, 0) } 71 if NX_LOCK_UN != 8 { return __syscall(93, 4, 0, 0, 0, 0, 0) } 72 73 // Lock stderr (always a valid fd; flock on it is harmless and 74 // immediately released). 75 let fd: i64 = 2 76 let r1: i64 = nx_flock_try_ex(fd) 77 // Some hosts disallow flock on stderr (returns -EBADF); 78 // accept either success(1) or 0/negative without crashing. 79 if r1 < -100 { return __syscall(93, 5, 0, 0, 0, 0, 0) } 80 81 if r1 == 1 { 82 let r2: i64 = nx_flock_un(fd) 83 if r2 != 0 { return __syscall(93, 6, 0, 0, 0, 0, 0) } 84 } 85 86 return 0 87}