Home | History | Annotate | Download | only in v1
      1 // -*- C++ -*-
      2 //===----------------------------------------------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_THREADING_SUPPORT
     12 #define _LIBCPP_THREADING_SUPPORT
     13 
     14 #include <__config>
     15 #include <chrono>
     16 #include <errno.h>
     17 
     18 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
     19 #pragma GCC system_header
     20 #endif
     21 
     22 #if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
     23 # include <__external_threading>
     24 #elif !defined(_LIBCPP_HAS_NO_THREADS)
     25 
     26 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
     27 # include <pthread.h>
     28 # include <sched.h>
     29 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
     30 #include <windows.h>
     31 #include <process.h>
     32 #include <fibersapi.h>
     33 #endif
     34 
     35 _LIBCPP_PUSH_MACROS
     36 #include <__undef_macros>
     37 
     38 
     39 #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
     40     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
     41 #define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
     42 #else
     43 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
     44 #endif
     45 
     46 #if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
     47 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
     48 #else
     49 #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
     50 #endif
     51 
     52 _LIBCPP_BEGIN_NAMESPACE_STD
     53 
     54 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
     55 // Mutex
     56 typedef pthread_mutex_t __libcpp_mutex_t;
     57 #define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
     58 
     59 typedef pthread_mutex_t __libcpp_recursive_mutex_t;
     60 
     61 // Condition Variable
     62 typedef pthread_cond_t __libcpp_condvar_t;
     63 #define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
     64 
     65 // Execute once
     66 typedef pthread_once_t __libcpp_exec_once_flag;
     67 #define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
     68 
     69 // Thread id
     70 typedef pthread_t __libcpp_thread_id;
     71 
     72 // Thread
     73 #define _LIBCPP_NULL_THREAD 0U
     74 
     75 typedef pthread_t __libcpp_thread_t;
     76 
     77 // Thrad Local Storage
     78 typedef pthread_key_t __libcpp_tls_key;
     79 
     80 #define _LIBCPP_TLS_DESTRUCTOR_CC
     81 #else
     82 // Mutex
     83 typedef SRWLOCK __libcpp_mutex_t;
     84 #define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
     85 
     86 typedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
     87 
     88 // Condition Variable
     89 typedef CONDITION_VARIABLE __libcpp_condvar_t;
     90 #define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
     91 
     92 // Execute Once
     93 typedef INIT_ONCE __libcpp_exec_once_flag;
     94 #define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
     95 
     96 // Thread ID
     97 typedef DWORD __libcpp_thread_id;
     98 
     99 // Thread
    100 #define _LIBCPP_NULL_THREAD 0U
    101 
    102 typedef HANDLE __libcpp_thread_t;
    103 
    104 // Thread Local Storage
    105 typedef DWORD __libcpp_tls_key;
    106 
    107 #define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
    108 #endif
    109 
    110 // Mutex
    111 _LIBCPP_THREAD_ABI_VISIBILITY
    112 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
    113 
    114 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    115 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
    116 
    117 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    118 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
    119 
    120 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    121 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
    122 
    123 _LIBCPP_THREAD_ABI_VISIBILITY
    124 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
    125 
    126 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    127 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
    128 
    129 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    130 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
    131 
    132 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    133 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
    134 
    135 _LIBCPP_THREAD_ABI_VISIBILITY
    136 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
    137 
    138 // Condition variable
    139 _LIBCPP_THREAD_ABI_VISIBILITY
    140 int __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
    141 
    142 _LIBCPP_THREAD_ABI_VISIBILITY
    143 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
    144 
    145 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    146 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
    147 
    148 _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
    149 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
    150                                timespec *__ts);
    151 
    152 _LIBCPP_THREAD_ABI_VISIBILITY
    153 int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
    154 
    155 // Execute once
    156 _LIBCPP_THREAD_ABI_VISIBILITY
    157 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
    158                           void (*init_routine)(void));
    159 
    160 // Thread id
    161 _LIBCPP_THREAD_ABI_VISIBILITY
    162 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
    163 
    164 _LIBCPP_THREAD_ABI_VISIBILITY
    165 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
    166 
    167 // Thread
    168 _LIBCPP_THREAD_ABI_VISIBILITY
    169 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
    170 
    171 _LIBCPP_THREAD_ABI_VISIBILITY
    172 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
    173                            void *__arg);
    174 
    175 _LIBCPP_THREAD_ABI_VISIBILITY
    176 __libcpp_thread_id __libcpp_thread_get_current_id();
    177 
    178 _LIBCPP_THREAD_ABI_VISIBILITY
    179 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
    180 
    181 _LIBCPP_THREAD_ABI_VISIBILITY
    182 int __libcpp_thread_join(__libcpp_thread_t *__t);
    183 
    184 _LIBCPP_THREAD_ABI_VISIBILITY
    185 int __libcpp_thread_detach(__libcpp_thread_t *__t);
    186 
    187 _LIBCPP_THREAD_ABI_VISIBILITY
    188 void __libcpp_thread_yield();
    189 
    190 _LIBCPP_THREAD_ABI_VISIBILITY
    191 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns);
    192 
    193 // Thread local storage
    194 _LIBCPP_THREAD_ABI_VISIBILITY
    195 int __libcpp_tls_create(__libcpp_tls_key* __key,
    196                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
    197 
    198 _LIBCPP_THREAD_ABI_VISIBILITY
    199 void *__libcpp_tls_get(__libcpp_tls_key __key);
    200 
    201 _LIBCPP_THREAD_ABI_VISIBILITY
    202 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
    203 
    204 #if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
    205     defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
    206 
    207 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
    208 
    209 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
    210 {
    211   pthread_mutexattr_t attr;
    212   int __ec = pthread_mutexattr_init(&attr);
    213   if (__ec)
    214     return __ec;
    215   __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    216   if (__ec) {
    217     pthread_mutexattr_destroy(&attr);
    218     return __ec;
    219   }
    220   __ec = pthread_mutex_init(__m, &attr);
    221   if (__ec) {
    222     pthread_mutexattr_destroy(&attr);
    223     return __ec;
    224   }
    225   __ec = pthread_mutexattr_destroy(&attr);
    226   if (__ec) {
    227     pthread_mutex_destroy(__m);
    228     return __ec;
    229   }
    230   return 0;
    231 }
    232 
    233 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
    234 {
    235   return pthread_mutex_lock(__m);
    236 }
    237 
    238 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
    239 {
    240   return pthread_mutex_trylock(__m) == 0;
    241 }
    242 
    243 int __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
    244 {
    245   return pthread_mutex_unlock(__m);
    246 }
    247 
    248 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
    249 {
    250   return pthread_mutex_destroy(__m);
    251 }
    252 
    253 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
    254 {
    255   return pthread_mutex_lock(__m);
    256 }
    257 
    258 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
    259 {
    260   return pthread_mutex_trylock(__m) == 0;
    261 }
    262 
    263 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
    264 {
    265   return pthread_mutex_unlock(__m);
    266 }
    267 
    268 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
    269 {
    270   return pthread_mutex_destroy(__m);
    271 }
    272 
    273 // Condition Variable
    274 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
    275 {
    276   return pthread_cond_signal(__cv);
    277 }
    278 
    279 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
    280 {
    281   return pthread_cond_broadcast(__cv);
    282 }
    283 
    284 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
    285 {
    286   return pthread_cond_wait(__cv, __m);
    287 }
    288 
    289 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
    290                                timespec *__ts)
    291 {
    292   return pthread_cond_timedwait(__cv, __m, __ts);
    293 }
    294 
    295 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
    296 {
    297   return pthread_cond_destroy(__cv);
    298 }
    299 
    300 // Execute once
    301 int __libcpp_execute_once(__libcpp_exec_once_flag *flag,
    302                           void (*init_routine)(void)) {
    303   return pthread_once(flag, init_routine);
    304 }
    305 
    306 // Thread id
    307 // Returns non-zero if the thread ids are equal, otherwise 0
    308 bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
    309 {
    310   return pthread_equal(t1, t2) != 0;
    311 }
    312 
    313 // Returns non-zero if t1 < t2, otherwise 0
    314 bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
    315 {
    316   return t1 < t2;
    317 }
    318 
    319 // Thread
    320 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
    321   return *__t == 0;
    322 }
    323 
    324 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
    325                            void *__arg)
    326 {
    327   return pthread_create(__t, 0, __func, __arg);
    328 }
    329 
    330 __libcpp_thread_id __libcpp_thread_get_current_id()
    331 {
    332   return pthread_self();
    333 }
    334 
    335 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
    336 {
    337   return *__t;
    338 }
    339 
    340 int __libcpp_thread_join(__libcpp_thread_t *__t)
    341 {
    342   return pthread_join(*__t, 0);
    343 }
    344 
    345 int __libcpp_thread_detach(__libcpp_thread_t *__t)
    346 {
    347   return pthread_detach(*__t);
    348 }
    349 
    350 void __libcpp_thread_yield()
    351 {
    352   sched_yield();
    353 }
    354 
    355 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
    356 {
    357    using namespace chrono;
    358    seconds __s = duration_cast<seconds>(__ns);
    359    timespec __ts;
    360    typedef decltype(__ts.tv_sec) ts_sec;
    361    _LIBCPP_CONSTEXPR ts_sec __ts_sec_max = numeric_limits<ts_sec>::max();
    362 
    363    if (__s.count() < __ts_sec_max)
    364    {
    365      __ts.tv_sec = static_cast<ts_sec>(__s.count());
    366      __ts.tv_nsec = static_cast<decltype(__ts.tv_nsec)>((__ns - __s).count());
    367    }
    368    else
    369    {
    370      __ts.tv_sec = __ts_sec_max;
    371      __ts.tv_nsec = 999999999; // (10^9 - 1)
    372    }
    373 
    374    while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
    375 }
    376 
    377 // Thread local storage
    378 int __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
    379 {
    380   return pthread_key_create(__key, __at_exit);
    381 }
    382 
    383 void *__libcpp_tls_get(__libcpp_tls_key __key)
    384 {
    385   return pthread_getspecific(__key);
    386 }
    387 
    388 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
    389 {
    390     return pthread_setspecific(__key, __p);
    391 }
    392 
    393 #elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
    394 
    395 // Mutex
    396 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
    397 {
    398   InitializeCriticalSection(__m);
    399   return 0;
    400 }
    401 
    402 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
    403 {
    404   EnterCriticalSection(__m);
    405   return 0;
    406 }
    407 
    408 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
    409 {
    410   return TryEnterCriticalSection(__m) != 0;
    411 }
    412 
    413 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
    414 {
    415   LeaveCriticalSection(__m);
    416   return 0;
    417 }
    418 
    419 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
    420 {
    421   DeleteCriticalSection(__m);
    422   return 0;
    423 }
    424 
    425 int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
    426 {
    427   AcquireSRWLockExclusive(__m);
    428   return 0;
    429 }
    430 
    431 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
    432 {
    433   return TryAcquireSRWLockExclusive(__m) != 0;
    434 }
    435 
    436 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
    437 {
    438   ReleaseSRWLockExclusive(__m);
    439   return 0;
    440 }
    441 
    442 int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
    443 {
    444   static_cast<void>(__m);
    445   return 0;
    446 }
    447 
    448 // Condition Variable
    449 int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
    450 {
    451   WakeConditionVariable(__cv);
    452   return 0;
    453 }
    454 
    455 int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
    456 {
    457   WakeAllConditionVariable(__cv);
    458   return 0;
    459 }
    460 
    461 int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
    462 {
    463   SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
    464   return 0;
    465 }
    466 
    467 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
    468                                timespec *__ts)
    469 {
    470   using namespace _VSTD::chrono;
    471 
    472   auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
    473   auto abstime =
    474       system_clock::time_point(duration_cast<system_clock::duration>(duration));
    475   auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
    476 
    477   if (!SleepConditionVariableSRW(__cv, __m,
    478                                  timeout_ms.count() > 0 ? timeout_ms.count()
    479                                                         : 0,
    480                                  0))
    481     {
    482       auto __ec = GetLastError();
    483       return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
    484     }
    485   return 0;
    486 }
    487 
    488 int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
    489 {
    490   static_cast<void>(__cv);
    491   return 0;
    492 }
    493 
    494 // Execute Once
    495 static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
    496 __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
    497                                       PVOID *__context)
    498 {
    499   static_cast<void>(__init_once);
    500   static_cast<void>(__context);
    501 
    502   void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
    503   init_routine();
    504   return TRUE;
    505 }
    506 
    507 int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
    508                           void (*__init_routine)(void))
    509 {
    510   if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
    511                            reinterpret_cast<void *>(__init_routine), NULL))
    512     return GetLastError();
    513   return 0;
    514 }
    515 
    516 // Thread ID
    517 bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
    518                               __libcpp_thread_id __rhs)
    519 {
    520   return __lhs == __rhs;
    521 }
    522 
    523 bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
    524 {
    525   return __lhs < __rhs;
    526 }
    527 
    528 // Thread
    529 struct __libcpp_beginthreadex_thunk_data
    530 {
    531   void *(*__func)(void *);
    532   void *__arg;
    533 };
    534 
    535 static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
    536 __libcpp_beginthreadex_thunk(void *__raw_data)
    537 {
    538   auto *__data =
    539       static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
    540   auto *__func = __data->__func;
    541   void *__arg = __data->__arg;
    542   delete __data;
    543   return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
    544 }
    545 
    546 bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
    547   return *__t == 0;
    548 }
    549 
    550 int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
    551                            void *__arg)
    552 {
    553   auto *__data = new __libcpp_beginthreadex_thunk_data;
    554   __data->__func = __func;
    555   __data->__arg = __arg;
    556 
    557   *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
    558                                                  __libcpp_beginthreadex_thunk,
    559                                                  __data, 0, nullptr));
    560 
    561   if (*__t)
    562     return 0;
    563   return GetLastError();
    564 }
    565 
    566 __libcpp_thread_id __libcpp_thread_get_current_id()
    567 {
    568   return GetCurrentThreadId();
    569 }
    570 
    571 __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
    572 {
    573   return GetThreadId(*__t);
    574 }
    575 
    576 int __libcpp_thread_join(__libcpp_thread_t *__t)
    577 {
    578   if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
    579     return GetLastError();
    580   if (!CloseHandle(*__t))
    581     return GetLastError();
    582   return 0;
    583 }
    584 
    585 int __libcpp_thread_detach(__libcpp_thread_t *__t)
    586 {
    587   if (!CloseHandle(*__t))
    588     return GetLastError();
    589   return 0;
    590 }
    591 
    592 void __libcpp_thread_yield()
    593 {
    594   SwitchToThread();
    595 }
    596 
    597 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
    598 {
    599   using namespace chrono;
    600   // round-up to the nearest milisecond
    601   milliseconds __ms =
    602       duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
    603   // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
    604   Sleep(__ms.count());
    605 }
    606 
    607 // Thread Local Storage
    608 int __libcpp_tls_create(__libcpp_tls_key* __key,
    609                         void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
    610 {
    611   *__key = FlsAlloc(__at_exit);
    612   if (*__key == FLS_OUT_OF_INDEXES)
    613     return GetLastError();
    614   return 0;
    615 }
    616 
    617 void *__libcpp_tls_get(__libcpp_tls_key __key)
    618 {
    619   return FlsGetValue(__key);
    620 }
    621 
    622 int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
    623 {
    624   if (!FlsSetValue(__key, __p))
    625     return GetLastError();
    626   return 0;
    627 }
    628 
    629 #endif // _LIBCPP_HAS_THREAD_API_PTHREAD
    630 
    631 #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
    632 
    633 _LIBCPP_END_NAMESPACE_STD
    634 
    635 _LIBCPP_POP_MACROS
    636 
    637 #endif // !_LIBCPP_HAS_NO_THREADS
    638 
    639 #endif // _LIBCPP_THREADING_SUPPORT
    640