Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.programming.threads > #184 > unrolled thread

cond signal wait

Started byp6 c6d6 <p6c6d6@gmail.com>
First post2011-05-24 18:56 -0700
Last post2011-05-31 14:07 -0700
Articles 19 — 5 participants

Back to article view | Back to comp.programming.threads


Contents

  cond signal wait p6 c6d6 <p6c6d6@gmail.com> - 2011-05-24 18:56 -0700
    Re: cond signal wait Anthony Williams <anthony.ajw@gmail.com> - 2011-05-25 08:46 +0100
      Re: cond signal wait p6 c6d6 <p6c6d6@gmail.com> - 2011-05-25 05:44 -0700
        Re: cond signal wait Anthony Williams <anthony.ajw@gmail.com> - 2011-05-25 15:57 +0100
          Re: cond signal wait p6 c6d6 <p6c6d6@gmail.com> - 2011-05-25 08:34 -0700
            Re: cond signal wait Anthony Williams <anthony.ajw@gmail.com> - 2011-05-25 16:53 +0100
              Re: cond signal wait Alexander Terekhov <terekhov@web.de> - 2011-05-25 19:16 +0200
            Re: cond signal wait David Schwartz <davids@webmaster.com> - 2011-05-26 09:51 -0700
            Re: cond signal wait Joshua Maurice <joshuamaurice@gmail.com> - 2011-05-26 14:48 -0700
              Re: cond signal wait David Schwartz <davids@webmaster.com> - 2011-05-26 23:20 -0700
                Re: cond signal wait Joshua Maurice <joshuamaurice@gmail.com> - 2011-05-27 14:50 -0700
                  Re: cond signal wait David Schwartz <davids@webmaster.com> - 2011-05-27 15:15 -0700
                    Re: cond signal wait Alexander Terekhov <terekhov@web.de> - 2011-05-28 15:48 +0200
              Re: cond signal wait Alexander Terekhov <terekhov@web.de> - 2011-05-27 16:01 +0200
                Re: cond signal wait David Schwartz <davids@webmaster.com> - 2011-05-27 12:34 -0700
                  Re: cond signal wait Alexander Terekhov <terekhov@web.de> - 2011-05-28 14:24 +0200
                    Re: cond signal wait David Schwartz <davids@webmaster.com> - 2011-05-29 01:33 -0700
                      Re: cond signal wait Alexander Terekhov <terekhov@web.de> - 2011-05-31 15:32 +0200
                        Re: cond signal wait David Schwartz <davids@webmaster.com> - 2011-05-31 14:07 -0700

#184 — cond signal wait

Fromp6 c6d6 <p6c6d6@gmail.com>
Date2011-05-24 18:56 -0700
Subjectcond signal wait
Message-ID<bff468ff-45d7-4e18-8ff5-95238eb94585@c1g2000yqe.googlegroups.com>
hi,

what happens if a thread does a condition signal for a thread that has
not yet done
condition wait. is this not legitimate scenario, according to my
limited experience in
thread programming, i feel it is always possible. am i missing
anything.or are there any
ways to deterministically signal and wait. please shed some light.

thanks

[toc] | [next] | [standalone]


#186

FromAnthony Williams <anthony.ajw@gmail.com>
Date2011-05-25 08:46 +0100
Message-ID<87aaebte7o.fsf@justsoftwaresolutions.co.uk>
In reply to#184
p6 c6d6 <p6c6d6@gmail.com> writes:

> what happens if a thread does a condition signal for a thread that has
> not yet done
> condition wait. is this not legitimate scenario, according to my
> limited experience in
> thread programming, i feel it is always possible. am i missing
> anything.or are there any
> ways to deterministically signal and wait. please shed some light.

If you signal a condition variable with no threads blocked in a waiting
function then the signal has no effect.

Anthony
-- 
Author of C++ Concurrency in Action     http://www.stdthread.co.uk/book/
just::thread C++0x thread library             http://www.stdthread.co.uk
Just Software Solutions Ltd       http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

[toc] | [prev] | [next] | [standalone]


#187

Fromp6 c6d6 <p6c6d6@gmail.com>
Date2011-05-25 05:44 -0700
Message-ID<98cd47de-73d9-48e9-ac18-cc01cac1bb48@z7g2000prh.googlegroups.com>
In reply to#186
On May 25, 12:46 pm, Anthony Williams <anthony....@gmail.com> wrote:
> p6 c6d6 <p6c...@gmail.com> writes:
> > what happens if a thread does a condition signal for a thread that has
> > not yet done
> > condition wait. is this not legitimate scenario, according to my
> > limited experience in
> > thread programming, i feel it is always possible. am i missing
> > anything.or are there any
> > ways to deterministically signal and wait. please shed some light.
>
> If you signal a condition variable with no threads blocked in a waiting
> function then the signal has no effect.
>
> Anthony
> --
> Author of C++ Concurrency in Action    http://www.stdthread.co.uk/book/
> just::thread C++0x thread library            http://www.stdthread.co.uk
> Just Software Solutions Ltd      http://www.justsoftwaresolutions.co.uk
> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

that is fine. but what if the thread which is suppose to recv the
signal
waits after the signal was delivered. doesn't it wait forever. let's
assume
a reader writer scenario. the writer writes one byte and waits for the
reader
to read and signal the writer. now if the writer writes some data and
does
a cond signal. during this time the reader was busy doing something
else
or didn't get a chance to run at all. now the reader waits on
condition, and
the signal was already lost. both reader and writer wait forever.
isn't this a
valid scenario.

thanks

[toc] | [prev] | [next] | [standalone]


#188

FromAnthony Williams <anthony.ajw@gmail.com>
Date2011-05-25 15:57 +0100
Message-ID<87lixubzfu.fsf@justsoftwaresolutions.co.uk>
In reply to#187
p6 c6d6 <p6c6d6@gmail.com> writes:

> On May 25, 12:46 pm, Anthony Williams <anthony....@gmail.com> wrote:
>> p6 c6d6 <p6c...@gmail.com> writes:
>> > what happens if a thread does a condition signal for a thread that has
>> > not yet done
>> > condition wait. is this not legitimate scenario, according to my
>> > limited experience in
>> > thread programming, i feel it is always possible. am i missing
>> > anything.or are there any
>> > ways to deterministically signal and wait. please shed some light.
>>
>> If you signal a condition variable with no threads blocked in a waiting
>> function then the signal has no effect.
>>
>> Anthony
>> --
>> Author of C++ Concurrency in Action    http://www.stdthread.co.uk/book/
>> just::thread C++0x thread library            http://www.stdthread.co.uk
>> Just Software Solutions Ltd      http://www.justsoftwaresolutions.co.uk
>> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
>
> that is fine. but what if the thread which is suppose to recv the
> signal
> waits after the signal was delivered. doesn't it wait forever. 

Yes, if there is no-one waiting when the condvar was signalled, then the
signal is ignored, and if the condvar is not subsequently signalled then
any subsequent waiting threads will block forever, unless they use a
timeout.

> let's assume a reader writer scenario. the writer writes one byte and
> waits for the reader to read and signal the writer. now if the writer
> writes some data and does a cond signal. during this time the reader
> was busy doing something else or didn't get a chance to run at
> all. now the reader waits on condition, and the signal was already
> lost. both reader and writer wait forever.  isn't this a valid
> scenario.

Yes. However, if you hold the mutex that is associated with the cond var
whilst signalling, then you can avoid this: if the signalling thread has
the mutex then either (a) the waiting thread hasn't yet acquired the
mutex to check if the data is ready, or (b) the waiting thread is
blocked in the wait on the condvar.

Anthony
-- 
Author of C++ Concurrency in Action     http://www.stdthread.co.uk/book/
just::thread C++0x thread library             http://www.stdthread.co.uk
Just Software Solutions Ltd       http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

[toc] | [prev] | [next] | [standalone]


#189

Fromp6 c6d6 <p6c6d6@gmail.com>
Date2011-05-25 08:34 -0700
Message-ID<a05141df-cede-4929-9e8d-4b9394fd6858@22g2000prx.googlegroups.com>
In reply to#188
On May 25, 7:57 pm, Anthony Williams <anthony....@gmail.com> wrote:
> p6 c6d6 <p6c...@gmail.com> writes:
> > On May 25, 12:46 pm, Anthony Williams <anthony....@gmail.com> wrote:
> >> p6 c6d6 <p6c...@gmail.com> writes:
> >> > what happens if a thread does a condition signal for a thread that has
> >> > not yet done
> >> > condition wait. is this not legitimate scenario, according to my
> >> > limited experience in
> >> > thread programming, i feel it is always possible. am i missing
> >> > anything.or are there any
> >> > ways to deterministically signal and wait. please shed some light.
>
> >> If you signal a condition variable with no threads blocked in a waiting
> >> function then the signal has no effect.
>
> >> Anthony
> >> --
> >> Author of C++ Concurrency in Action    http://www.stdthread.co.uk/book/
> >> just::thread C++0x thread library            http://www.stdthread.co.uk
> >> Just Software Solutions Ltd      http://www.justsoftwaresolutions.co.uk
> >> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
>
> > that is fine. but what if the thread which is suppose to recv the
> > signal
> > waits after the signal was delivered. doesn't it wait forever.
>
> Yes, if there is no-one waiting when the condvar was signalled, then the
> signal is ignored, and if the condvar is not subsequently signalled then
> any subsequent waiting threads will block forever, unless they use a
> timeout.
>
> > let's assume a reader writer scenario. the writer writes one byte and
> > waits for the reader to read and signal the writer. now if the writer
> > writes some data and does a cond signal. during this time the reader
> > was busy doing something else or didn't get a chance to run at
> > all. now the reader waits on condition, and the signal was already
> > lost. both reader and writer wait forever.  isn't this a valid
> > scenario.
>
> Yes. However, if you hold the mutex that is associated with the cond var
> whilst signalling, then you can avoid this: if the signalling thread has
> the mutex then either (a) the waiting thread hasn't yet acquired the
> mutex to check if the data is ready, or (b) the waiting thread is
> blocked in the wait on the condvar.
>
> Anthony
> --
> Author of C++ Concurrency in Action    http://www.stdthread.co.uk/book/
> just::thread C++0x thread library            http://www.stdthread.co.uk
> Just Software Solutions Ltd      http://www.justsoftwaresolutions.co.uk
> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

> hasn't yet acquired the
> mutex to check if the data is ready

Ha! so, the key is the flag which specifies that the data is ready,
before waiting on a condition variable the thread should always check
if
the work is already available if so there is no need to wait.

> (a) the waiting thread hasn't yet acquired the
> mutex to check if the data is ready,

i didn't quiet get this point, holding the mutex just protects from
the race for the flag
and condition variable, it doesn't avoid the deadlock.

thanks

[toc] | [prev] | [next] | [standalone]


#190

FromAnthony Williams <anthony.ajw@gmail.com>
Date2011-05-25 16:53 +0100
Message-ID<87hb8ibwur.fsf@justsoftwaresolutions.co.uk>
In reply to#189
p6 c6d6 <p6c6d6@gmail.com> writes:

> On May 25, 7:57 pm, Anthony Williams <anthony....@gmail.com> wrote:
>> p6 c6d6 <p6c...@gmail.com> writes:
>> > let's assume a reader writer scenario. the writer writes one byte and
>> > waits for the reader to read and signal the writer. now if the writer
>> > writes some data and does a cond signal. during this time the reader
>> > was busy doing something else or didn't get a chance to run at
>> > all. now the reader waits on condition, and the signal was already
>> > lost. both reader and writer wait forever.  isn't this a valid
>> > scenario.
>>
>> Yes. However, if you hold the mutex that is associated with the cond var
>> whilst signalling, then you can avoid this: if the signalling thread has
>> the mutex then either (a) the waiting thread hasn't yet acquired the
>> mutex to check if the data is ready, or (b) the waiting thread is
>> blocked in the wait on the condvar.

void waiter()
{
        lock mutex; // **A**
        while(!data ready) // loop to handle spurious wake-ups
                wait on condvar; // **B** releases mutex
        process data;
        unlock mutex; // **C**
}

void signaller()
{
        lock mutex;
        // if we get here, waiter() hasn't yet executed **A**
        // or is blocked in **B**, so will be woken by signal
        // or has executed line **C** so doesn't care about signal
        mark data as ready;
        signal condvar;
        unlock mutex;
}

Anthony
-- 
Author of C++ Concurrency in Action     http://www.stdthread.co.uk/book/
just::thread C++0x thread library             http://www.stdthread.co.uk
Just Software Solutions Ltd       http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

[toc] | [prev] | [next] | [standalone]


#191

FromAlexander Terekhov <terekhov@web.de>
Date2011-05-25 19:16 +0200
Message-ID<4DDD3950.81DEDF32@web.de>
In reply to#190
Anthony Williams wrote:

[...]

> void signaller()
> {
>         lock mutex;
>         // if we get here, waiter() hasn't yet executed **A**
>         // or is blocked in **B**, so will be woken by signal
>         // or has executed line **C** so doesn't care about signal
>         mark data as ready;
>         signal condvar;
>         unlock mutex;
> }
          lock mutex;
          // if we get here, waiter() hasn't yet executed **A**
          // or is blocked in **B**, so will be woken by signal
          // or has executed line **C** so doesn't care about signal
          mark data as ready;
          unlock mutex;
          signal condvar;

is the regular case.

signalling prior to unlock is special.

regards,
alexander.

[toc] | [prev] | [next] | [standalone]


#192

FromDavid Schwartz <davids@webmaster.com>
Date2011-05-26 09:51 -0700
Message-ID<f83d65a2-b249-43fb-84a0-195f88c90d56@18g2000prd.googlegroups.com>
In reply to#189
On May 25, 8:34 am, p6 c6d6 <p6c...@gmail.com> wrote:

> Ha! so, the key is the flag which specifies that the data is ready,
> before waiting on a condition variable the thread should always check
> if
> the work is already available if so there is no need to wait.

You'd have to be an idiot to wait for something that has already
happened.

> > (a) the waiting thread hasn't yet acquired the
> > mutex to check if the data is ready,

> i didn't quiet get this point, holding the mutex just protects from
> the race for the flag
> and condition variable, it doesn't avoid the deadlock.

It does prevent the deadlock. The race is between the flag and the
condition variable. Since you check the flag and start to wait while
holding the mutex, the mutex prevents a race between the flag and the
condition variable wait. The wait can only occur if the flag changes
after you check the flag and decide to wait but before you actually
start the wait.

DS

[toc] | [prev] | [next] | [standalone]


#193

FromJoshua Maurice <joshuamaurice@gmail.com>
Date2011-05-26 14:48 -0700
Message-ID<8ab4e07e-2b9b-4375-b425-dc03e6d017d5@f15g2000pro.googlegroups.com>
In reply to#189
On May 25, 8:34 am, p6 c6d6 <p6c...@gmail.com> wrote:
> On May 25, 7:57 pm, Anthony Williams <anthony....@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > p6 c6d6 <p6c...@gmail.com> writes:
> > > On May 25, 12:46 pm, Anthony Williams <anthony....@gmail.com> wrote:
> > >> p6 c6d6 <p6c...@gmail.com> writes:
> > >> > what happens if a thread does a condition signal for a thread that has
> > >> > not yet done
> > >> > condition wait. is this not legitimate scenario, according to my
> > >> > limited experience in
> > >> > thread programming, i feel it is always possible. am i missing
> > >> > anything.or are there any
> > >> > ways to deterministically signal and wait. please shed some light.
>
> > >> If you signal a condition variable with no threads blocked in a waiting
> > >> function then the signal has no effect.
>
> > >> Anthony
> > >> --
> > >> Author of C++ Concurrency in Action    http://www.stdthread.co.uk/book/
> > >> just::thread C++0x thread library            http://www.stdthread.co.uk
> > >> Just Software Solutions Ltd      http://www.justsoftwaresolutions.co.uk
> > >> 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
>
> > > that is fine. but what if the thread which is suppose to recv the
> > > signal
> > > waits after the signal was delivered. doesn't it wait forever.
>
> > Yes, if there is no-one waiting when the condvar was signalled, then the
> > signal is ignored, and if the condvar is not subsequently signalled then
> > any subsequent waiting threads will block forever, unless they use a
> > timeout.
>
> > > let's assume a reader writer scenario. the writer writes one byte and
> > > waits for the reader to read and signal the writer. now if the writer
> > > writes some data and does a cond signal. during this time the reader
> > > was busy doing something else or didn't get a chance to run at
> > > all. now the reader waits on condition, and the signal was already
> > > lost. both reader and writer wait forever.  isn't this a valid
> > > scenario.
>
> > Yes. However, if you hold the mutex that is associated with the cond var
> > whilst signalling, then you can avoid this: if the signalling thread has
> > the mutex then either (a) the waiting thread hasn't yet acquired the
> > mutex to check if the data is ready, or (b) the waiting thread is
> > blocked in the wait on the condvar.
>
> > Anthony
> > --
> > Author of C++ Concurrency in Action    http://www.stdthread.co.uk/book/
> > just::thread C++0x thread library            http://www.stdthread.co.uk
> > Just Software Solutions Ltd      http://www.justsoftwaresolutions.co.uk
> > 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
> > hasn't yet acquired the
> > mutex to check if the data is ready
>
> Ha! so, the key is the flag which specifies that the data is ready,
> before waiting on a condition variable the thread should always check
> if
> the work is already available if so there is no need to wait.
>
> > (a) the waiting thread hasn't yet acquired the
> > mutex to check if the data is ready,
>
> i didn't quiet get this point, holding the mutex just protects from
> the race for the flag
> and condition variable, it doesn't avoid the deadlock.

See Anthony Williams's post else-thread for the idiomatic way, and the
way you should do it a majority of the time, and the default choice,
for using condition variables.

Note that actually the idiomatic way is to signal after the critical
section instead of inside it (and definitely not before!!). Signalling
inside the critical section doesn't break correctness, but it may (?)
result in some additional work by the scheduler as it moves a thread
from the cond wait state to the waiting for mutex state, and maybe (?)
some additional context swaps, both of which are bad for performance.

Also note how he uses "while" instead of "if"

>         while(!data ready) // loop to handle spurious wake-ups
>                wait on condvar; // **B** releases mutex

This is required because of spurious wakeups with POSIX (and possibly
other forms of condition variables). In POSIX condition variables,
sometimes the waiter is woken up without a corresponding signal nor
broadcast, randomly, for no particular reason. (Implementation
detail.) That's why you need to recheck the shared data to see if
there actually was a signal; hence "while" not "if".

[toc] | [prev] | [next] | [standalone]


#195

FromDavid Schwartz <davids@webmaster.com>
Date2011-05-26 23:20 -0700
Message-ID<c7b7a994-fb4d-4bf9-bb20-8bf9fceaa5b9@35g2000prp.googlegroups.com>
In reply to#193
On May 26, 2:48 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:

> Also note how he uses "while" instead of "if"
>
> >         while(!data ready) // loop to handle spurious wake-ups
> >                wait on condvar; // **B** releases mutex
>
> This is required because of spurious wakeups with POSIX (and possibly
> other forms of condition variables). In POSIX condition variables,
> sometimes the waiter is woken up without a corresponding signal nor
> broadcast, randomly, for no particular reason. (Implementation
> detail.) That's why you need to recheck the shared data to see if
> there actually was a signal; hence "while" not "if".

Even without spurious wakeups, it is usually still necessary.
Consider:

1) Queue servicing threads A and B find the queue empty and block on
the condition variable.
2) Thread C puts an object on the queue and calls pthread_cond_signal,
waking thread A.
3) Thread D puts an object on the queue and calls pthread_cond_signal,
waking thread B.
4) Thread A pulls the first object from the queue, process it.
5) Thread A re-acquires the mutex and checks the predicate. It finds
the queue non-empty and pulls the second object from the queue. It
releases the mutex to process the second object.
6) Thread B gets the CPU finally -- the queue is empty. The wakeup
seems spurious.

By the way, it is precisely this race that is the reason spurious
wakeups are allowed by POSIX. The situation above is a problem that
can only be resolved by checking the predicate after a wakeup. But
condition variables have no predicate, they are stateless, so there is
no good way the condition variable logic itself can prevent spurious
wakeups. Only checking the predicate does that.

DS

[toc] | [prev] | [next] | [standalone]


#199

FromJoshua Maurice <joshuamaurice@gmail.com>
Date2011-05-27 14:50 -0700
Message-ID<fb054ce9-8efe-4540-9cdd-cdfd0790ce3d@s16g2000prf.googlegroups.com>
In reply to#195
On May 26, 11:20 pm, David Schwartz <dav...@webmaster.com> wrote:
> On May 26, 2:48 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:
>
> > Also note how he uses "while" instead of "if"
>
> > >         while(!data ready) // loop to handle spurious wake-ups
> > >                wait on condvar; // **B** releases mutex
>
> > This is required because of spurious wakeups with POSIX (and possibly
> > other forms of condition variables). In POSIX condition variables,
> > sometimes the waiter is woken up without a corresponding signal nor
> > broadcast, randomly, for no particular reason. (Implementation
> > detail.) That's why you need to recheck the shared data to see if
> > there actually was a signal; hence "while" not "if".
>
> Even without spurious wakeups, it is usually still necessary.

Agreed. Depends on the design. In some rather contrived and simple
designs, without spurious wakeups, you could get away with just an
"if". I wouldn't suggest it. In an earlier draft of my post, I
mentioned how it's also easier to reason about correctness with
"while" instead of "true", but I trimmed it out. Apparently I should
have kept it.

> Consider:
>
> 1) Queue servicing threads A and B find the queue empty and block on
> the condition variable.
> 2) Thread C puts an object on the queue and calls pthread_cond_signal,
> waking thread A.
> 3) Thread D puts an object on the queue and calls pthread_cond_signal,
> waking thread B.
> 4) Thread A pulls the first object from the queue, process it.
> 5) Thread A re-acquires the mutex and checks the predicate. It finds
> the queue non-empty and pulls the second object from the queue. It
> releases the mutex to process the second object.
> 6) Thread B gets the CPU finally -- the queue is empty. The wakeup
> seems spurious.
>
> By the way, it is precisely this race that is the reason spurious
> wakeups are allowed by POSIX. The situation above is a problem that
> can only be resolved by checking the predicate after a wakeup. But
> condition variables have no predicate, they are stateless, so there is
> no good way the condition variable logic itself can prevent spurious
> wakeups. Only checking the predicate does that.

Really? That doesn't seem to be an argument for spurious wakeups. That
seems to be a good argument for using "while" instead of "if" by
default.

I thought that spurious wakeups were allowed because of signal
handling. As best as I can remember, it goes something like: A thread
is waiting on a condition variable. It receives a thread specific
signal. Due to the details of how this is can be / commonly is
implemented, the system call used to implement pthread_cond_wait will
return EINTR after the thread is used to process the signal. The
pthread_cond_wait cannot simply go back to waiting on the cond var
because it might have lost a signal in the meantime, and thus it
returns to the caller who can recheck invariants and decide if he
needs to go back to waiting.

[toc] | [prev] | [next] | [standalone]


#200

FromDavid Schwartz <davids@webmaster.com>
Date2011-05-27 15:15 -0700
Message-ID<a014c2ff-7449-4010-b104-1a8ee6309eea@34g2000pru.googlegroups.com>
In reply to#199
On May 27, 2:50 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:

> > By the way, it is precisely this race that is the reason spurious
> > wakeups are allowed by POSIX. The situation above is a problem that
> > can only be resolved by checking the predicate after a wakeup. But
> > condition variables have no predicate, they are stateless, so there is
> > no good way the condition variable logic itself can prevent spurious
> > wakeups. Only checking the predicate does that.

> Really? That doesn't seem to be an argument for spurious wakeups. That
> seems to be a good argument for using "while" instead of "if" by
> default.

Except that the condition variable implementation *can't* use 'while'
instead of 'if'. To use 'while', it would have to check the predicate,
and the condition variable has no access to the predicate. The
condition variable has no need for the 'if' because it waits
unconditionally. This is why a standard for a stateless wait generally
has no choice but to specify that spurious wakeups are possible.

> I thought that spurious wakeups were allowed because of signal
> handling. As best as I can remember, it goes something like: A thread
> is waiting on a condition variable. It receives a thread specific
> signal. Due to the details of how this is can be / commonly is
> implemented, the system call used to implement pthread_cond_wait will
> return EINTR after the thread is used to process the signal. The
> pthread_cond_wait cannot simply go back to waiting on the cond var
> because it might have lost a signal in the meantime, and thus it
> returns to the caller who can recheck invariants and decide if he
> needs to go back to waiting.

It's the same point. If the condition variable code had access to the
predicate, it could make a sensible decision of whether to repeat the
wait or not. But since the condition variable implementation has no
access to the predicate, the only sensible way to handle a case where
there might have been a signal is to return.

DS

[toc] | [prev] | [next] | [standalone]


#203

FromAlexander Terekhov <terekhov@web.de>
Date2011-05-28 15:48 +0200
Message-ID<4DE0FD20.8FA7464A@web.de>
In reply to#200
David Schwartz wrote:

[... "if" v. "while" ...]

> It's the same point. If the condition variable code had access to the
> predicate, it could make a sensible decision of whether to repeat the
> wait or not. But since the condition variable implementation has no
> access to the predicate, the only sensible way to handle a case where
> there might have been a signal is to return.

AFAIK, when Hoare invented condition variables he saw only signal (no
broadcast) operation and "if" (not "while") for the wait with signalling
done under protection of mutex (hand-off of mutex ownership from
signaller to signallee akin to semas). Later, MESA folks introduced
broadcast, changed "if" to "while", and allowed signalling without
holding mutex.

regards,
alexander.

[toc] | [prev] | [next] | [standalone]


#197

FromAlexander Terekhov <terekhov@web.de>
Date2011-05-27 16:01 +0200
Message-ID<4DDFAEC8.531D6882@web.de>
In reply to#193
Joshua Maurice wrote:
[...]
> Note that actually the idiomatic way is to signal after the critical
> section instead of inside it (and definitely not before!!). Signalling
> inside the critical section doesn't break correctness, but it may (?)
> result in some additional work by the scheduler as it moves a thread
> from the cond wait state to the waiting for mutex state, and maybe (?)
> some additional context swaps, both of which are bad for performance.

Regarding question marks above:

Simply put, signalling before unlock prolongs the duration of mutex lock
time (signalling operation takes some time) and that is not good.

That said, there are cases when condvar signalling must be done with
locked mutex (e.g. when condvar may be destroyed by the other thread as
the reaction to the predicate change).

regards,
alexander.

[toc] | [prev] | [next] | [standalone]


#198

FromDavid Schwartz <davids@webmaster.com>
Date2011-05-27 12:34 -0700
Message-ID<2f847af0-7f62-43d2-aff3-f35f0d42c3ce@l2g2000prg.googlegroups.com>
In reply to#197
On May 27, 7:01 am, Alexander Terekhov <terek...@web.de> wrote:

> Simply put, signalling before unlock prolongs the duration of mutex lock
> time (signalling operation takes some time) and that is not good.

That's true, but there are many factors weighing the other way. The
biggest one is that unlocking the mutex may wake up a thread that
consumes the predicate, leading the subsequent signal to cause a
spurious wakeup and two extra context switches.

> That said, there are cases when condvar signalling must be done with
> locked mutex (e.g. when condvar may be destroyed by the other thread as
> the reaction to the predicate change).

Yep. Another case is where unblocking the mutex may allow a new thread
to block on the condition variable (as it will see the new predicate),
causing the subsequent signal to wake up the wrong thread (not one
that blocked on the old predicate), leading to a lost signal.

DS

[toc] | [prev] | [next] | [standalone]


#202

FromAlexander Terekhov <terekhov@web.de>
Date2011-05-28 14:24 +0200
Message-ID<4DE0E997.42657B4A@web.de>
In reply to#198
David Schwartz wrote:
> 
> On May 27, 7:01 am, Alexander Terekhov <terek...@web.de> wrote:
> 
> > Simply put, signalling before unlock prolongs the duration of mutex lock
> > time (signalling operation takes some time) and that is not good.
> 
> That's true, but there are many factors weighing the other way. The
> biggest one is that unlocking the mutex may wake up a thread that
> consumes the predicate, leading the subsequent signal to cause a

Without wait-morphing, condvar signalling with mutex locked may cause a
thread blocked on a condvar to wake up just to be blocked again now on
mutex (after wake up due to condvar signalling).

> spurious wakeup and two extra context switches.

Context switching is old thinking. Nowadays think of idle multi(-core)
processors hardware consuming electricity for no good reason instead of
context switching: assume that all threads can run in parallel
(simultaneously) and that unblocking blocked threads can never impact
performance negatively.

regards,
alexander.

[toc] | [prev] | [next] | [standalone]


#204

FromDavid Schwartz <davids@webmaster.com>
Date2011-05-29 01:33 -0700
Message-ID<38011e68-82bb-4ca5-af04-009c2d750e17@q12g2000prb.googlegroups.com>
In reply to#202
On May 28, 5:24 am, Alexander Terekhov <terek...@web.de> wrote:

> Without wait-morphing, condvar signalling with mutex locked may cause a
> thread blocked on a condvar to wake up just to be blocked again now on
> mutex (after wake up due to condvar signalling).

If you're going to assume an implementation handles X badly and Y
well, then Y is better. If you assume it handles Y badly and X well,
then X is better. If you're going to compare X to Y in an
implementation-neutral context, you have to assume that the
implementation doesn't do anything particularly stupid.

> > spurious wakeup and two extra context switches.

> Context switching is old thinking. Nowadays think of idle multi(-core)
> processors hardware consuming electricity for no good reason instead of
> context switching: assume that all threads can run in parallel
> (simultaneously) and that unblocking blocked threads can never impact
> performance negatively.

If that's the case, why care about performance since there's clearly
tons of CPU to spare? Quite the contrary, the case in which you care
about performance is when all the cores are doing useful work and a
wasted context switch ejects a useful task and blows away its caches.

DS

[toc] | [prev] | [next] | [standalone]


#210

FromAlexander Terekhov <terekhov@web.de>
Date2011-05-31 15:32 +0200
Message-ID<4DE4EDD9.7B27185A@web.de>
In reply to#204
David Schwartz wrote:
[...]
> If that's the case, why care about performance since there's clearly
> tons of CPU to spare? Quite the contrary, the case in which you care
> about performance is when all the cores are doing useful work and a
> wasted context switch ejects a useful task and blows away its caches.

You didn't get me: I'm taking about the case with no context
switching/no ejected threads due to blocking (i.e. there is nothing to
blow away).

IOW, assume that you just can't perceive the effect of (supposed)
context switching.

regards,
alexander.

[toc] | [prev] | [next] | [standalone]


#216

FromDavid Schwartz <davids@webmaster.com>
Date2011-05-31 14:07 -0700
Message-ID<a0ed82d4-ff25-4a6d-ad8d-037cbc9c2d8e@r33g2000prh.googlegroups.com>
In reply to#210
On May 31, 6:32 am, Alexander Terekhov <terek...@web.de> wrote:

> You didn't get me: I'm taking about the case with no context
> switching/no ejected threads due to blocking (i.e. there is nothing to
> blow away).
>
> IOW, assume that you just can't perceive the effect of (supposed)
> context switching.

I don't see how that case is realistic in any situation in which you
care about performance. If the CPU is sitting idle doing nothing, that
means either the software is horribly designed (which means nobody
cares about performance) or there's very little work to do (in which
case, nobody cares about performance). You only care about performance
when the software is optimized for performance and there is lots of
work to do.

DS

[toc] | [prev] | [standalone]


Back to top | Article view | comp.programming.threads


csiph-web