From: Alexander Monakov <amonakov@ispras.ru>
To: musl@lists.openwall.com
Subject: Re: sem_getvalue conformance considerations
Date: Sat, 30 Aug 2014 02:51:35 +0400 (MSK) [thread overview]
Message-ID: <alpine.LNX.2.00.1408292251540.5292@monopod.intra.ispras.ru> (raw)
In-Reply-To: <alpine.LNX.2.00.1408290034120.5292@monopod.intra.ispras.ru>
Hi,
To begin, I have a few questions regarding cancellation (please excuse
deviating from topic for a while):
1. It looks non-conforming not to act on pending cancellation in uncontended
sem_wait (or any cancellation point that does not invoke a syscall, for that
matter; nsz pointed out that many instances should already be handled, but
pthread_join for instance seems to miss explicit timedwait). A bug?
2. I had trouble understanding cancel_handler. What is re-raising
SIGCANCEL at the end for?
3. My understanding is that for deferred cancellation, ideally you'd want
SIGCANCEL to be delivered only as interruptions to syscalls --- that would
eliminate some scaffolding around syscall_cp including IP range check in
cancel_handler, correct?
4. If the above could be provided, it would be possible to guarantee that
pthread cancellation cleanup is executing in a signal handler context only for
asynchronous cancellation. I'd like that for my sem unwait. Too bad?
======
Trying to approach a formal description of my proposed sem ops
implementation, here's what I can do now:
1. Sem ops begin execution by performing an atomic read or read-modify-write
on val[0]. The sequence of atomic accesses establishes an order between
threads doing the ops (with respect to a given semaphore).
2. Returning from futex wait with timeout or interrupt also accesses
val[0] and is included in that order
3. The following invariant is maintained: val[0] is equal to the semaphore
value minus the number of current waiters (as given by the linear sequence of
events established above)
4. sem_post begins by performing an atomic increment on val[0]; if the
previous value was negative, there was at least one waiter, which is now
discounted from val[0]; we must arrange that one waiter eventually wakes up
and proceeds
4.1. Note: when sem_post increments negative val[0], we need that one waiter
returns successfully from sem_wait; if they were to exit exceptionally (eintr,
timeout, cancel), they would need to increment val[0] yet again;
but this will allow other threads to observe incrementing sem_getvalue despite
no new posts, as Rich noted in his email
4.2. We arrange that exactly one waiter proceeds by atomically incrementing
val[1] and futex-waking it; since we are doing that non-atomically with val[0]
update, we must guarantee that no waiters can proceed to destroy the semaphore
between val[0] and val[1] updates in sem_post
5. sem_wait begins by atomically decrementing val[0]; if the previous value
was positive, we have simply successfully decremented the semaphore;
otherwise, we have become a waiter and must suspend
5.1. sem_wait futex-waits on val[1]; on normal wakeups, it tries to
atomically-decrement-if-positive val[1] and leaves if successful
FIXME: we are reading from val[1] even though val[0] was increased long ago and
semaphore may be now positive; is there a justification for that, why can't
other threads assume the semaphore is free to be destroyed?
5.2. On eintr/timeout/cancel, a waiter must decide if it may just discount
itself as a waiter, or must deal with a racing post; in case there is a racing
post, the waiter must either consume it and return normally, or discount
itself as a waiter nevertheless and ensure that rather than causing a wake the
post increases semaphore value beyond zero
It seems there are two ways of doing it. We either prefer to consume a
pending post if available (a), or to propagate eintr/cancel (b).
5.2.a. Begin by incrementing-if-negative val[0]. If successful, we have
discounted ourselves as a waiter, so we don't need to care about concurrent
posts (there are fewer pending posts than waiters) and may propagate
eintr/timeout/cancel. If unsuccessful, there is a pending post. Consume it
and cause normal return from sem_wait (as if interruption did not happen).
Can't easily cause normal return from sem_wait if acting upon cancellation.
5.2.b. Begin by incrementing val[0] unconditionally. If it was negative, we
have discounted ourselves as a waiter; otherwise, there is a pending post, and
our increment is making it look as if the post is increasing an uncontended
semaphore (out of sequence, so other threads may observe oddly increasing
value); however there is a pending increase of val[1] and we must undo it.
Wait for val[1] to become positive by futex-waiting and then decrement it.
This looks more hairy, causes non-conforming behavior, but easier to execute
from a signal handler context for cancellation.
Does that help? Thoughts?
Alexander
next prev parent reply other threads:[~2014-08-29 22:51 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-27 2:33 Rich Felker
2014-08-27 7:05 ` Jens Gustedt
2014-08-27 7:43 ` Rich Felker
2014-08-27 10:43 ` Alexander Monakov
2014-08-27 13:32 ` Alexander Monakov
2014-08-27 19:06 ` Alexander Monakov
2014-08-27 21:06 ` Alexander Monakov
2014-08-28 20:47 ` Alexander Monakov
2014-08-29 22:51 ` Alexander Monakov [this message]
2014-08-30 5:12 ` Rich Felker
2014-09-01 17:50 ` Alexander Monakov
2015-02-27 23:21 ` semaphore redesign Alexander Monakov
2015-02-28 15:42 ` Rich Felker
2015-03-01 18:54 ` Alexander Monakov
2015-03-01 17:30 ` Szabolcs Nagy
2015-03-01 17:50 ` Szabolcs Nagy
2015-03-02 22:40 ` Alexander Monakov
2015-03-02 22:45 ` Rich Felker
2015-03-01 18:24 ` Alexander Monakov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LNX.2.00.1408292251540.5292@monopod.intra.ispras.ru \
--to=amonakov@ispras.ru \
--cc=musl@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).