aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2015-11-11 17:08:51 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2015-11-11 17:08:51 +0000
commitf55e699d3dac1e2764920fa32bee16bfe5313ff2 (patch)
tree8a635d744d2c9f5e16d9c2d156fd9421a58463f8 /libstdc++-v3
parentf83e226207d9458396a3a5cf9a1eb2a0092497bb (diff)
downloadgcc-f55e699d3dac1e2764920fa32bee16bfe5313ff2.zip
gcc-f55e699d3dac1e2764920fa32bee16bfe5313ff2.tar.gz
gcc-f55e699d3dac1e2764920fa32bee16bfe5313ff2.tar.bz2
Loop in std::this_thread sleep functions
PR libstdc++/60421 * include/std/thread (this_thread::sleep_for): Retry on EINTR. (this_thread::sleep_until): Retry if time not reached. * src/c++11/thread.cc (__sleep_for): Retry on EINTR. * testsuite/30_threads/this_thread/60421.cc: Test interruption and non-steady clocks. From-SVN: r230183
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/std/thread16
-rw-r--r--libstdc++-v3/src/c++11/thread.cc3
-rw-r--r--libstdc++-v3/testsuite/30_threads/this_thread/60421.cc64
4 files changed, 86 insertions, 6 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 3506c0e..aba4f7e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2015-11-11 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/60421
+ * include/std/thread (this_thread::sleep_for): Retry on EINTR.
+ (this_thread::sleep_until): Retry if time not reached.
+ * src/c++11/thread.cc (__sleep_for): Retry on EINTR.
+ * testsuite/30_threads/this_thread/60421.cc: Test interruption and
+ non-steady clocks.
+
2015-11-11 Ville Voutilainen <ville.voutilainen@gmail.com>
LWG 2510, make the default constructors of library tag types
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index c67ec46..5940e6e 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -297,7 +297,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
static_cast<std::time_t>(__s.count()),
static_cast<long>(__ns.count())
};
- ::nanosleep(&__ts, 0);
+ while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
+ { }
#else
__sleep_for(__s, __ns);
#endif
@@ -309,8 +310,17 @@ _GLIBCXX_END_NAMESPACE_VERSION
sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
{
auto __now = _Clock::now();
- if (__now < __atime)
- sleep_for(__atime - __now);
+ if (_Clock::is_steady)
+ {
+ if (__now < __atime)
+ sleep_for(__atime - __now);
+ return;
+ }
+ while (__now < __atime)
+ {
+ sleep_for(__atime - __now);
+ __now = _Clock::now();
+ }
}
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc
index e116afa..3407e80 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -221,7 +221,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_cast<std::time_t>(__s.count()),
static_cast<long>(__ns.count())
};
- ::nanosleep(&__ts, 0);
+ while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
+ { }
#elif defined(_GLIBCXX_HAVE_SLEEP)
# ifdef _GLIBCXX_HAVE_USLEEP
::sleep(__s.count());
diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc b/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc
index ecc4deb..5dbf257 100644
--- a/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc
+++ b/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc
@@ -15,12 +15,19 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-options "-std=gnu++11" }
+// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-rtems* *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-rtems* *-*-darwin* } }
// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
// { dg-require-time "" }
#include <thread>
#include <chrono>
+#include <atomic>
+#include <cstdint>
+#include <signal.h>
#include <testsuite_hooks.h>
void
@@ -28,11 +35,64 @@ test01()
{
std::this_thread::sleep_for(std::chrono::seconds(0));
std::this_thread::sleep_for(std::chrono::seconds(-1));
- std::this_thread::sleep_for(std::chrono::duration<uint64_t>::zero());
+ std::this_thread::sleep_for(std::chrono::duration<std::uint64_t>::zero());
+}
+
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ // test interruption of this_thread::sleep_for() by a signal
+ struct sigaction sa{ };
+ sa.sa_handler = +[](int) { };
+ sigaction(SIGUSR1, &sa, 0);
+ bool result = false;
+ std::atomic<bool> sleeping{false};
+ std::thread t([&result, &sleeping] {
+ auto start = std::chrono::system_clock::now();
+ auto time = std::chrono::seconds(3);
+ sleeping = true;
+ std::this_thread::sleep_for(time);
+ result = std::chrono::system_clock::now() >= (start + time);
+ });
+ while (!sleeping) { }
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ pthread_kill(t.native_handle(), SIGUSR1);
+ t.join();
+ VERIFY( result );
+}
+
+struct slow_clock
+{
+ using rep = std::chrono::system_clock::rep;
+ using period = std::chrono::system_clock::period;
+ using duration = std::chrono::system_clock::duration;
+ using time_point = std::chrono::time_point<slow_clock, duration>;
+ static constexpr bool is_steady = false;
+
+ static time_point now()
+ {
+ auto real = std::chrono::system_clock::now();
+ return time_point{real.time_since_epoch() / 2};
+ }
+};
+
+void
+test03()
+{
+ bool test __attribute__((unused)) = true;
+
+ // test that this_thread::sleep_until() handles clock adjustments
+ auto when = slow_clock::now() + std::chrono::seconds(2);
+ std::this_thread::sleep_until(when);
+ VERIFY( slow_clock::now() >= when );
}
int
main()
{
test01();
+ test02();
+ test03();
}