|  | 
|  | 1 | +package futex | 
|  | 2 | + | 
|  | 3 | +import ( | 
|  | 4 | +	"unsafe" | 
|  | 5 | +) | 
|  | 6 | + | 
|  | 7 | +// Atomically check for cmp to still be equal to the futex value and if so, go | 
|  | 8 | +// to sleep. Return true if we were definitely awoken by a call to Wake or | 
|  | 9 | +// WakeAll, and false if we can't be sure of that. | 
|  | 10 | +func (f *Futex) Wait(cmp uint32) bool { | 
|  | 11 | +	tinygo_futex_wait((*uint32)(unsafe.Pointer(&f.Uint32)), cmp) | 
|  | 12 | + | 
|  | 13 | +	// We *could* detect a zero return value from the futex system call which | 
|  | 14 | +	// would indicate we got awoken by a Wake or WakeAll call. However, this is | 
|  | 15 | +	// what the manual page has to say: | 
|  | 16 | +	// | 
|  | 17 | +	// > Note that a wake-up can also be caused by common futex usage patterns | 
|  | 18 | +	// > in unrelated code that happened to have previously used the futex | 
|  | 19 | +	// > word's memory location (e.g., typical futex-based implementations of | 
|  | 20 | +	// > Pthreads mutexes can cause this under some conditions). Therefore, | 
|  | 21 | +	// > callers should always conservatively assume that a return value of 0 | 
|  | 22 | +	// > can mean a spurious wake-up, and use the futex word's value (i.e., the | 
|  | 23 | +	// > user-space synchronization scheme) to decide whether to continue to | 
|  | 24 | +	// > block or not. | 
|  | 25 | +	// | 
|  | 26 | +	// I'm not sure whether we do anything like pthread does, so to be on the | 
|  | 27 | +	// safe side we say we don't know whether the wakeup was spurious or not and | 
|  | 28 | +	// return false. | 
|  | 29 | +	return false | 
|  | 30 | +} | 
|  | 31 | + | 
|  | 32 | +// Like Wait, but times out after the number of nanoseconds in timeout. | 
|  | 33 | +func (f *Futex) WaitUntil(cmp uint32, timeout uint64) { | 
|  | 34 | +	tinygo_futex_wait_timeout((*uint32)(unsafe.Pointer(&f.Uint32)), cmp, timeout) | 
|  | 35 | +} | 
|  | 36 | + | 
|  | 37 | +// Wake a single waiter. | 
|  | 38 | +func (f *Futex) Wake() { | 
|  | 39 | +	tinygo_futex_wake((*uint32)(unsafe.Pointer(&f.Uint32)), 1) | 
|  | 40 | +} | 
|  | 41 | + | 
|  | 42 | +// Wake all waiters. | 
|  | 43 | +func (f *Futex) WakeAll() { | 
|  | 44 | +	const maxInt32 = 0x7fff_ffff | 
|  | 45 | +	tinygo_futex_wake((*uint32)(unsafe.Pointer(&f.Uint32)), maxInt32) | 
|  | 46 | +} | 
|  | 47 | + | 
|  | 48 | +//export tinygo_futex_wait | 
|  | 49 | +func tinygo_futex_wait(addr *uint32, cmp uint32) | 
|  | 50 | + | 
|  | 51 | +//export tinygo_futex_wait_timeout | 
|  | 52 | +func tinygo_futex_wait_timeout(addr *uint32, cmp uint32, timeout uint64) | 
|  | 53 | + | 
|  | 54 | +//export tinygo_futex_wake | 
|  | 55 | +func tinygo_futex_wake(addr *uint32, num uint32) | 
0 commit comments