xref: /minix3/external/bsd/libc++/dist/libcxx/src/thread.cpp (revision 4684ddb6aab0b36791c8099bc705d6140b3d05d0)
1*4684ddb6SLionel Sambuc //===------------------------- thread.cpp----------------------------------===//
2*4684ddb6SLionel Sambuc //
3*4684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
4*4684ddb6SLionel Sambuc //
5*4684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6*4684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7*4684ddb6SLionel Sambuc //
8*4684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
9*4684ddb6SLionel Sambuc 
10*4684ddb6SLionel Sambuc #include "thread"
11*4684ddb6SLionel Sambuc #include "exception"
12*4684ddb6SLionel Sambuc #include "vector"
13*4684ddb6SLionel Sambuc #include "future"
14*4684ddb6SLionel Sambuc #include "limits"
15*4684ddb6SLionel Sambuc #include <sys/types.h>
16*4684ddb6SLionel Sambuc #if !defined(_WIN32)
17*4684ddb6SLionel Sambuc #if !defined(__sun__) && !defined(__linux__) && !defined(_AIX)
18*4684ddb6SLionel Sambuc #include <sys/sysctl.h>
19*4684ddb6SLionel Sambuc #endif // !__sun__ && !__linux__ && !_AIX
20*4684ddb6SLionel Sambuc #include <unistd.h>
21*4684ddb6SLionel Sambuc #endif // !_WIN32
22*4684ddb6SLionel Sambuc 
23*4684ddb6SLionel Sambuc #if defined(__NetBSD__) || defined(__minix)
24*4684ddb6SLionel Sambuc #pragma weak pthread_create // Do not create libpthread dependency
25*4684ddb6SLionel Sambuc #endif
26*4684ddb6SLionel Sambuc #if defined(_WIN32)
27*4684ddb6SLionel Sambuc #include <windows.h>
28*4684ddb6SLionel Sambuc #endif
29*4684ddb6SLionel Sambuc 
30*4684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
31*4684ddb6SLionel Sambuc 
32*4684ddb6SLionel Sambuc thread::~thread()
33*4684ddb6SLionel Sambuc {
34*4684ddb6SLionel Sambuc     if (__t_ != 0)
35*4684ddb6SLionel Sambuc         terminate();
36*4684ddb6SLionel Sambuc }
37*4684ddb6SLionel Sambuc 
38*4684ddb6SLionel Sambuc void
39*4684ddb6SLionel Sambuc thread::join()
40*4684ddb6SLionel Sambuc {
41*4684ddb6SLionel Sambuc     int ec = pthread_join(__t_, 0);
42*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
43*4684ddb6SLionel Sambuc     if (ec)
44*4684ddb6SLionel Sambuc         throw system_error(error_code(ec, system_category()), "thread::join failed");
45*4684ddb6SLionel Sambuc #else
46*4684ddb6SLionel Sambuc     (void)ec;
47*4684ddb6SLionel Sambuc #endif  // _LIBCPP_NO_EXCEPTIONS
48*4684ddb6SLionel Sambuc     __t_ = 0;
49*4684ddb6SLionel Sambuc }
50*4684ddb6SLionel Sambuc 
51*4684ddb6SLionel Sambuc void
52*4684ddb6SLionel Sambuc thread::detach()
53*4684ddb6SLionel Sambuc {
54*4684ddb6SLionel Sambuc     int ec = EINVAL;
55*4684ddb6SLionel Sambuc     if (__t_ != 0)
56*4684ddb6SLionel Sambuc     {
57*4684ddb6SLionel Sambuc         ec = pthread_detach(__t_);
58*4684ddb6SLionel Sambuc         if (ec == 0)
59*4684ddb6SLionel Sambuc             __t_ = 0;
60*4684ddb6SLionel Sambuc     }
61*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
62*4684ddb6SLionel Sambuc     if (ec)
63*4684ddb6SLionel Sambuc         throw system_error(error_code(ec, system_category()), "thread::detach failed");
64*4684ddb6SLionel Sambuc #endif  // _LIBCPP_NO_EXCEPTIONS
65*4684ddb6SLionel Sambuc }
66*4684ddb6SLionel Sambuc 
67*4684ddb6SLionel Sambuc unsigned
68*4684ddb6SLionel Sambuc thread::hardware_concurrency() _NOEXCEPT
69*4684ddb6SLionel Sambuc {
70*4684ddb6SLionel Sambuc #if defined(CTL_HW) && defined(HW_NCPU)
71*4684ddb6SLionel Sambuc     unsigned n;
72*4684ddb6SLionel Sambuc     int mib[2] = {CTL_HW, HW_NCPU};
73*4684ddb6SLionel Sambuc     std::size_t s = sizeof(n);
74*4684ddb6SLionel Sambuc     sysctl(mib, 2, &n, &s, 0, 0);
75*4684ddb6SLionel Sambuc     return n;
76*4684ddb6SLionel Sambuc #elif defined(_SC_NPROCESSORS_ONLN)
77*4684ddb6SLionel Sambuc     long result = sysconf(_SC_NPROCESSORS_ONLN);
78*4684ddb6SLionel Sambuc     // sysconf returns -1 if the name is invalid, the option does not exist or
79*4684ddb6SLionel Sambuc     // does not have a definite limit.
80*4684ddb6SLionel Sambuc     // if sysconf returns some other negative number, we have no idea
81*4684ddb6SLionel Sambuc     // what is going on. Default to something safe.
82*4684ddb6SLionel Sambuc     if (result < 0)
83*4684ddb6SLionel Sambuc         return 0;
84*4684ddb6SLionel Sambuc     return static_cast<unsigned>(result);
85*4684ddb6SLionel Sambuc #elif defined(_WIN32)
86*4684ddb6SLionel Sambuc     SYSTEM_INFO info;
87*4684ddb6SLionel Sambuc     GetSystemInfo(&info);
88*4684ddb6SLionel Sambuc     return info.dwNumberOfProcessors;
89*4684ddb6SLionel Sambuc #else  // defined(CTL_HW) && defined(HW_NCPU)
90*4684ddb6SLionel Sambuc     // TODO: grovel through /proc or check cpuid on x86 and similar
91*4684ddb6SLionel Sambuc     // instructions on other architectures.
92*4684ddb6SLionel Sambuc #   if defined(_MSC_VER) && ! defined(__clang__)
93*4684ddb6SLionel Sambuc         _LIBCPP_WARNING("hardware_concurrency not yet implemented")
94*4684ddb6SLionel Sambuc #   else
95*4684ddb6SLionel Sambuc #       warning hardware_concurrency not yet implemented
96*4684ddb6SLionel Sambuc #   endif
97*4684ddb6SLionel Sambuc     return 0;  // Means not computable [thread.thread.static]
98*4684ddb6SLionel Sambuc #endif  // defined(CTL_HW) && defined(HW_NCPU)
99*4684ddb6SLionel Sambuc }
100*4684ddb6SLionel Sambuc 
101*4684ddb6SLionel Sambuc namespace this_thread
102*4684ddb6SLionel Sambuc {
103*4684ddb6SLionel Sambuc 
104*4684ddb6SLionel Sambuc void
105*4684ddb6SLionel Sambuc sleep_for(const chrono::nanoseconds& ns)
106*4684ddb6SLionel Sambuc {
107*4684ddb6SLionel Sambuc     using namespace chrono;
108*4684ddb6SLionel Sambuc     if (ns > nanoseconds::zero())
109*4684ddb6SLionel Sambuc     {
110*4684ddb6SLionel Sambuc         seconds s = duration_cast<seconds>(ns);
111*4684ddb6SLionel Sambuc         timespec ts;
112*4684ddb6SLionel Sambuc         typedef decltype(ts.tv_sec) ts_sec;
113*4684ddb6SLionel Sambuc         _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
114*4684ddb6SLionel Sambuc         if (s.count() < ts_sec_max)
115*4684ddb6SLionel Sambuc         {
116*4684ddb6SLionel Sambuc             ts.tv_sec = static_cast<ts_sec>(s.count());
117*4684ddb6SLionel Sambuc             ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count());
118*4684ddb6SLionel Sambuc         }
119*4684ddb6SLionel Sambuc         else
120*4684ddb6SLionel Sambuc         {
121*4684ddb6SLionel Sambuc             ts.tv_sec = ts_sec_max;
122*4684ddb6SLionel Sambuc             ts.tv_nsec = giga::num - 1;
123*4684ddb6SLionel Sambuc         }
124*4684ddb6SLionel Sambuc         nanosleep(&ts, 0);
125*4684ddb6SLionel Sambuc     }
126*4684ddb6SLionel Sambuc }
127*4684ddb6SLionel Sambuc 
128*4684ddb6SLionel Sambuc }  // this_thread
129*4684ddb6SLionel Sambuc 
130*4684ddb6SLionel Sambuc __thread_specific_ptr<__thread_struct>&
131*4684ddb6SLionel Sambuc __thread_local_data()
132*4684ddb6SLionel Sambuc {
133*4684ddb6SLionel Sambuc     static __thread_specific_ptr<__thread_struct> __p;
134*4684ddb6SLionel Sambuc     return __p;
135*4684ddb6SLionel Sambuc }
136*4684ddb6SLionel Sambuc 
137*4684ddb6SLionel Sambuc // __thread_struct_imp
138*4684ddb6SLionel Sambuc 
139*4684ddb6SLionel Sambuc template <class T>
140*4684ddb6SLionel Sambuc class _LIBCPP_HIDDEN __hidden_allocator
141*4684ddb6SLionel Sambuc {
142*4684ddb6SLionel Sambuc public:
143*4684ddb6SLionel Sambuc     typedef T  value_type;
144*4684ddb6SLionel Sambuc 
145*4684ddb6SLionel Sambuc     T* allocate(size_t __n)
146*4684ddb6SLionel Sambuc         {return static_cast<T*>(::operator new(__n * sizeof(T)));}
147*4684ddb6SLionel Sambuc     void deallocate(T* __p, size_t) {::operator delete((void*)__p);}
148*4684ddb6SLionel Sambuc 
149*4684ddb6SLionel Sambuc     size_t max_size() const {return size_t(~0) / sizeof(T);}
150*4684ddb6SLionel Sambuc };
151*4684ddb6SLionel Sambuc 
152*4684ddb6SLionel Sambuc class _LIBCPP_HIDDEN __thread_struct_imp
153*4684ddb6SLionel Sambuc {
154*4684ddb6SLionel Sambuc     typedef vector<__assoc_sub_state*,
155*4684ddb6SLionel Sambuc                           __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
156*4684ddb6SLionel Sambuc     typedef vector<pair<condition_variable*, mutex*>,
157*4684ddb6SLionel Sambuc                __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
158*4684ddb6SLionel Sambuc 
159*4684ddb6SLionel Sambuc     _AsyncStates async_states_;
160*4684ddb6SLionel Sambuc     _Notify notify_;
161*4684ddb6SLionel Sambuc 
162*4684ddb6SLionel Sambuc     __thread_struct_imp(const __thread_struct_imp&);
163*4684ddb6SLionel Sambuc     __thread_struct_imp& operator=(const __thread_struct_imp&);
164*4684ddb6SLionel Sambuc public:
165*4684ddb6SLionel Sambuc     __thread_struct_imp() {}
166*4684ddb6SLionel Sambuc     ~__thread_struct_imp();
167*4684ddb6SLionel Sambuc 
168*4684ddb6SLionel Sambuc     void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
169*4684ddb6SLionel Sambuc     void __make_ready_at_thread_exit(__assoc_sub_state* __s);
170*4684ddb6SLionel Sambuc };
171*4684ddb6SLionel Sambuc 
172*4684ddb6SLionel Sambuc __thread_struct_imp::~__thread_struct_imp()
173*4684ddb6SLionel Sambuc {
174*4684ddb6SLionel Sambuc     for (_Notify::iterator i = notify_.begin(), e = notify_.end();
175*4684ddb6SLionel Sambuc             i != e; ++i)
176*4684ddb6SLionel Sambuc     {
177*4684ddb6SLionel Sambuc         i->second->unlock();
178*4684ddb6SLionel Sambuc         i->first->notify_all();
179*4684ddb6SLionel Sambuc     }
180*4684ddb6SLionel Sambuc     for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
181*4684ddb6SLionel Sambuc             i != e; ++i)
182*4684ddb6SLionel Sambuc     {
183*4684ddb6SLionel Sambuc         (*i)->__make_ready();
184*4684ddb6SLionel Sambuc         (*i)->__release_shared();
185*4684ddb6SLionel Sambuc     }
186*4684ddb6SLionel Sambuc }
187*4684ddb6SLionel Sambuc 
188*4684ddb6SLionel Sambuc void
189*4684ddb6SLionel Sambuc __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
190*4684ddb6SLionel Sambuc {
191*4684ddb6SLionel Sambuc     notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
192*4684ddb6SLionel Sambuc }
193*4684ddb6SLionel Sambuc 
194*4684ddb6SLionel Sambuc void
195*4684ddb6SLionel Sambuc __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
196*4684ddb6SLionel Sambuc {
197*4684ddb6SLionel Sambuc     async_states_.push_back(__s);
198*4684ddb6SLionel Sambuc     __s->__add_shared();
199*4684ddb6SLionel Sambuc }
200*4684ddb6SLionel Sambuc 
201*4684ddb6SLionel Sambuc // __thread_struct
202*4684ddb6SLionel Sambuc 
203*4684ddb6SLionel Sambuc __thread_struct::__thread_struct()
204*4684ddb6SLionel Sambuc     : __p_(new __thread_struct_imp)
205*4684ddb6SLionel Sambuc {
206*4684ddb6SLionel Sambuc }
207*4684ddb6SLionel Sambuc 
208*4684ddb6SLionel Sambuc __thread_struct::~__thread_struct()
209*4684ddb6SLionel Sambuc {
210*4684ddb6SLionel Sambuc     delete __p_;
211*4684ddb6SLionel Sambuc }
212*4684ddb6SLionel Sambuc 
213*4684ddb6SLionel Sambuc void
214*4684ddb6SLionel Sambuc __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
215*4684ddb6SLionel Sambuc {
216*4684ddb6SLionel Sambuc     __p_->notify_all_at_thread_exit(cv, m);
217*4684ddb6SLionel Sambuc }
218*4684ddb6SLionel Sambuc 
219*4684ddb6SLionel Sambuc void
220*4684ddb6SLionel Sambuc __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
221*4684ddb6SLionel Sambuc {
222*4684ddb6SLionel Sambuc     __p_->__make_ready_at_thread_exit(__s);
223*4684ddb6SLionel Sambuc }
224*4684ddb6SLionel Sambuc 
225*4684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
226