Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // thread -*- C++ -*-
  2.  
  3. // Copyright (C) 2008-2015 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25.  
  26. #include <thread>
  27. #include <system_error>
  28. #include <cerrno>
  29. #include <cxxabi_forced.h>
  30.  
  31. #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
  32.  
  33. #if defined(_GLIBCXX_USE_GET_NPROCS)
  34. # include <sys/sysinfo.h>
  35. # define _GLIBCXX_NPROCS get_nprocs()
  36. #elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP)
  37. # define _GLIBCXX_NPROCS pthread_num_processors_np()
  38. #elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU)
  39. # include <stddef.h>
  40. # include <sys/sysctl.h>
  41. static inline int get_nprocs()
  42. {
  43.  int count;
  44.  size_t size = sizeof(count);
  45.  int mib[] = { CTL_HW, HW_NCPU };
  46.  if (!sysctl(mib, 2, &count, &size, NULL, 0))
  47.    return count;
  48.  return 0;
  49. }
  50. # define _GLIBCXX_NPROCS get_nprocs()
  51. #elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)
  52. # include <unistd.h>
  53. # define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN)
  54. #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
  55. # include <unistd.h>
  56. # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
  57. #else
  58. # define _GLIBCXX_NPROCS 0
  59. #endif
  60.  
  61. #ifndef _GLIBCXX_USE_NANOSLEEP
  62. # ifdef _GLIBCXX_HAVE_SLEEP
  63. #  include <unistd.h>
  64. # elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
  65. #  include <windows.h>
  66. # else
  67. #  error "No sleep function known for this target"
  68. # endif
  69. #endif
  70.  
  71. namespace std _GLIBCXX_VISIBILITY(default)
  72. {
  73.   extern "C"
  74.   {
  75.     static void*
  76.     execute_native_thread_routine(void* __p)
  77.     {
  78.       thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
  79.       thread::__shared_base_type __local;
  80.       __local.swap(__t->_M_this_ptr);
  81.  
  82.       __try
  83.         {
  84.           __t->_M_run();
  85.         }
  86.       __catch(const __cxxabiv1::__forced_unwind&)
  87.         {
  88.           __throw_exception_again;
  89.         }
  90.       __catch(...)
  91.         {
  92.           std::terminate();
  93.         }
  94.  
  95.       return nullptr;
  96.     }
  97.   } // extern "C"
  98.  
  99. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  100.  
  101.   void
  102.   thread::join()
  103.   {
  104.     int __e = EINVAL;
  105.  
  106.     if (_M_id != id())
  107.       __e = __gthread_join(_M_id._M_thread, 0);
  108.  
  109.     if (__e)
  110.       __throw_system_error(__e);
  111.  
  112.     _M_id = id();
  113.   }
  114.  
  115.   void
  116.   thread::detach()
  117.   {
  118.     int __e = EINVAL;
  119.  
  120.     if (_M_id != id())
  121.       __e = __gthread_detach(_M_id._M_thread);
  122.  
  123.     if (__e)
  124.       __throw_system_error(__e);
  125.  
  126.     _M_id = id();
  127.   }
  128.  
  129.   void
  130.   thread::_M_start_thread(__shared_base_type __b)
  131.   {
  132.     if (!__gthread_active_p())
  133. #if __cpp_exceptions
  134.       throw system_error(make_error_code(errc::operation_not_permitted),
  135.                          "Enable multithreading to use std::thread");
  136. #else
  137.       __throw_system_error(int(errc::operation_not_permitted));
  138. #endif
  139.  
  140.     _M_start_thread(std::move(__b), nullptr);
  141.   }
  142.  
  143.   void
  144.   thread::_M_start_thread(__shared_base_type __b, void (*)())
  145.   {
  146.     auto ptr = __b.get();
  147.     ptr->_M_this_ptr = std::move(__b);
  148.     int __e = __gthread_create(&_M_id._M_thread,
  149.                                &execute_native_thread_routine, ptr);
  150.     if (__e)
  151.     {
  152.       ptr->_M_this_ptr.reset();
  153.       __throw_system_error(__e);
  154.     }
  155.   }
  156.  
  157.   unsigned int
  158.   thread::hardware_concurrency() noexcept
  159.   {
  160.     int __n = _GLIBCXX_NPROCS;
  161.     if (__n < 0)
  162.       __n = 0;
  163.     return __n;
  164.   }
  165.  
  166. _GLIBCXX_END_NAMESPACE_VERSION
  167.  
  168. namespace this_thread
  169. {
  170. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  171.  
  172.   void
  173.   __sleep_for(chrono::seconds __s, chrono::nanoseconds __ns)
  174.   {
  175. #ifdef _GLIBCXX_USE_NANOSLEEP
  176.     __gthread_time_t __ts =
  177.       {
  178.         static_cast<std::time_t>(__s.count()),
  179.         static_cast<long>(__ns.count())
  180.       };
  181.     ::nanosleep(&__ts, 0);
  182. #elif defined(_GLIBCXX_HAVE_SLEEP)
  183. # ifdef _GLIBCXX_HAVE_USLEEP
  184.     ::sleep(__s.count());
  185.     if (__ns.count() > 0)
  186.       {
  187.         long __us = __ns.count() / 1000;
  188.         if (__us == 0)
  189.           __us = 1;
  190.         ::usleep(__us);
  191.       }
  192. # else
  193.     ::sleep(__s.count() + (__ns.count() >= 1000000));
  194. # endif
  195. #elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
  196.     unsigned long ms = __ns.count() / 1000000;
  197.     if (__ns.count() > 0 && ms == 0)
  198.       ms = 1;
  199.     ::Sleep(chrono::milliseconds(__s).count() + ms);
  200. #endif
  201.   }
  202.  
  203. _GLIBCXX_END_NAMESPACE_VERSION
  204. }
  205.  
  206. } // namespace std
  207.  
  208. #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
  209.