class Semaphore
Defined at line 33 of file ../../zircon/kernel/include/kernel/semaphore.h
A basic counting semaphore used to control access to a shared resource.
Think of Semaphore as a gatekeeper that allows a certain number of threads to
pass through a gate so they can access some resource.
Threads queue up at the gate by calling Wait and then block until the
gatekeeper lets them through or they give up and leave the queue because of
timeout or thread signal. In the case of timeout or thread signal, the
waiter may not proceed to the resource.
Calling Post tells the gatekeeper that they may immediately admit one through
the gate (if there's a waiter in the queue) or admit one in the future once a
waiter has queued up.
Public Methods
void Post (OwnedWaitQueue * queue_to_own)
Every call to this method must wake one waiter unless the queue is empty.
When leaving this method, we must have either
- incremented a non-negative count or
- unblocked one thread and
- left an empty queue with a count of zero or
- left a non-empty queue with negative count
Defined at line 25 of file ../../zircon/kernel/kernel/semaphore.cc
void Semaphore (int64_t initial_count)
Defined at line 35 of file ../../zircon/kernel/include/kernel/semaphore.h
void Semaphore (const Semaphore & )
Defined at line 37 of file ../../zircon/kernel/include/kernel/semaphore.h
void Semaphore (Semaphore && )
Defined at line 38 of file ../../zircon/kernel/include/kernel/semaphore.h
Semaphore & operator= (const Semaphore & )
Defined at line 39 of file ../../zircon/kernel/include/kernel/semaphore.h
void ~Semaphore ()
Defined at line 40 of file ../../zircon/kernel/include/kernel/semaphore.h
int64_t count ()
Observe the current internal count of the semaphore.
This should only be used for testing/diagnostic purposes.
Defined at line 67 of file ../../zircon/kernel/include/kernel/semaphore.h
uint64_t num_waiters ()
Observe the current internal count of waiters.
This should only be used for testing/diagnostic purposes.
Defined at line 72 of file ../../zircon/kernel/include/kernel/semaphore.h
zx_status_t Wait (const Deadline & deadline)
Handling failed waits -- Waits can fail due to timeout or thread signal.
When a Wait fails, the caller cannot proceed to the resource guarded by the
semaphore. It's as if the waiter gave up and left. We want to ensure failed
waits do not impact other waiters. While it seems like a failed wait should
simply "undo" its decrement, it is not safe to do so in Wait. Instead, we
"fix" the count in subsequent call to Post.
To understand why we can't simply fix the count in Wait after returning from
Block, let's look at an alternative (buggy) implementation of Post and Wait.
In this hypothetical implementation, Post increments and Wait decrements
before Block, but also increments if Block returns an error. With this
hypothetical implementation in mind, consider the following sequence of
operations:
Q C
0 0
1W 1 -1 B
1T 0 -1
2P 0 0
3W 1 -1 B
1R 1 0
The way to read the sequence above is that the wait queue (Q) starts empty
and the count (C) starts at zero. Thread1 calls Wait (1W) and blocks (B).
Thread1's times out (1T) and is removed from the queue, but has not yet
resumed execution. Thread2 calls Post (2P), but does not unblock any threads
because it finds an empty queue. Thread3 calls Wait (3W) and blocks (B).
Thread1 returns from Block, resumes execution (1R), and increments the count.
At this point Thread3 is blocked as it should be (two Posts and one failed
Wait), however, a subsequent call to Post will not unblock it. We have a
"lost wakeup".
Defined at line 183 of file ../../zircon/kernel/kernel/semaphore.cc