blob: cc8c3274be4f3b6d5dcd563cf60b0b2d525db4aa [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------- thread.cpp----------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "thread"
11#include "exception"
Howard Hinnant47499b12010-08-27 20:10:19 +000012#include "vector"
13#include "future"
Howard Hinnant0bfe8802010-05-25 17:25:25 +000014#include <sys/types.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000015#if !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000016#include <sys/sysctl.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000017#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018
19_LIBCPP_BEGIN_NAMESPACE_STD
20
21thread::~thread()
22{
Howard Hinnantadff4892010-05-24 17:49:41 +000023 if (__t_ != 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024 terminate();
25}
26
27void
28thread::join()
29{
30 int ec = pthread_join(__t_, 0);
Howard Hinnantd4444702010-08-11 17:04:31 +000031#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000032 if (ec)
33 throw system_error(error_code(ec, system_category()), "thread::join failed");
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000034#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantadff4892010-05-24 17:49:41 +000035 __t_ = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036}
37
38void
39thread::detach()
40{
41 int ec = EINVAL;
42 if (__t_ != 0)
43 {
44 ec = pthread_detach(__t_);
45 if (ec == 0)
46 __t_ = 0;
47 }
Howard Hinnantd4444702010-08-11 17:04:31 +000048#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049 if (ec)
50 throw system_error(error_code(ec, system_category()), "thread::detach failed");
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000051#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000052}
53
54unsigned
55thread::hardware_concurrency()
56{
Howard Hinnantadff4892010-05-24 17:49:41 +000057#if defined(CTL_HW) && defined(HW_NCPU)
Howard Hinnantec3773c2011-12-01 20:21:04 +000058 unsigned n;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000059 int mib[2] = {CTL_HW, HW_NCPU};
60 std::size_t s = sizeof(n);
61 sysctl(mib, 2, &n, &s, 0, 0);
62 return n;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000063#else // defined(CTL_HW) && defined(HW_NCPU)
Howard Hinnantadff4892010-05-24 17:49:41 +000064 // TODO: grovel through /proc or check cpuid on x86 and similar
65 // instructions on other architectures.
66 return 0; // Means not computable [thread.thread.static]
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000067#endif // defined(CTL_HW) && defined(HW_NCPU)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000068}
69
70namespace this_thread
71{
72
73void
74sleep_for(const chrono::nanoseconds& ns)
75{
76 using namespace chrono;
77 if (ns >= nanoseconds::zero())
78 {
79 timespec ts;
80 ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count());
81 ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count());
82 nanosleep(&ts, 0);
83 }
84}
85
86} // this_thread
87
Howard Hinnant5306d682010-10-14 19:18:04 +000088__thread_specific_ptr<__thread_struct>&
89__thread_local_data()
90{
91 static __thread_specific_ptr<__thread_struct> __p;
92 return __p;
93}
Howard Hinnant47499b12010-08-27 20:10:19 +000094
95// __thread_struct_imp
96
Howard Hinnant2d72b1e2010-12-17 14:46:43 +000097template <class T>
98class _LIBCPP_HIDDEN __hidden_allocator
Howard Hinnant47499b12010-08-27 20:10:19 +000099{
Howard Hinnant2d72b1e2010-12-17 14:46:43 +0000100public:
101 typedef T value_type;
102
103 T* allocate(size_t __n)
104 {return static_cast<T*>(::operator new(__n * sizeof(T)));}
105 void deallocate(T* __p, size_t) {::operator delete((void*)__p);}
106
107 size_t max_size() const {return size_t(~0) / sizeof(T);}
108};
109
110class _LIBCPP_HIDDEN __thread_struct_imp
111{
112 typedef vector<__assoc_sub_state*,
113 __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
114 typedef vector<pair<condition_variable*, mutex*>,
115 __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
Howard Hinnante6e4d012010-09-03 21:46:37 +0000116
Howard Hinnant47499b12010-08-27 20:10:19 +0000117 _AsyncStates async_states_;
Howard Hinnante6e4d012010-09-03 21:46:37 +0000118 _Notify notify_;
Howard Hinnant47499b12010-08-27 20:10:19 +0000119
120 __thread_struct_imp(const __thread_struct_imp&);
121 __thread_struct_imp& operator=(const __thread_struct_imp&);
122public:
123 __thread_struct_imp() {}
124 ~__thread_struct_imp();
125
Howard Hinnante6e4d012010-09-03 21:46:37 +0000126 void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
Howard Hinnant47499b12010-08-27 20:10:19 +0000127 void __make_ready_at_thread_exit(__assoc_sub_state* __s);
128};
129
130__thread_struct_imp::~__thread_struct_imp()
131{
Howard Hinnante6e4d012010-09-03 21:46:37 +0000132 for (_Notify::iterator i = notify_.begin(), e = notify_.end();
133 i != e; ++i)
134 {
135 i->second->unlock();
136 i->first->notify_all();
137 }
Howard Hinnant47499b12010-08-27 20:10:19 +0000138 for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
139 i != e; ++i)
140 {
141 (*i)->__make_ready();
142 (*i)->__release_shared();
143 }
144}
145
146void
Howard Hinnante6e4d012010-09-03 21:46:37 +0000147__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
148{
149 notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
150}
151
152void
Howard Hinnant47499b12010-08-27 20:10:19 +0000153__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
154{
155 async_states_.push_back(__s);
156 __s->__add_shared();
157}
158
159// __thread_struct
160
161__thread_struct::__thread_struct()
162 : __p_(new __thread_struct_imp)
163{
164}
165
166__thread_struct::~__thread_struct()
167{
168 delete __p_;
169}
170
171void
Howard Hinnante6e4d012010-09-03 21:46:37 +0000172__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
173{
174 __p_->notify_all_at_thread_exit(cv, m);
175}
176
177void
Howard Hinnant47499b12010-08-27 20:10:19 +0000178__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
179{
180 __p_->__make_ready_at_thread_exit(__s);
181}
182
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000183_LIBCPP_END_NAMESPACE_STD