Date: Tue, 26 Aug 2014 22:33:38 -0400 From: Rich Felker <dalias@...c.org> To: musl@...ts.openwall.com Subject: sem_getvalue conformance considerations POSIX says: "The sem_getvalue() function shall update the location referenced by the sval argument to have the value of the semaphore referenced by sem without affecting the state of the semaphore. The updated value represents an actual semaphore value that occurred at some unspecified time during the call, but it need not be the actual value of the semaphore when it is returned to the calling process." musl currently implements this as: int val = sem->__val; *valp = val < 0 ? 0 : val; However, I don't think this is correct. The "semaphore value" read from __val is not the formal semaphore value, but an implementation detail: while there are waiters, after a post there is a window where __val is positive (to allow a waiter to take the semaphore) despite the formal value never becoming positive. sem_post is documented as: "If the semaphore value resulting from this operation is positive, then no threads were blocked waiting for the semaphore to become unlocked; the semaphore value is simply incremented." "If the value of the semaphore resulting from this operation is zero, then one of the threads blocked waiting for the semaphore shall be allowed to return successfully from its call to sem_wait()." So the formal "semaphore value" should always be zero while there are more waiters than posts, even if those waiters have not yet woken to take the semaphore. It seems at least semi-possible to observe incorrect behavior with the current implementation: Example 1: Initially two waiters. One call to sem_post followed by sem_getvalue should read a value of 0, not 1. In principle we could compensate for this by declaring the value zero if there are any waiters. But then: Example 2: Initially one waiter. Two calls to sem_post followed by sem_getvalue should read a value of 1, not 0. What if we try to get fancy and subtract waiters from __val? Unfortunately we can't necessarily read __val and waiters (__val) atomically together, so it's possible that one is outdated by the time we read the other, such that the resulting difference is not the correct formal semaphore value at any time during the sem_getvalue call. The one easy cop-out: We could claim the current behavior is conforming anyway, since there is no way to prove that a thread is actually blocked on a semaphore. (This is in contrast to cond vars, where having unlocked the mutex proves they've formally become waiters.) The state "blocked on semaphore" is fundamentally indistinguishable from the state of "about to enter sem_wait". Thus, we could say that, formally, there are never any waiters; sem_post always makes the semaphore value positive, and a would-be waiter formally arrives and decrements the semaphore value at some time after the post makes the value positive. Of course this is a really pathetic solution, but is there any way we can provide real, consistent, meaningful results from sem_getvalue? Or is the whole concept of sem_getvalue just so messed up that this is the best possible way to handle it? Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.