From 5bbb1f3000c57fd4d95969b30fa0e35be6d54ffb Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 11 Aug 2020 16:16:21 +0100 Subject: [PATCH] libstdc++: Make std::this_thread functions work without gthreads The only function in namespace std::this_thread that actually depends on thread support being present is this_thread::get_id(). The other functions (yield, sleep_for and sleep_until) can be defined for targets without gthreads. A small change is needed in std::this_thread::sleep_for which currently uses the __gthread_time_t typedef. Since it just calls nanosleep directly, it should use timespec directly instead of the typedef. Even std::this_thread::get_id() could be made to work, the only difficulty is that it returns a value of type std::thread::id and std::thread is only defined when gthreads support exists. libstdc++-v3/ChangeLog: * include/std/thread [!_GLIBCXX_HAS_GTHREADS] (this_thread::yield) (this_thread::sleep_until): Define. [!_GLIBCXX_HAS_GTHREADS] (this_thread::sleep_for): Define. Replace use of __gthread_time_t typedef with timespec. * src/c++11/thread.cc [!_GLIBCXX_HAS_GTHREADS] (__sleep_for): Likewise. * testsuite/30_threads/this_thread/2.cc: Moved to... * testsuite/30_threads/this_thread/yield.cc: ...here. * testsuite/30_threads/this_thread/3.cc: Moved to... * testsuite/30_threads/this_thread/sleep_for-mt.cc: ...here. * testsuite/30_threads/this_thread/4.cc: Moved to... * testsuite/30_threads/this_thread/sleep_until-mt.cc: ...here. * testsuite/30_threads/this_thread/58038.cc: Add dg-require-sleep. * testsuite/30_threads/this_thread/60421.cc: Likewise. * testsuite/30_threads/this_thread/sleep_for.cc: New test. * testsuite/30_threads/this_thread/sleep_until.cc: New test. --- libstdc++-v3/include/std/thread | 29 +++++++------ libstdc++-v3/src/c++11/thread.cc | 33 ++++++++------ .../testsuite/30_threads/this_thread/58038.cc | 1 + .../testsuite/30_threads/this_thread/60421.cc | 1 + .../this_thread/{3.cc => sleep_for-mt.cc} | 0 .../30_threads/this_thread/sleep_for.cc | 43 +++++++++++++++++++ .../this_thread/{4.cc => sleep_until-mt.cc} | 0 .../30_threads/this_thread/sleep_until.cc | 43 +++++++++++++++++++ .../30_threads/this_thread/{2.cc => yield.cc} | 9 ++-- 9 files changed, 127 insertions(+), 32 deletions(-) rename libstdc++-v3/testsuite/30_threads/this_thread/{3.cc => sleep_for-mt.cc} (100%) create mode 100644 libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc rename libstdc++-v3/testsuite/30_threads/this_thread/{4.cc => sleep_until-mt.cc} (100%) create mode 100644 libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc rename libstdc++-v3/testsuite/30_threads/this_thread/{2.cc => yield.cc} (85%) diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 0445ab1e319e..30ae93a0d5bf 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -35,12 +35,16 @@ # include #else -#include +#include // std::chrono::* + +#ifdef _GLIBCXX_USE_NANOSLEEP +# include // errno, EINTR +# include // nanosleep +#endif #if defined(_GLIBCXX_HAS_GTHREADS) #include -#include // std::chrono::* #include // std::unique_ptr #include // std::tuple @@ -49,14 +53,11 @@ # include // std::stop_source, std::stop_token, std::nostopstate #endif -#ifdef _GLIBCXX_USE_NANOSLEEP -# include // errno, EINTR -# include // nanosleep -#endif - #include // std::hash #include // std::__invoke +#endif // _GLIBCXX_HAS_GTHREADS + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -69,6 +70,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ +#if defined(_GLIBCXX_HAS_GTHREADS) /// thread class thread { @@ -352,6 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else return __out << __id._M_thread; } +#endif // _GLIBCXX_HAS_GTHREADS /** @namespace std::this_thread * @brief ISO C++ 2011 namespace for interacting with the current thread @@ -360,6 +363,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ namespace this_thread { +#if defined _GLIBCXX_HAS_GTHREADS /// get_id inline thread::id get_id() noexcept @@ -374,12 +378,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif return thread::id(__gthread_self()); } +#endif // _GLIBCXX_HAS_GTHREADS /// yield inline void yield() noexcept { -#ifdef _GLIBCXX_USE_SCHED_YIELD +#if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD __gthread_yield(); #endif } @@ -397,7 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __s = chrono::duration_cast(__rtime); auto __ns = chrono::duration_cast(__rtime - __s); #ifdef _GLIBCXX_USE_NANOSLEEP - __gthread_time_t __ts = + struct ::timespec __ts = { static_cast(__s.count()), static_cast(__ns.count()) @@ -432,8 +437,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } - // @} group threads - #ifdef __cpp_lib_jthread class jthread @@ -562,8 +565,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION thread _M_thread; }; #endif // __cpp_lib_jthread + + // @} group threads + _GLIBCXX_END_NAMESPACE_VERSION } // namespace -#endif // _GLIBCXX_HAS_GTHREADS #endif // C++11 #endif // _GLIBCXX_THREAD diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc index 2d8781724f24..a4c87d816a58 100644 --- a/libstdc++-v3/src/c++11/thread.cc +++ b/libstdc++-v3/src/c++11/thread.cc @@ -29,6 +29,16 @@ #include #include +#ifndef _GLIBCXX_USE_NANOSLEEP +# ifdef _GLIBCXX_HAVE_SLEEP +# include +# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP) +# include +# else +# error "No sleep function known for this target" +# endif +#endif + #ifdef _GLIBCXX_HAS_GTHREADS #if defined(_GLIBCXX_USE_GET_NPROCS) @@ -59,16 +69,6 @@ static inline int get_nprocs() # define _GLIBCXX_NPROCS 0 #endif -#ifndef _GLIBCXX_USE_NANOSLEEP -# ifdef _GLIBCXX_HAVE_SLEEP -# include -# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP) -# include -# else -# error "No sleep function known for this target" -# endif -#endif - namespace std _GLIBCXX_VISIBILITY(default) { extern "C" @@ -180,13 +180,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __n; } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _GLIBCXX_HAS_GTHREADS + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION namespace this_thread { void __sleep_for(chrono::seconds __s, chrono::nanoseconds __ns) { #ifdef _GLIBCXX_USE_NANOSLEEP - __gthread_time_t __ts = + struct ::timespec __ts = { static_cast(__s.count()), static_cast(__ns.count()) @@ -231,8 +239,5 @@ namespace this_thread #endif } } - _GLIBCXX_END_NAMESPACE_VERSION } // namespace std - -#endif // _GLIBCXX_HAS_GTHREADS diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/58038.cc b/libstdc++-v3/testsuite/30_threads/this_thread/58038.cc index 54ff0fb53219..fd007368527a 100644 --- a/libstdc++-v3/testsuite/30_threads/this_thread/58038.cc +++ b/libstdc++-v3/testsuite/30_threads/this_thread/58038.cc @@ -17,6 +17,7 @@ // { dg-do run { target c++11 } } // { dg-require-time "" } +// { dg-require-sleep "" } #include #include diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc b/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc index 531bb366c01f..3f9d8b134d2e 100644 --- a/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc +++ b/libstdc++-v3/testsuite/30_threads/this_thread/60421.cc @@ -22,6 +22,7 @@ // { dg-require-cstdint "" } // { dg-require-gthreads "" } // { dg-require-time "" } +// { dg-require-sleep "" } #include #include diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/3.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc similarity index 100% rename from libstdc++-v3/testsuite/30_threads/this_thread/3.cc rename to libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc new file mode 100644 index 000000000000..9552a23435e3 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for.cc @@ -0,0 +1,43 @@ +// { dg-do run { target c++11 } } +// { dg-require-sleep "" } + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include + +// This tests this_thread::sleep_until without using -pthread + +namespace chr = std::chrono; + +void +test01() +{ + chr::system_clock::time_point begin = chr::system_clock::now(); + chr::microseconds ms(500); + + std::this_thread::sleep_for(ms); + + VERIFY( (chr::system_clock::now() - begin) >= ms ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/4.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc similarity index 100% rename from libstdc++-v3/testsuite/30_threads/this_thread/4.cc rename to libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc new file mode 100644 index 000000000000..6af875911df3 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until.cc @@ -0,0 +1,43 @@ +// { dg-do run { target c++11 } } +// { dg-require-sleep "" } + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include + +// This tests this_thread::sleep_until without using -pthread + +namespace chr = std::chrono; + +void +test01() +{ + chr::system_clock::time_point begin = chr::system_clock::now(); + chr::microseconds ms(500); + + std::this_thread::sleep_until(chr::system_clock::now() + ms); + + VERIFY( (chr::system_clock::now() - begin) >= ms ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/2.cc b/libstdc++-v3/testsuite/30_threads/this_thread/yield.cc similarity index 85% rename from libstdc++-v3/testsuite/30_threads/this_thread/2.cc rename to libstdc++-v3/testsuite/30_threads/this_thread/yield.cc index 00dde1474860..08f4efaaaf51 100644 --- a/libstdc++-v3/testsuite/30_threads/this_thread/2.cc +++ b/libstdc++-v3/testsuite/30_threads/this_thread/yield.cc @@ -1,8 +1,5 @@ -// { dg-do run } -// { dg-options "-pthread" } -// { dg-require-effective-target c++11 } -// { dg-require-effective-target pthread } -// { dg-require-gthreads "" } +// { dg-do run { target c++11 } } +// { dg-additional-options "-pthread" { target pthread } } // Copyright (C) 2008-2020 Free Software Foundation, Inc. // @@ -28,7 +25,7 @@ int main() { - try + try { std::this_thread::yield(); } -- 2.39.2