futex_wake is the Linux FUTEX_WAKE operation for resuming executions suspended on a specified memory address. It treats the address as a wait queue: the count selects how many queued executions the operating system resumes, while a count of 0 resumes all suspended executions. section 12.3.1
A wake operation follows these rules:
- Targets the wait queue associated with a memory address. section 12.3.1
- Resumes executions from the front of that address’s queue. section 12.3.1
- Wakes one execution when count is 1 and all suspended executions when count is 0. section 12.3.1
- Avoids the system call when an optimized lock state shows that no execution is waiting. section 12.3.2
Waking a waiter while unlocking
A futex-based lock stores 0 for unlocked, 1 for locked, and 2 for locked with waiters. Unlocking swaps the value to 0; if the old value was 2, it calls futex_wakeup(address, 1) to resume one waiting execution. The wake is therefore performed only when contention was recorded. section 12.3.2
Listing 12.12 Waking up a futex only when it’s needed
package listing12_12 import "sync/atomic" type FutexLock int32 func (f *FutexLock) Unlock() { oldValue := atomic.SwapInt32((*int32)(f), 0) #1 if oldValue == 2 { #2 futex_wakeup((*int32)(f), 1) #3 } } #1 Marks the lock as unlocked, storing the old value #2 If the old value was 2, it means executions are waiting. #3 Wakes up one execution
See the compact pseudo-Go unlock implementation that records the previous lock state and wakes one execution only when waiters existed. section 12.3.2
