ref: 303798469e8afe0e514c667f3c8c7ae2c65e58c5
dir: /lib/thread/sem+plan9.myr/
use std use sys use "atomic" pkg thread = type sem = struct _user : int32 _kern : int32 ;; const mksem : (v : uint32 -> sem) const semwait : (s : sem# -> void) const semtrywait : (s : sem# -> bool) const sempost : (s : sem# -> void) ;; const mksem = {v std.assert((v : int32) >= 0, "error: invalid initial semaphore value\n") -> [._user = (v : int32), ._kern = 0] } const semwait = {s var u = xadd(&s._user, -1) std.assert(u != ~0, "error: semaphore underflowed\n") /* When the userspace value is negative we fall back on the kernel semaphore */ if u <= 0 while sys.semacquire(&s._kern , 1) < 0 /* Interrupted, retry */ ;; ;; } const semtrywait = {s for ; ; var u = xget(&s._user) if u <= 0 -> false ;; if xcas(&s._user, u, u - 1) == u -> true ;; ;; -> false /* Unreachable */ } const sempost = {s var u = xadd(&s._user, 1) std.assert(u != 0x7fffffff, "error: semaphore overflowed\n") if u < 0 sys.semrelease(&s._kern, 1) ;; }