From: Jonathan Wakely Date: Tue, 11 Aug 2020 15:16:21 +0000 (+0100) Subject: libstdc++: Make std::this_thread functions work without gthreads X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=r11-2649-g5bbb1f3000c57fd4d95969b30fa0e35be6d54ffb;p=gcc.git 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. --- diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 0445ab1e319..30ae93a0d5b 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 2d8781724f2..a4c87d816a5 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/2.cc b/libstdc++-v3/testsuite/30_threads/this_thread/2.cc deleted file mode 100644 index 00dde147486..00000000000 --- a/libstdc++-v3/testsuite/30_threads/this_thread/2.cc +++ /dev/null @@ -1,45 +0,0 @@ -// { dg-do run } -// { dg-options "-pthread" } -// { dg-require-effective-target c++11 } -// { dg-require-effective-target pthread } -// { dg-require-gthreads "" } - -// Copyright (C) 2008-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 - -int main() -{ - try - { - std::this_thread::yield(); - } - catch (const std::system_error&) - { - VERIFY( false ); - } - catch (...) - { - VERIFY( false ); - } - - return 0; -} diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/3.cc b/libstdc++-v3/testsuite/30_threads/this_thread/3.cc deleted file mode 100644 index 45993811d01..00000000000 --- a/libstdc++-v3/testsuite/30_threads/this_thread/3.cc +++ /dev/null @@ -1,60 +0,0 @@ -// { dg-do run } -// { dg-options "-pthread" } -// { dg-require-effective-target c++11 } -// { dg-require-effective-target pthread } -// { dg-require-gthreads "" } -// { dg-require-sleep "" } - -// Copyright (C) 2008-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 -#include - -namespace chr = std::chrono; - -void foo() -{ - 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() -{ - try - { - std::thread t(foo); - t.join(); - } - catch (const std::system_error&) - { - VERIFY( false ); - } - catch (...) - { - VERIFY( false ); - } - - return 0; -} diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/4.cc b/libstdc++-v3/testsuite/30_threads/this_thread/4.cc deleted file mode 100644 index fc8d10d8448..00000000000 --- a/libstdc++-v3/testsuite/30_threads/this_thread/4.cc +++ /dev/null @@ -1,60 +0,0 @@ -// { dg-do run } -// { dg-options "-pthread" } -// { dg-require-effective-target c++11 } -// { dg-require-effective-target pthread } -// { dg-require-gthreads "" } -// { dg-require-sleep "" } - -// Copyright (C) 2008-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 -#include - -namespace chr = std::chrono; - -void foo() -{ - 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() -{ - try - { - std::thread t(foo); - t.join(); - } - catch (const std::system_error&) - { - VERIFY( false ); - } - catch (...) - { - VERIFY( false ); - } - - return 0; -} diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/58038.cc b/libstdc++-v3/testsuite/30_threads/this_thread/58038.cc index 54ff0fb5321..fd007368527 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 531bb366c01..3f9d8b134d2 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/sleep_for-mt.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc new file mode 100644 index 00000000000..45993811d01 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_for-mt.cc @@ -0,0 +1,60 @@ +// { dg-do run } +// { dg-options "-pthread" } +// { dg-require-effective-target c++11 } +// { dg-require-effective-target pthread } +// { dg-require-gthreads "" } +// { dg-require-sleep "" } + +// Copyright (C) 2008-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 +#include + +namespace chr = std::chrono; + +void foo() +{ + 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() +{ + try + { + std::thread t(foo); + t.join(); + } + catch (const std::system_error&) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } + + return 0; +} 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 00000000000..9552a23435e --- /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/sleep_until-mt.cc b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc new file mode 100644 index 00000000000..fc8d10d8448 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/sleep_until-mt.cc @@ -0,0 +1,60 @@ +// { dg-do run } +// { dg-options "-pthread" } +// { dg-require-effective-target c++11 } +// { dg-require-effective-target pthread } +// { dg-require-gthreads "" } +// { dg-require-sleep "" } + +// Copyright (C) 2008-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 +#include + +namespace chr = std::chrono; + +void foo() +{ + 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() +{ + try + { + std::thread t(foo); + t.join(); + } + catch (const std::system_error&) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } + + return 0; +} 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 00000000000..6af875911df --- /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/yield.cc b/libstdc++-v3/testsuite/30_threads/this_thread/yield.cc new file mode 100644 index 00000000000..08f4efaaaf5 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/yield.cc @@ -0,0 +1,42 @@ +// { dg-do run { target c++11 } } +// { dg-additional-options "-pthread" { target pthread } } + +// Copyright (C) 2008-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 + +int main() +{ + try + { + std::this_thread::yield(); + } + catch (const std::system_error&) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } + + return 0; +}