thread.cpp revision 253159
1179055Sjfv//===------------------------- thread.cpp----------------------------------===//
2171384Sjfv//
3230775Sjfv//                     The LLVM Compiler Infrastructure
4171384Sjfv//
5171384Sjfv// This file is dual licensed under the MIT and the University of Illinois Open
6171384Sjfv// Source Licenses. See LICENSE.TXT for details.
7171384Sjfv//
8171384Sjfv//===----------------------------------------------------------------------===//
9171384Sjfv
10171384Sjfv#include "thread"
11171384Sjfv#include "exception"
12171384Sjfv#include "vector"
13171384Sjfv#include "future"
14171384Sjfv#include "limits"
15171384Sjfv#include <sys/types.h>
16171384Sjfv#if !defined(_WIN32)
17171384Sjfv#if !defined(__sun__) && !defined(__linux__)
18171384Sjfv#include <sys/sysctl.h>
19171384Sjfv#endif // !__sun__ && !__linux__
20171384Sjfv#include <unistd.h>
21171384Sjfv#endif // !_WIN32
22171384Sjfv
23171384Sjfv#if defined(__NetBSD__)
24171384Sjfv#pragma weak pthread_create // Do not create libpthread dependency
25171384Sjfv#endif
26171384Sjfv#if defined(_WIN32)
27171384Sjfv#include <windows.h>
28171384Sjfv#endif
29171384Sjfv
30171384Sjfv_LIBCPP_BEGIN_NAMESPACE_STD
31171384Sjfv
32179055Sjfvthread::~thread()
33179055Sjfv{
34171384Sjfv    if (__t_ != 0)
35171384Sjfv        terminate();
36171384Sjfv}
37171384Sjfv
38171384Sjfvvoid
39171384Sjfvthread::join()
40194875Sjfv{
41171384Sjfv    int ec = pthread_join(__t_, 0);
42230775Sjfv#ifndef _LIBCPP_NO_EXCEPTIONS
43171384Sjfv    if (ec)
44171384Sjfv        throw system_error(error_code(ec, system_category()), "thread::join failed");
45230775Sjfv#else
46230775Sjfv    (void)ec;
47230775Sjfv#endif  // _LIBCPP_NO_EXCEPTIONS
48230775Sjfv    __t_ = 0;
49230775Sjfv}
50230775Sjfv
51230775Sjfvvoid
52230775Sjfvthread::detach()
53230775Sjfv{
54230775Sjfv    int ec = EINVAL;
55230775Sjfv    if (__t_ != 0)
56230775Sjfv    {
57230775Sjfv        ec = pthread_detach(__t_);
58230775Sjfv        if (ec == 0)
59230775Sjfv            __t_ = 0;
60230775Sjfv    }
61230775Sjfv#ifndef _LIBCPP_NO_EXCEPTIONS
62230775Sjfv    if (ec)
63230775Sjfv        throw system_error(error_code(ec, system_category()), "thread::detach failed");
64230775Sjfv#endif  // _LIBCPP_NO_EXCEPTIONS
65230775Sjfv}
66230775Sjfv
67230775Sjfvunsigned
68230775Sjfvthread::hardware_concurrency() _NOEXCEPT
69238149Sjfv{
70230775Sjfv#if defined(CTL_HW) && defined(HW_NCPU)
71230775Sjfv    unsigned n;
72230775Sjfv    int mib[2] = {CTL_HW, HW_NCPU};
73230775Sjfv    std::size_t s = sizeof(n);
74230775Sjfv    sysctl(mib, 2, &n, &s, 0, 0);
75230775Sjfv    return n;
76238149Sjfv#elif defined(_SC_NPROCESSORS_ONLN)
77171384Sjfv    long result = sysconf(_SC_NPROCESSORS_ONLN);
78171384Sjfv    // sysconf returns -1 if the name is invalid, the option does not exist or
79230775Sjfv    // does not have a definite limit.
80230775Sjfv    // if sysconf returns some other negative number, we have no idea
81230775Sjfv    // what is going on. Default to something safe.
82230775Sjfv    if (result < 0)
83230775Sjfv        return 0;
84230775Sjfv    return static_cast<unsigned>(result);
85230775Sjfv#elif defined(_WIN32)
86230775Sjfv    SYSTEM_INFO info;
87230775Sjfv    GetSystemInfo(&info);
88230775Sjfv    return info.dwNumberOfProcessors;
89230775Sjfv#else  // defined(CTL_HW) && defined(HW_NCPU)
90230775Sjfv    // TODO: grovel through /proc or check cpuid on x86 and similar
91230775Sjfv    // instructions on other architectures.
92230775Sjfv#warning hardware_concurrency not yet implemented
93230775Sjfv    return 0;  // Means not computable [thread.thread.static]
94230775Sjfv#endif  // defined(CTL_HW) && defined(HW_NCPU)
95171384Sjfv}
96171384Sjfv
97230775Sjfvnamespace this_thread
98230775Sjfv{
99230775Sjfv
100230775Sjfvvoid
101230775Sjfvsleep_for(const chrono::nanoseconds& ns)
102230775Sjfv{
103230775Sjfv    using namespace chrono;
104230775Sjfv    if (ns > nanoseconds::zero())
105230775Sjfv    {
106230775Sjfv        seconds s = duration_cast<seconds>(ns);
107230775Sjfv        timespec ts;
108230775Sjfv        typedef decltype(ts.tv_sec) ts_sec;
109230775Sjfv        _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
110171384Sjfv        if (s.count() < ts_sec_max)
111190873Sjfv        {
112230775Sjfv            ts.tv_sec = static_cast<ts_sec>(s.count());
113230775Sjfv            ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count());
114190873Sjfv        }
115230775Sjfv        else
116230775Sjfv        {
117190873Sjfv            ts.tv_sec = ts_sec_max;
118190873Sjfv            ts.tv_nsec = giga::num - 1;
119230775Sjfv        }
120230775Sjfv        nanosleep(&ts, 0);
121230775Sjfv    }
122230775Sjfv}
123238149Sjfv
124190873Sjfv}  // this_thread
125238149Sjfv
126171384Sjfv__thread_specific_ptr<__thread_struct>&
127230775Sjfv__thread_local_data()
128230775Sjfv{
129230775Sjfv    static __thread_specific_ptr<__thread_struct> __p;
130230775Sjfv    return __p;
131230775Sjfv}
132230775Sjfv
133230775Sjfv// __thread_struct_imp
134230775Sjfv
135230775Sjfvtemplate <class T>
136230775Sjfvclass _LIBCPP_HIDDEN __hidden_allocator
137190873Sjfv{
138190873Sjfvpublic:
139190873Sjfv    typedef T  value_type;
140190873Sjfv
141190873Sjfv    T* allocate(size_t __n)
142230775Sjfv        {return static_cast<T*>(::operator new(__n * sizeof(T)));}
143230775Sjfv    void deallocate(T* __p, size_t) {::operator delete((void*)__p);}
144230775Sjfv
145230775Sjfv    size_t max_size() const {return size_t(~0) / sizeof(T);}
146230775Sjfv};
147230775Sjfv
148230775Sjfvclass _LIBCPP_HIDDEN __thread_struct_imp
149230775Sjfv{
150230775Sjfv    typedef vector<__assoc_sub_state*,
151230775Sjfv                          __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
152230775Sjfv    typedef vector<pair<condition_variable*, mutex*>,
153230775Sjfv               __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
154230775Sjfv
155230775Sjfv    _AsyncStates async_states_;
156230775Sjfv    _Notify notify_;
157230775Sjfv
158171384Sjfv    __thread_struct_imp(const __thread_struct_imp&);
159171384Sjfv    __thread_struct_imp& operator=(const __thread_struct_imp&);
160230775Sjfvpublic:
161230775Sjfv    __thread_struct_imp() {}
162230775Sjfv    ~__thread_struct_imp();
163230775Sjfv
164230775Sjfv    void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
165230775Sjfv    void __make_ready_at_thread_exit(__assoc_sub_state* __s);
166230775Sjfv};
167230775Sjfv
168230775Sjfv__thread_struct_imp::~__thread_struct_imp()
169230775Sjfv{
170230775Sjfv    for (_Notify::iterator i = notify_.begin(), e = notify_.end();
171230775Sjfv            i != e; ++i)
172230775Sjfv    {
173171384Sjfv        i->second->unlock();
174171384Sjfv        i->first->notify_all();
175230775Sjfv    }
176230775Sjfv    for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
177230775Sjfv            i != e; ++i)
178230775Sjfv    {
179230775Sjfv        (*i)->__make_ready();
180230775Sjfv        (*i)->__release_shared();
181230775Sjfv    }
182230775Sjfv}
183230775Sjfv
184230775Sjfvvoid
185230775Sjfv__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
186230775Sjfv{
187230775Sjfv    notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
188230775Sjfv}
189230775Sjfv
190230775Sjfvvoid
191230775Sjfv__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
192230775Sjfv{
193179055Sjfv    async_states_.push_back(__s);
194179055Sjfv    __s->__add_shared();
195179055Sjfv}
196179055Sjfv
197179055Sjfv// __thread_struct
198179055Sjfv
199230775Sjfv__thread_struct::__thread_struct()
200230775Sjfv    : __p_(new __thread_struct_imp)
201230775Sjfv{
202179055Sjfv}
203179055Sjfv
204179055Sjfv__thread_struct::~__thread_struct()
205179055Sjfv{
206179055Sjfv    delete __p_;
207179055Sjfv}
208230775Sjfv
209230775Sjfvvoid
210230775Sjfv__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
211230775Sjfv{
212230775Sjfv    __p_->notify_all_at_thread_exit(cv, m);
213230775Sjfv}
214230775Sjfv
215230775Sjfvvoid
216230775Sjfv__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
217230775Sjfv{
218171384Sjfv    __p_->__make_ready_at_thread_exit(__s);
219171384Sjfv}
220230775Sjfv
221230775Sjfv_LIBCPP_END_NAMESPACE_STD
222230775Sjfv