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