Commit f55e699d by Jonathan Wakely Committed by Jonathan Wakely

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
parent f83e2262
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> 2015-11-11 Ville Voutilainen <ville.voutilainen@gmail.com>
LWG 2510, make the default constructors of library tag types LWG 2510, make the default constructors of library tag types
......
...@@ -297,7 +297,8 @@ _GLIBCXX_END_NAMESPACE_VERSION ...@@ -297,7 +297,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
static_cast<std::time_t>(__s.count()), static_cast<std::time_t>(__s.count()),
static_cast<long>(__ns.count()) static_cast<long>(__ns.count())
}; };
::nanosleep(&__ts, 0); while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
{ }
#else #else
__sleep_for(__s, __ns); __sleep_for(__s, __ns);
#endif #endif
...@@ -309,8 +310,17 @@ _GLIBCXX_END_NAMESPACE_VERSION ...@@ -309,8 +310,17 @@ _GLIBCXX_END_NAMESPACE_VERSION
sleep_until(const chrono::time_point<_Clock, _Duration>& __atime) sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
{ {
auto __now = _Clock::now(); auto __now = _Clock::now();
if (__now < __atime) if (_Clock::is_steady)
sleep_for(__atime - __now); {
if (__now < __atime)
sleep_for(__atime - __now);
return;
}
while (__now < __atime)
{
sleep_for(__atime - __now);
__now = _Clock::now();
}
} }
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
......
...@@ -221,7 +221,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -221,7 +221,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_cast<std::time_t>(__s.count()), static_cast<std::time_t>(__s.count()),
static_cast<long>(__ns.count()) static_cast<long>(__ns.count())
}; };
::nanosleep(&__ts, 0); while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
{ }
#elif defined(_GLIBCXX_HAVE_SLEEP) #elif defined(_GLIBCXX_HAVE_SLEEP)
# ifdef _GLIBCXX_HAVE_USLEEP # ifdef _GLIBCXX_HAVE_USLEEP
::sleep(__s.count()); ::sleep(__s.count());
......
...@@ -15,12 +15,19 @@ ...@@ -15,12 +15,19 @@
// with this library; see the file COPYING3. If not see // with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>. // <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-cstdint "" }
// { dg-require-gthreads "" }
// { dg-require-time "" } // { dg-require-time "" }
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <atomic>
#include <cstdint>
#include <signal.h>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void void
...@@ -28,11 +35,64 @@ test01() ...@@ -28,11 +35,64 @@ test01()
{ {
std::this_thread::sleep_for(std::chrono::seconds(0)); 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::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 int
main() main()
{ {
test01(); test01();
test02();
test03();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment