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__) && !defined(_AIX)
     18 #include <sys/sysctl.h>
     19 #endif // !__sun__ && !__linux__ && !_AIX
     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 #   if defined(_MSC_VER) && ! defined(__clang__)
     93         _LIBCPP_WARNING("hardware_concurrency not yet implemented")
     94 #   else
     95 #       warning hardware_concurrency not yet implemented
     96 #   endif
     97     return 0;  // Means not computable [thread.thread.static]
     98 #endif  // defined(CTL_HW) && defined(HW_NCPU)
     99 }
    100 
    101 namespace this_thread
    102 {
    103 
    104 void
    105 sleep_for(const chrono::nanoseconds& ns)
    106 {
    107     using namespace chrono;
    108     if (ns > nanoseconds::zero())
    109     {
    110         seconds s = duration_cast<seconds>(ns);
    111         timespec ts;
    112         typedef decltype(ts.tv_sec) ts_sec;
    113         _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
    114         if (s.count() < ts_sec_max)
    115         {
    116             ts.tv_sec = static_cast<ts_sec>(s.count());
    117             ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count());
    118         }
    119         else
    120         {
    121             ts.tv_sec = ts_sec_max;
    122             ts.tv_nsec = giga::num - 1;
    123         }
    124         nanosleep(&ts, 0);
    125     }
    126 }
    127 
    128 }  // this_thread
    129 
    130 __thread_specific_ptr<__thread_struct>&
    131 __thread_local_data()
    132 {
    133     static __thread_specific_ptr<__thread_struct> __p;
    134     return __p;
    135 }
    136 
    137 // __thread_struct_imp
    138 
    139 template <class T>
    140 class _LIBCPP_HIDDEN __hidden_allocator
    141 {
    142 public:
    143     typedef T  value_type;
    144 
    145     T* allocate(size_t __n)
    146         {return static_cast<T*>(::operator new(__n * sizeof(T)));}
    147     void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));}
    148 
    149     size_t max_size() const {return size_t(~0) / sizeof(T);}
    150 };
    151 
    152 class _LIBCPP_HIDDEN __thread_struct_imp
    153 {
    154     typedef vector<__assoc_sub_state*,
    155                           __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
    156     typedef vector<pair<condition_variable*, mutex*>,
    157                __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
    158 
    159     _AsyncStates async_states_;
    160     _Notify notify_;
    161 
    162     __thread_struct_imp(const __thread_struct_imp&);
    163     __thread_struct_imp& operator=(const __thread_struct_imp&);
    164 public:
    165     __thread_struct_imp() {}
    166     ~__thread_struct_imp();
    167 
    168     void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
    169     void __make_ready_at_thread_exit(__assoc_sub_state* __s);
    170 };
    171 
    172 __thread_struct_imp::~__thread_struct_imp()
    173 {
    174     for (_Notify::iterator i = notify_.begin(), e = notify_.end();
    175             i != e; ++i)
    176     {
    177         i->second->unlock();
    178         i->first->notify_all();
    179     }
    180     for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
    181             i != e; ++i)
    182     {
    183         (*i)->__make_ready();
    184         (*i)->__release_shared();
    185     }
    186 }
    187 
    188 void
    189 __thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
    190 {
    191     notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
    192 }
    193 
    194 void
    195 __thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
    196 {
    197     async_states_.push_back(__s);
    198     __s->__add_shared();
    199 }
    200 
    201 // __thread_struct
    202 
    203 __thread_struct::__thread_struct()
    204     : __p_(new __thread_struct_imp)
    205 {
    206 }
    207 
    208 __thread_struct::~__thread_struct()
    209 {
    210     delete __p_;
    211 }
    212 
    213 void
    214 __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
    215 {
    216     __p_->notify_all_at_thread_exit(cv, m);
    217 }
    218 
    219 void
    220 __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
    221 {
    222     __p_->__make_ready_at_thread_exit(__s);
    223 }
    224 
    225 _LIBCPP_END_NAMESPACE_STD
    226