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>
|
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
|
* include/bits/allocator.h
|
||||||
(operator==(const allocator<_Tp>&, const allocator<_Tp>))
|
(operator==(const allocator<_Tp>&, const allocator<_Tp>))
|
||||||
(operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace
|
(operator!=(const allocator<_Tp>&, const allocator<_Tp>)): Replace
|
||||||
|
|
|
@ -194,18 +194,35 @@ namespace this_thread
|
||||||
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
|
||||||
{ }
|
{ }
|
||||||
#elif defined(_GLIBCXX_HAVE_SLEEP)
|
#elif defined(_GLIBCXX_HAVE_SLEEP)
|
||||||
# ifdef _GLIBCXX_HAVE_USLEEP
|
const auto target = chrono::steady_clock::now() + __s + __ns;
|
||||||
::sleep(__s.count());
|
while (true)
|
||||||
if (__ns.count() > 0)
|
|
||||||
{
|
{
|
||||||
long __us = __ns.count() / 1000;
|
unsigned secs = __s.count();
|
||||||
if (__us == 0)
|
if (__ns.count() > 0)
|
||||||
__us = 1;
|
{
|
||||||
::usleep(__us);
|
# ifdef _GLIBCXX_HAVE_USLEEP
|
||||||
}
|
long us = __ns.count() / 1000;
|
||||||
|
if (us == 0)
|
||||||
|
us = 1;
|
||||||
|
::usleep(us);
|
||||||
# else
|
# else
|
||||||
::sleep(__s.count() + (__ns.count() >= 1000000));
|
if (__ns.count() > 1000000 || secs == 0)
|
||||||
|
++secs; // No sub-second sleep function, so round up.
|
||||||
# endif
|
# 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)
|
#elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
|
||||||
unsigned long ms = __ns.count() / 1000000;
|
unsigned long ms = __ns.count() / 1000000;
|
||||||
if (__ns.count() > 0 && ms == 0)
|
if (__ns.count() > 0 && ms == 0)
|
||||||
|
|
|
@ -53,10 +53,19 @@ test02()
|
||||||
sleeping = true;
|
sleeping = true;
|
||||||
std::this_thread::sleep_for(time);
|
std::this_thread::sleep_for(time);
|
||||||
result = std::chrono::system_clock::now() >= (start + time);
|
result = std::chrono::system_clock::now() >= (start + time);
|
||||||
|
sleeping = false;
|
||||||
});
|
});
|
||||||
while (!sleeping) { }
|
while (!sleeping)
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
{
|
||||||
pthread_kill(t.native_handle(), SIGUSR1);
|
// 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();
|
t.join();
|
||||||
VERIFY( result );
|
VERIFY( result );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue