Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. // thread -*- C++ -*-
  2.  
  3. // Copyright (C) 2008-2013 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.   namespace
  74.   {
  75.     extern "C" 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 0;
  96.     }
  97.   }
  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 __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.     __b->_M_this_ptr = __b;
  141.     int __e = __gthread_create(&_M_id._M_thread,
  142.                                &execute_native_thread_routine, __b.get());
  143.     if (__e)
  144.     {
  145.       __b->_M_this_ptr.reset();
  146.       __throw_system_error(__e);
  147.     }
  148.   }
  149.  
  150.   unsigned int
  151.   thread::hardware_concurrency() noexcept
  152.   {
  153.     int __n = _GLIBCXX_NPROCS;
  154.     if (__n < 0)
  155.       __n = 0;
  156.     return __n;
  157.   }
  158.  
  159. _GLIBCXX_END_NAMESPACE_VERSION
  160.  
  161. namespace this_thread
  162. {
  163. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  164.  
  165.   void
  166.   __sleep_for(chrono::seconds __s, chrono::nanoseconds __ns)
  167.   {
  168. #ifdef _GLIBCXX_USE_NANOSLEEP
  169.     __gthread_time_t __ts =
  170.       {
  171.         static_cast<std::time_t>(__s.count()),
  172.         static_cast<long>(__ns.count())
  173.       };
  174.     ::nanosleep(&__ts, 0);
  175. #elif defined(_GLIBCXX_HAVE_SLEEP)
  176. # ifdef _GLIBCXX_HAVE_USLEEP
  177.     ::sleep(__s.count());
  178.     if (__ns.count() > 0)
  179.       {
  180.         long __us = __ns.count() / 1000;
  181.         if (__us == 0)
  182.           __us = 1;
  183.         ::usleep(__us);
  184.       }
  185. # else
  186.     ::sleep(__s.count() + (__ns >= 1000000));
  187. # endif
  188. #elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
  189.     unsigned long ms = __ns.count() / 1000000;
  190.     if (__ns.count() > 0 && ms == 0)
  191.       ms = 1;
  192.     ::Sleep(chrono::milliseconds(__s).count() + ms);
  193. #endif
  194.   }
  195.  
  196. _GLIBCXX_END_NAMESPACE_VERSION
  197. }
  198.  
  199. } // namespace std
  200.  
  201. #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
  202.