PR libstdc++/80538 Only call sleep for non-zero values
Avoid a system call when no sleep is required. Sleep in a loop (actually two loops) to handle interruption by signals. PR libstdc++/80538 * src/c++11/thread.cc (this_thread::__sleep_for) [_GLIBCXX_HAVE_SLEEP]: Only call sleep for non-zero values. Loop while sleep call is interrupted and until steady_clock shows requested duration has elapsed. (!_GLIBCXX_HAVE_USLEEP]: Use the _GLIBCXX_HAVE_SLEEP code path, but avoiding the usleep call. * testsuite/30_threads/this_thread/60421.cc: Test repeated signal interruptions. From-SVN: r265044
This commit is contained in:
parent
2045ae1d3f
commit
cfef4c324a
|
@ -1,5 +1,15 @@
|
|||
2018-10-11 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/80538
|
||||
* src/c++11/thread.cc (this_thread::__sleep_for)
|
||||
[_GLIBCXX_HAVE_SLEEP]: Only call sleep for non-zero values.
|
||||
Loop while sleep call is interrupted and until steady_clock
|
||||
shows requested duration has elapsed.
|
||||
(!_GLIBCXX_HAVE_USLEEP]: Use the _GLIBCXX_HAVE_SLEEP code path, but
|
||||
avoiding the usleep call.
|
||||
* testsuite/30_threads/this_thread/60421.cc: Test repeated
|
||||
signal interruptions.
|
||||
|
||||
* include/bits/allocator.h
|
||||
(operator==(const allocator<_Tp>&, const allocator<_Tp>))
|
||||
(operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace
|
||||
|
|
|
@ -194,18 +194,35 @@ namespace this_thread
|
|||
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
||||
{ }
|
||||
#elif defined(_GLIBCXX_HAVE_SLEEP)
|
||||
# ifdef _GLIBCXX_HAVE_USLEEP
|
||||
::sleep(__s.count());
|
||||
if (__ns.count() > 0)
|
||||
const auto target = chrono::steady_clock::now() + __s + __ns;
|
||||
while (true)
|
||||
{
|
||||
long __us = __ns.count() / 1000;
|
||||
if (__us == 0)
|
||||
__us = 1;
|
||||
::usleep(__us);
|
||||
}
|
||||
unsigned secs = __s.count();
|
||||
if (__ns.count() > 0)
|
||||
{
|
||||
# ifdef _GLIBCXX_HAVE_USLEEP
|
||||
long us = __ns.count() / 1000;
|
||||
if (us == 0)
|
||||
us = 1;
|
||||
::usleep(us);
|
||||
# else
|
||||
::sleep(__s.count() + (__ns.count() >= 1000000));
|
||||
if (__ns.count() > 1000000 || secs == 0)
|
||||
++secs; // No sub-second sleep function, so round up.
|
||||
# endif
|
||||
}
|
||||
|
||||
if (secs > 0)
|
||||
{
|
||||
// Sleep in a loop to handle interruption by signals:
|
||||
while ((secs = ::sleep(secs)))
|
||||
{ }
|
||||
}
|
||||
const auto now = chrono::steady_clock::now();
|
||||
if (now >= target)
|
||||
break;
|
||||
__s = chrono::duration_cast<chrono::seconds>(target - now);
|
||||
__ns = chrono::duration_cast<chrono::nanoseconds>(target - (now + __s));
|
||||
}
|
||||
#elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
|
||||
unsigned long ms = __ns.count() / 1000000;
|
||||
if (__ns.count() > 0 && ms == 0)
|
||||
|
|
|
@ -53,10 +53,19 @@ test02()
|
|||
sleeping = true;
|
||||
std::this_thread::sleep_for(time);
|
||||
result = std::chrono::system_clock::now() >= (start + time);
|
||||
sleeping = false;
|
||||
});
|
||||
while (!sleeping) { }
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
pthread_kill(t.native_handle(), SIGUSR1);
|
||||
while (!sleeping)
|
||||
{
|
||||
// Wait for the thread to start sleeping.
|
||||
}
|
||||
while (sleeping)
|
||||
{
|
||||
// The sleeping thread should finish eventually,
|
||||
// even if continually interrupted after less than a second:
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
pthread_kill(t.native_handle(), SIGUSR1);
|
||||
}
|
||||
t.join();
|
||||
VERIFY( result );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue