public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout
@ 2018-07-10 10:09 Mike Crowe
  2018-07-10 10:09 ` [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for Mike Crowe
  2018-07-20 10:53 ` [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Jonathan Wakely
  0 siblings, 2 replies; 7+ messages in thread
From: Mike Crowe @ 2018-07-10 10:09 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: Mike Crowe

As currently implemented, condition_variable always ultimately waits
against std::chrono::system_clock. This clock can be changed in arbitrary
ways by the user which may result in us waking up too early or too late
when measured against the caller-supplied clock.

We can't (yet) do much about waking up too late[1], but
if we wake up too early we must return cv_status::no_timeout to indicate a
spurious wakeup rather than incorrectly returning cv_status::timeout.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861
---
 libstdc++-v3/ChangeLog                      | 5 +++++
 libstdc++-v3/include/std/condition_variable | 8 +++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index cceef0271ae..ea7875ace9f 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,8 @@
+2018-07-09  Mike Crowe <mac@mcrowe.com>
+       * include/std/condition_variable (wait_until): Only report timeout
+       if we really have timed out when measured against the
+       caller-supplied clock.
+
 2018-07-06  François Dumont  <fdumont@gcc.gnu.org>

        * include/debug/functions.h (__gnu_debug::__check_string): Move...
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index 84863a162d6..a2d146a9b09 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -116,7 +116,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        const auto __delta = __atime - __c_entry;
        const auto __s_atime = __s_entry + __delta;

-       return __wait_until_impl(__lock, __s_atime);
+       // We might get a timeout when measured against __clock_t but
+       // we need to check against the caller-supplied clock to tell
+       // whether we should return a timeout.
+       if (__wait_until_impl(__lock, __s_atime) == cv_status::timeout)
+         return _Clock::now() < __atime ? cv_status::no_timeout : cv_status::timeout;
+       else
+         return cv_status::no_timeout;
       }

     template<typename _Clock, typename _Duration, typename _Predicate>
--
2.11.0

BrightSign considers your privacy to be very important. The emails you send to us will be protected and secured. Furthermore, we will only use your email and contact information for the reasons you sent them to us and for tracking how effectively we respond to your requests.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for
  2018-07-10 10:09 [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Mike Crowe
@ 2018-07-10 10:09 ` Mike Crowe
  2018-07-20 10:53 ` [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Jonathan Wakely
  1 sibling, 0 replies; 7+ messages in thread
From: Mike Crowe @ 2018-07-10 10:09 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: Mike Crowe

I believe[1][2] that the C++ standard says that
std::condition_variable::wait_for should be implemented to be equivalent
to:

 return wait_until(lock, chrono::steady_clock::now() + rel_time);

But the existing implementation uses chrono::system_clock. Now that
wait_until has potentially-different behaviour for chrono::steady_clock,
let's at least try to wait using the correct clock.

[1] https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
[2] https://github.com/cplusplus/draft/blob/master/source/threads.tex
---
 libstdc++-v3/ChangeLog                      | 3 +++
 libstdc++-v3/include/std/condition_variable | 5 +++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index ea7875ace9f..4500273ace7 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,4 +1,7 @@
 2018-07-09  Mike Crowe <mac@mcrowe.com>
+       * include/std/condition_variable (wait_for): Use steady_clock.
+
+2018-07-09  Mike Crowe <mac@mcrowe.com>
        * include/std/condition_variable (wait_until): Only report timeout
        if we really have timed out when measured against the
        caller-supplied clock.
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index a2d146a9b09..ce583990b9d 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -65,6 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   class condition_variable
   {
     typedef chrono::system_clock       __clock_t;
+    typedef chrono::steady_clock       __steady_clock_t;
     typedef __gthread_cond_t           __native_type;

 #ifdef __GTHREAD_COND_INIT
@@ -142,11 +143,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       wait_for(unique_lock<mutex>& __lock,
               const chrono::duration<_Rep, _Period>& __rtime)
       {
-       using __dur = typename __clock_t::duration;
+       using __dur = typename __steady_clock_t::duration;
        auto __reltime = chrono::duration_cast<__dur>(__rtime);
        if (__reltime < __rtime)
          ++__reltime;
-       return wait_until(__lock, __clock_t::now() + __reltime);
+       return wait_until(__lock, __steady_clock_t::now() + __reltime);
       }

     template<typename _Rep, typename _Period, typename _Predicate>
--
2.11.0

BrightSign considers your privacy to be very important. The emails you send to us will be protected and secured. Furthermore, we will only use your email and contact information for the reasons you sent them to us and for tracking how effectively we respond to your requests.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout
  2018-07-10 10:09 [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Mike Crowe
  2018-07-10 10:09 ` [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for Mike Crowe
@ 2018-07-20 10:53 ` Jonathan Wakely
  2018-07-20 11:30   ` Mike Crowe
  1 sibling, 1 reply; 7+ messages in thread
From: Jonathan Wakely @ 2018-07-20 10:53 UTC (permalink / raw)
  To: Mike Crowe; +Cc: libstdc++, gcc-patches

On 10/07/18 11:09 +0100, Mike Crowe wrote:
>As currently implemented, condition_variable always ultimately waits
>against std::chrono::system_clock. This clock can be changed in arbitrary
>ways by the user which may result in us waking up too early or too late
>when measured against the caller-supplied clock.
>
>We can't (yet) do much about waking up too late[1], but
>if we wake up too early we must return cv_status::no_timeout to indicate a
>spurious wakeup rather than incorrectly returning cv_status::timeout.

The patch looks good, thanks.

Can we come up with a test for this, using a user-defined clock that
jumps back?


>[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861
>---
> libstdc++-v3/ChangeLog                      | 5 +++++
> libstdc++-v3/include/std/condition_variable | 8 +++++++-
> 2 files changed, 12 insertions(+), 1 deletion(-)
>
>diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
>index cceef0271ae..ea7875ace9f 100644
>--- a/libstdc++-v3/ChangeLog
>+++ b/libstdc++-v3/ChangeLog
>@@ -1,3 +1,8 @@
>+2018-07-09  Mike Crowe <mac@mcrowe.com>
>+       * include/std/condition_variable (wait_until): Only report timeout
>+       if we really have timed out when measured against the
>+       caller-supplied clock.
>+
> 2018-07-06  François Dumont  <fdumont@gcc.gnu.org>
>
>        * include/debug/functions.h (__gnu_debug::__check_string): Move...
>diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
>index 84863a162d6..a2d146a9b09 100644
>--- a/libstdc++-v3/include/std/condition_variable
>+++ b/libstdc++-v3/include/std/condition_variable
>@@ -116,7 +116,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        const auto __delta = __atime - __c_entry;
>        const auto __s_atime = __s_entry + __delta;
>
>-       return __wait_until_impl(__lock, __s_atime);
>+       // We might get a timeout when measured against __clock_t but
>+       // we need to check against the caller-supplied clock to tell
>+       // whether we should return a timeout.
>+       if (__wait_until_impl(__lock, __s_atime) == cv_status::timeout)
>+         return _Clock::now() < __atime ? cv_status::no_timeout : cv_status::timeout;
>+       else
>+         return cv_status::no_timeout;
>       }
>
>     template<typename _Clock, typename _Duration, typename _Predicate>
>--
>2.11.0
>
>BrightSign considers your privacy to be very important. The emails you send to us will be protected and secured. Furthermore, we will only use your email and contact information for the reasons you sent them to us and for tracking how effectively we respond to your requests.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout
  2018-07-20 10:53 ` [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Jonathan Wakely
@ 2018-07-20 11:30   ` Mike Crowe
  2018-07-20 11:44     ` Jonathan Wakely
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Crowe @ 2018-07-20 11:30 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Friday 20 July 2018 at 11:53:38 +0100, Jonathan Wakely wrote:
> On 10/07/18 11:09 +0100, Mike Crowe wrote:
> > As currently implemented, condition_variable always ultimately waits
> > against std::chrono::system_clock. This clock can be changed in arbitrary
> > ways by the user which may result in us waking up too early or too late
> > when measured against the caller-supplied clock.
> > 
> > We can't (yet) do much about waking up too late[1], but
> > if we wake up too early we must return cv_status::no_timeout to indicate a
> > spurious wakeup rather than incorrectly returning cv_status::timeout.
> 
> The patch looks good, thanks.
> 
> Can we come up with a test for this, using a user-defined clock that
> jumps back?

That's a good idea. I'll do that.

Thanks.

Mike.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout
  2018-07-20 11:30   ` Mike Crowe
@ 2018-07-20 11:44     ` Jonathan Wakely
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Wakely @ 2018-07-20 11:44 UTC (permalink / raw)
  To: Mike Crowe; +Cc: libstdc++, gcc-patches

On 20/07/18 12:30 +0100, Mike Crowe wrote:
>On Friday 20 July 2018 at 11:53:38 +0100, Jonathan Wakely wrote:
>> On 10/07/18 11:09 +0100, Mike Crowe wrote:
>> > As currently implemented, condition_variable always ultimately waits
>> > against std::chrono::system_clock. This clock can be changed in arbitrary
>> > ways by the user which may result in us waking up too early or too late
>> > when measured against the caller-supplied clock.
>> >
>> > We can't (yet) do much about waking up too late[1], but
>> > if we wake up too early we must return cv_status::no_timeout to indicate a
>> > spurious wakeup rather than incorrectly returning cv_status::timeout.
>>
>> The patch looks good, thanks.
>>
>> Can we come up with a test for this, using a user-defined clock that
>> jumps back?
>
>That's a good idea. I'll do that.

Thanks.

There are "broken" clocks in testsuite/30_threads/this_thread/60421.cc
and testsuite/30_threads/timed_mutex/try_lock_until/57641.cc but I'm
not sure if either of them is reusable. A custom one for this test
should be reasonably easy.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for
  2018-07-20 16:50 ` [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for Mike Crowe
@ 2018-08-01 15:41   ` Jonathan Wakely
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Wakely @ 2018-08-01 15:41 UTC (permalink / raw)
  To: Mike Crowe; +Cc: libstdc++, gcc-patches

On 20/07/18 17:49 +0100, Mike Crowe wrote:
>I believe[1][2] that the C++ standard says that
>std::condition_variable::wait_for should be implemented to be equivalent
>to:
>
> return wait_until(lock, chrono::steady_clock::now() + rel_time);
>
>But the existing implementation uses chrono::system_clock. Now that
>wait_until has potentially-different behaviour for chrono::steady_clock,
>let's at least try to wait using the correct clock.
>
>[1] https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
>[2] https://github.com/cplusplus/draft/blob/master/source/threads.tex

Also committed to trunk. Thanks again.

>---
> libstdc++-v3/ChangeLog                      | 3 +++
> libstdc++-v3/include/std/condition_variable | 5 +++--
> 2 files changed, 6 insertions(+), 2 deletions(-)
>
>diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
>index 4657af7..432cb84 100644
>--- a/libstdc++-v3/ChangeLog
>+++ b/libstdc++-v3/ChangeLog
>@@ -1,4 +1,7 @@
> 2018-07-20  Mike Crowe <mac@mcrowe.com>
>+       * include/std/condition_variable (wait_for): Use steady_clock.
>+
>+2018-07-20  Mike Crowe <mac@mcrowe.com>
>        * include/std/condition_variable (wait_until): Only report timeout
>        if we really have timed out when measured against the
>        caller-supplied clock.
>diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
>index a2d146a..ce58399 100644
>--- a/libstdc++-v3/include/std/condition_variable
>+++ b/libstdc++-v3/include/std/condition_variable
>@@ -65,6 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>   class condition_variable
>   {
>     typedef chrono::system_clock       __clock_t;
>+    typedef chrono::steady_clock       __steady_clock_t;
>     typedef __gthread_cond_t           __native_type;
>
> #ifdef __GTHREAD_COND_INIT
>@@ -142,11 +143,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       wait_for(unique_lock<mutex>& __lock,
>               const chrono::duration<_Rep, _Period>& __rtime)
>       {
>-       using __dur = typename __clock_t::duration;
>+       using __dur = typename __steady_clock_t::duration;
>        auto __reltime = chrono::duration_cast<__dur>(__rtime);
>        if (__reltime < __rtime)
>          ++__reltime;
>-       return wait_until(__lock, __clock_t::now() + __reltime);
>+       return wait_until(__lock, __steady_clock_t::now() + __reltime);
>       }
>
>     template<typename _Rep, typename _Period, typename _Predicate>
>--
>git-series 0.9.1
>BrightSign considers your privacy to be very important. The emails you send to us will be protected and secured. Furthermore, we will only use your email and contact information for the reasons you sent them to us and for tracking how effectively we respond to your requests.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for
  2018-07-20 16:50 Mike Crowe
@ 2018-07-20 16:50 ` Mike Crowe
  2018-08-01 15:41   ` Jonathan Wakely
  0 siblings, 1 reply; 7+ messages in thread
From: Mike Crowe @ 2018-07-20 16:50 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: Jonathan Wakely, Mike Crowe

I believe[1][2] that the C++ standard says that
std::condition_variable::wait_for should be implemented to be equivalent
to:

 return wait_until(lock, chrono::steady_clock::now() + rel_time);

But the existing implementation uses chrono::system_clock. Now that
wait_until has potentially-different behaviour for chrono::steady_clock,
let's at least try to wait using the correct clock.

[1] https://en.cppreference.com/w/cpp/thread/condition_variable/wait_for
[2] https://github.com/cplusplus/draft/blob/master/source/threads.tex
---
 libstdc++-v3/ChangeLog                      | 3 +++
 libstdc++-v3/include/std/condition_variable | 5 +++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 4657af7..432cb84 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,4 +1,7 @@
 2018-07-20  Mike Crowe <mac@mcrowe.com>
+       * include/std/condition_variable (wait_for): Use steady_clock.
+
+2018-07-20  Mike Crowe <mac@mcrowe.com>
        * include/std/condition_variable (wait_until): Only report timeout
        if we really have timed out when measured against the
        caller-supplied clock.
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index a2d146a..ce58399 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -65,6 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   class condition_variable
   {
     typedef chrono::system_clock       __clock_t;
+    typedef chrono::steady_clock       __steady_clock_t;
     typedef __gthread_cond_t           __native_type;

 #ifdef __GTHREAD_COND_INIT
@@ -142,11 +143,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       wait_for(unique_lock<mutex>& __lock,
               const chrono::duration<_Rep, _Period>& __rtime)
       {
-       using __dur = typename __clock_t::duration;
+       using __dur = typename __steady_clock_t::duration;
        auto __reltime = chrono::duration_cast<__dur>(__rtime);
        if (__reltime < __rtime)
          ++__reltime;
-       return wait_until(__lock, __clock_t::now() + __reltime);
+       return wait_until(__lock, __steady_clock_t::now() + __reltime);
       }

     template<typename _Rep, typename _Period, typename _Predicate>
--
git-series 0.9.1
BrightSign considers your privacy to be very important. The emails you send to us will be protected and secured. Furthermore, we will only use your email and contact information for the reasons you sent them to us and for tracking how effectively we respond to your requests.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-08-01 15:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-10 10:09 [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Mike Crowe
2018-07-10 10:09 ` [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for Mike Crowe
2018-07-20 10:53 ` [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Jonathan Wakely
2018-07-20 11:30   ` Mike Crowe
2018-07-20 11:44     ` Jonathan Wakely
2018-07-20 16:50 Mike Crowe
2018-07-20 16:50 ` [PATCH 2/2] condition_variable: Use steady_clock to implement wait_for Mike Crowe
2018-08-01 15:41   ` Jonathan Wakely

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 read-only IMAP folder(s) and NNTP newsgroup(s).