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