1e4b17023SJohn Marino // thread -*- C++ -*-
2e4b17023SJohn Marino 
3*5ce9237cSJohn Marino // Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
4e4b17023SJohn Marino //
5e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
7e4b17023SJohn Marino // terms of the GNU General Public License as published by the
8e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
9e4b17023SJohn Marino // any later version.
10e4b17023SJohn Marino 
11e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
12e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
13e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14e4b17023SJohn Marino // GNU General Public License for more details.
15e4b17023SJohn Marino 
16e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19e4b17023SJohn Marino 
20e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24e4b17023SJohn Marino 
25e4b17023SJohn Marino 
26e4b17023SJohn Marino #include <thread>
27e4b17023SJohn Marino #include <system_error>
28e4b17023SJohn Marino #include <cerrno>
29*5ce9237cSJohn Marino #include <cxxabi_forced.h>
30e4b17023SJohn Marino 
31e4b17023SJohn Marino #if defined(_GLIBCXX_USE_GET_NPROCS)
32e4b17023SJohn Marino # include <sys/sysinfo.h>
33e4b17023SJohn Marino # define _GLIBCXX_NPROCS get_nprocs()
34e4b17023SJohn Marino #elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP)
35e4b17023SJohn Marino # define _GLIBCXX_NPROCS pthread_num_processors_np()
36e4b17023SJohn Marino #elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU)
37e4b17023SJohn Marino # include <stddef.h>
38e4b17023SJohn Marino # include <sys/sysctl.h>
get_nprocs()39e4b17023SJohn Marino static inline int get_nprocs()
40e4b17023SJohn Marino {
41e4b17023SJohn Marino  int count;
42e4b17023SJohn Marino  size_t size = sizeof(count);
43e4b17023SJohn Marino  int mib[] = { CTL_HW, HW_NCPU };
44e4b17023SJohn Marino  if (!sysctl(mib, 2, &count, &size, NULL, 0))
45e4b17023SJohn Marino    return count;
46e4b17023SJohn Marino  return 0;
47e4b17023SJohn Marino }
48e4b17023SJohn Marino # define _GLIBCXX_NPROCS get_nprocs()
49e4b17023SJohn Marino #elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)
50e4b17023SJohn Marino # include <unistd.h>
51e4b17023SJohn Marino # define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN)
52e4b17023SJohn Marino #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
53e4b17023SJohn Marino # include <unistd.h>
54e4b17023SJohn Marino # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
55e4b17023SJohn Marino #else
56e4b17023SJohn Marino # define _GLIBCXX_NPROCS 0
57e4b17023SJohn Marino #endif
58e4b17023SJohn Marino 
59e4b17023SJohn Marino #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
60e4b17023SJohn Marino 
61e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default)
62e4b17023SJohn Marino {
63e4b17023SJohn Marino   namespace
64e4b17023SJohn Marino   {
65e4b17023SJohn Marino     extern "C" void*
execute_native_thread_routine(void * __p)66e4b17023SJohn Marino     execute_native_thread_routine(void* __p)
67e4b17023SJohn Marino     {
68e4b17023SJohn Marino       thread::_Impl_base* __t = static_cast<thread::_Impl_base*>(__p);
69e4b17023SJohn Marino       thread::__shared_base_type __local;
70e4b17023SJohn Marino       __local.swap(__t->_M_this_ptr);
71e4b17023SJohn Marino 
72e4b17023SJohn Marino       __try
73e4b17023SJohn Marino 	{
74e4b17023SJohn Marino 	  __t->_M_run();
75e4b17023SJohn Marino 	}
76*5ce9237cSJohn Marino       __catch(const __cxxabiv1::__forced_unwind&)
77*5ce9237cSJohn Marino 	{
78*5ce9237cSJohn Marino 	  __throw_exception_again;
79*5ce9237cSJohn Marino 	}
80e4b17023SJohn Marino       __catch(...)
81e4b17023SJohn Marino 	{
82e4b17023SJohn Marino 	  std::terminate();
83e4b17023SJohn Marino 	}
84e4b17023SJohn Marino 
85e4b17023SJohn Marino       return 0;
86e4b17023SJohn Marino     }
87e4b17023SJohn Marino   }
88e4b17023SJohn Marino 
89e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION
90e4b17023SJohn Marino 
91e4b17023SJohn Marino   void
join()92e4b17023SJohn Marino   thread::join()
93e4b17023SJohn Marino   {
94e4b17023SJohn Marino     int __e = EINVAL;
95e4b17023SJohn Marino 
96e4b17023SJohn Marino     if (_M_id != id())
97e4b17023SJohn Marino       __e = __gthread_join(_M_id._M_thread, 0);
98e4b17023SJohn Marino 
99e4b17023SJohn Marino     if (__e)
100e4b17023SJohn Marino       __throw_system_error(__e);
101e4b17023SJohn Marino 
102e4b17023SJohn Marino     _M_id = id();
103e4b17023SJohn Marino   }
104e4b17023SJohn Marino 
105e4b17023SJohn Marino   void
detach()106e4b17023SJohn Marino   thread::detach()
107e4b17023SJohn Marino   {
108e4b17023SJohn Marino     int __e = EINVAL;
109e4b17023SJohn Marino 
110e4b17023SJohn Marino     if (_M_id != id())
111e4b17023SJohn Marino       __e = __gthread_detach(_M_id._M_thread);
112e4b17023SJohn Marino 
113e4b17023SJohn Marino     if (__e)
114e4b17023SJohn Marino       __throw_system_error(__e);
115e4b17023SJohn Marino 
116e4b17023SJohn Marino     _M_id = id();
117e4b17023SJohn Marino   }
118e4b17023SJohn Marino 
119e4b17023SJohn Marino   void
_M_start_thread(__shared_base_type __b)120e4b17023SJohn Marino   thread::_M_start_thread(__shared_base_type __b)
121e4b17023SJohn Marino   {
122e4b17023SJohn Marino     if (!__gthread_active_p())
123e4b17023SJohn Marino       __throw_system_error(int(errc::operation_not_permitted));
124e4b17023SJohn Marino 
125e4b17023SJohn Marino     __b->_M_this_ptr = __b;
126e4b17023SJohn Marino     int __e = __gthread_create(&_M_id._M_thread,
127e4b17023SJohn Marino 			       &execute_native_thread_routine, __b.get());
128e4b17023SJohn Marino     if (__e)
129e4b17023SJohn Marino     {
130e4b17023SJohn Marino       __b->_M_this_ptr.reset();
131e4b17023SJohn Marino       __throw_system_error(__e);
132e4b17023SJohn Marino     }
133e4b17023SJohn Marino   }
134e4b17023SJohn Marino 
135e4b17023SJohn Marino   unsigned int
hardware_concurrency()136e4b17023SJohn Marino   thread::hardware_concurrency() noexcept
137e4b17023SJohn Marino   {
138e4b17023SJohn Marino     int __n = _GLIBCXX_NPROCS;
139e4b17023SJohn Marino     if (__n < 0)
140e4b17023SJohn Marino       __n = 0;
141e4b17023SJohn Marino     return __n;
142e4b17023SJohn Marino   }
143e4b17023SJohn Marino 
144e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION
145e4b17023SJohn Marino } // namespace std
146e4b17023SJohn Marino 
147e4b17023SJohn Marino #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
148