1c7e4239fSAsiri Rathnayake// -*- C++ -*-
2c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===//
3c7e4239fSAsiri Rathnayake//
4c7e4239fSAsiri Rathnayake//                     The LLVM Compiler Infrastructure
5c7e4239fSAsiri Rathnayake//
6c7e4239fSAsiri Rathnayake// This file is dual licensed under the MIT and the University of Illinois Open
7c7e4239fSAsiri Rathnayake// Source Licenses. See LICENSE.TXT for details.
8c7e4239fSAsiri Rathnayake//
9c7e4239fSAsiri Rathnayake//===----------------------------------------------------------------------===//
10c7e4239fSAsiri Rathnayake
11c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_THREADING_SUPPORT
12c7e4239fSAsiri Rathnayake#define _LIBCPP_THREADING_SUPPORT
13c7e4239fSAsiri Rathnayake
14c7e4239fSAsiri Rathnayake#include <__config>
15c7e4239fSAsiri Rathnayake
16c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
17c7e4239fSAsiri Rathnayake#pragma GCC system_header
18c7e4239fSAsiri Rathnayake#endif
19c7e4239fSAsiri Rathnayake
2000f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
213cf2f7bcSAsiri Rathnayake# include <__external_threading>
2200f6beaeSEric Fiselier#elif !defined(_LIBCPP_HAS_NO_THREADS)
23790e10f6SSaleem Abdulrasool
2400f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
25c7e4239fSAsiri Rathnayake# include <pthread.h>
26c7e4239fSAsiri Rathnayake# include <sched.h>
276d7d0becSSaleem Abdulrasool#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
28f9e7bf3aSEric Fiselier#include <assert.h>
296d7d0becSSaleem Abdulrasool#include <Windows.h>
306d7d0becSSaleem Abdulrasool#include <process.h>
316d7d0becSSaleem Abdulrasool#include <fibersapi.h>
326d7d0becSSaleem Abdulrasool
336d7d0becSSaleem Abdulrasool#include <chrono>
34790e10f6SSaleem Abdulrasool#endif
35c7e4239fSAsiri Rathnayake
3600f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
3700f6beaeSEric Fiselier    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
388c2bf45dSAsiri Rathnayake#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
398c2bf45dSAsiri Rathnayake#else
408c2bf45dSAsiri Rathnayake#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
418c2bf45dSAsiri Rathnayake#endif
428c2bf45dSAsiri Rathnayake
43*83dca5c3SDimitry Andric#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
44*83dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
45*83dca5c3SDimitry Andric#else
46*83dca5c3SDimitry Andric#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
47*83dca5c3SDimitry Andric#endif
48*83dca5c3SDimitry Andric
49c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD
50c7e4239fSAsiri Rathnayake
5100f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
52c7e4239fSAsiri Rathnayake// Mutex
53c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t;
548c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
55c7e4239fSAsiri Rathnayake
5658a0dceeSSaleem Abdulrasooltypedef pthread_mutex_t __libcpp_recursive_mutex_t;
5758a0dceeSSaleem Abdulrasool
58790e10f6SSaleem Abdulrasool// Condition Variable
59790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t;
60790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
61790e10f6SSaleem Abdulrasool
62205d7d3fSAsiri Rathnayake// Execute once
63205d7d3fSAsiri Rathnayaketypedef pthread_once_t __libcpp_exec_once_flag;
64205d7d3fSAsiri Rathnayake#define _LIBCPP_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT
65205d7d3fSAsiri Rathnayake
66205d7d3fSAsiri Rathnayake// Thread id
67790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_id;
68790e10f6SSaleem Abdulrasool
69790e10f6SSaleem Abdulrasool// Thread
70af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
71af762e91SAsiri Rathnayake
72790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t;
73790e10f6SSaleem Abdulrasool
74790e10f6SSaleem Abdulrasool// Thrad Local Storage
75790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key;
766d7d0becSSaleem Abdulrasool
776d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC
786d7d0becSSaleem Abdulrasool#else
796d7d0becSSaleem Abdulrasool// Mutex
806d7d0becSSaleem Abdulrasooltypedef SRWLOCK __libcpp_mutex_t;
816d7d0becSSaleem Abdulrasool#define _LIBCPP_MUTEX_INITIALIZER SRWLOCK_INIT
826d7d0becSSaleem Abdulrasool
836d7d0becSSaleem Abdulrasooltypedef CRITICAL_SECTION __libcpp_recursive_mutex_t;
846d7d0becSSaleem Abdulrasool
856d7d0becSSaleem Abdulrasool// Condition Variable
866d7d0becSSaleem Abdulrasooltypedef CONDITION_VARIABLE __libcpp_condvar_t;
876d7d0becSSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER CONDITION_VARIABLE_INIT
886d7d0becSSaleem Abdulrasool
896d7d0becSSaleem Abdulrasool// Execute Once
906d7d0becSSaleem Abdulrasooltypedef INIT_ONCE __libcpp_exec_once_flag;
916d7d0becSSaleem Abdulrasool#define _LIBCPP_EXEC_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
926d7d0becSSaleem Abdulrasool
936d7d0becSSaleem Abdulrasool// Thread ID
946d7d0becSSaleem Abdulrasooltypedef DWORD __libcpp_thread_id;
956d7d0becSSaleem Abdulrasool
966d7d0becSSaleem Abdulrasool// Thread
97af762e91SAsiri Rathnayake#define _LIBCPP_NULL_THREAD 0U
98af762e91SAsiri Rathnayake
996d7d0becSSaleem Abdulrasooltypedef HANDLE __libcpp_thread_t;
1006d7d0becSSaleem Abdulrasool
1016d7d0becSSaleem Abdulrasool// Thread Local Storage
1026d7d0becSSaleem Abdulrasooltypedef DWORD __libcpp_tls_key;
1036d7d0becSSaleem Abdulrasool
1046d7d0becSSaleem Abdulrasool#define _LIBCPP_TLS_DESTRUCTOR_CC WINAPI
105790e10f6SSaleem Abdulrasool#endif
106790e10f6SSaleem Abdulrasool
107790e10f6SSaleem Abdulrasool// Mutex
1088c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
10958a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
11058a0dceeSSaleem Abdulrasool
111*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
11258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
11358a0dceeSSaleem Abdulrasool
114*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
11508e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
11658a0dceeSSaleem Abdulrasool
117*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
11858a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
11958a0dceeSSaleem Abdulrasool
12058a0dceeSSaleem Abdulrasool_LIBCPP_THREAD_ABI_VISIBILITY
12158a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
122790e10f6SSaleem Abdulrasool
123*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1248c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
125790e10f6SSaleem Abdulrasool
126*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
12708e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
128790e10f6SSaleem Abdulrasool
129*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1308c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
131790e10f6SSaleem Abdulrasool
1328c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1338c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
1348c2bf45dSAsiri Rathnayake
1358c2bf45dSAsiri Rathnayake// Condition variable
1368c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1378c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
138790e10f6SSaleem Abdulrasool
1398c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1408c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
141790e10f6SSaleem Abdulrasool
142*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
1438c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
144790e10f6SSaleem Abdulrasool
145*83dca5c3SDimitry Andric_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
146790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
147790e10f6SSaleem Abdulrasool                               timespec *__ts);
148790e10f6SSaleem Abdulrasool
1498c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1508c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
1518c2bf45dSAsiri Rathnayake
152205d7d3fSAsiri Rathnayake// Execute once
153205d7d3fSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
154205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
155205d7d3fSAsiri Rathnayake                          void (*init_routine)(void));
156205d7d3fSAsiri Rathnayake
157205d7d3fSAsiri Rathnayake// Thread id
1588c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1598c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
160790e10f6SSaleem Abdulrasool
1618c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1628c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
1638c2bf45dSAsiri Rathnayake
1648c2bf45dSAsiri Rathnayake// Thread
1658c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
166af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t);
167af762e91SAsiri Rathnayake
168af762e91SAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
169790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
170790e10f6SSaleem Abdulrasool                           void *__arg);
171790e10f6SSaleem Abdulrasool
1728c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1738c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id();
174790e10f6SSaleem Abdulrasool
1758c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1768c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
177790e10f6SSaleem Abdulrasool
1788c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1798c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t);
180790e10f6SSaleem Abdulrasool
1818c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1828c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t);
183790e10f6SSaleem Abdulrasool
1848c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1858c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield();
1868c2bf45dSAsiri Rathnayake
1878c2bf45dSAsiri Rathnayake// Thread local storage
1888c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1896d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key,
1906d7d0becSSaleem Abdulrasool                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*));
191790e10f6SSaleem Abdulrasool
1928c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1938c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key);
194790e10f6SSaleem Abdulrasool
1958c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
196205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
1978c2bf45dSAsiri Rathnayake
19800f6beaeSEric Fiselier#if !defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \
19900f6beaeSEric Fiselier    defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)
20000f6beaeSEric Fiselier
20100f6beaeSEric Fiselier#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
2028c2bf45dSAsiri Rathnayake
20358a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
204c7e4239fSAsiri Rathnayake{
205c7e4239fSAsiri Rathnayake  pthread_mutexattr_t attr;
206c7e4239fSAsiri Rathnayake  int __ec = pthread_mutexattr_init(&attr);
207c7e4239fSAsiri Rathnayake  if (__ec)
208790e10f6SSaleem Abdulrasool    return __ec;
209790e10f6SSaleem Abdulrasool  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
210790e10f6SSaleem Abdulrasool  if (__ec) {
211c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
212c7e4239fSAsiri Rathnayake    return __ec;
213c7e4239fSAsiri Rathnayake  }
214c7e4239fSAsiri Rathnayake  __ec = pthread_mutex_init(__m, &attr);
215790e10f6SSaleem Abdulrasool  if (__ec) {
216c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
217c7e4239fSAsiri Rathnayake    return __ec;
218c7e4239fSAsiri Rathnayake  }
219c7e4239fSAsiri Rathnayake  __ec = pthread_mutexattr_destroy(&attr);
220790e10f6SSaleem Abdulrasool  if (__ec) {
221c7e4239fSAsiri Rathnayake    pthread_mutex_destroy(__m);
222c7e4239fSAsiri Rathnayake    return __ec;
223c7e4239fSAsiri Rathnayake  }
224c7e4239fSAsiri Rathnayake  return 0;
225c7e4239fSAsiri Rathnayake}
226c7e4239fSAsiri Rathnayake
22758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
22858a0dceeSSaleem Abdulrasool{
22958a0dceeSSaleem Abdulrasool  return pthread_mutex_lock(__m);
23058a0dceeSSaleem Abdulrasool}
23158a0dceeSSaleem Abdulrasool
23208e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
23358a0dceeSSaleem Abdulrasool{
23408e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
23558a0dceeSSaleem Abdulrasool}
23658a0dceeSSaleem Abdulrasool
23758a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_mutex_t *__m)
23858a0dceeSSaleem Abdulrasool{
23958a0dceeSSaleem Abdulrasool  return pthread_mutex_unlock(__m);
24058a0dceeSSaleem Abdulrasool}
24158a0dceeSSaleem Abdulrasool
24258a0dceeSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
24358a0dceeSSaleem Abdulrasool{
24458a0dceeSSaleem Abdulrasool  return pthread_mutex_destroy(__m);
24558a0dceeSSaleem Abdulrasool}
24658a0dceeSSaleem Abdulrasool
247c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
248c7e4239fSAsiri Rathnayake{
249c7e4239fSAsiri Rathnayake  return pthread_mutex_lock(__m);
250c7e4239fSAsiri Rathnayake}
251c7e4239fSAsiri Rathnayake
25208e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
253c7e4239fSAsiri Rathnayake{
25408e1477cSEric Fiselier  return pthread_mutex_trylock(__m) == 0;
255c7e4239fSAsiri Rathnayake}
256c7e4239fSAsiri Rathnayake
257c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
258c7e4239fSAsiri Rathnayake{
259c7e4239fSAsiri Rathnayake  return pthread_mutex_unlock(__m);
260c7e4239fSAsiri Rathnayake}
261c7e4239fSAsiri Rathnayake
262c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
263c7e4239fSAsiri Rathnayake{
264c7e4239fSAsiri Rathnayake  return pthread_mutex_destroy(__m);
265c7e4239fSAsiri Rathnayake}
266c7e4239fSAsiri Rathnayake
267790e10f6SSaleem Abdulrasool// Condition Variable
268c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
269c7e4239fSAsiri Rathnayake{
270c7e4239fSAsiri Rathnayake  return pthread_cond_signal(__cv);
271c7e4239fSAsiri Rathnayake}
272c7e4239fSAsiri Rathnayake
273c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
274c7e4239fSAsiri Rathnayake{
275c7e4239fSAsiri Rathnayake  return pthread_cond_broadcast(__cv);
276c7e4239fSAsiri Rathnayake}
277c7e4239fSAsiri Rathnayake
278c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
279c7e4239fSAsiri Rathnayake{
280c7e4239fSAsiri Rathnayake  return pthread_cond_wait(__cv, __m);
281c7e4239fSAsiri Rathnayake}
282c7e4239fSAsiri Rathnayake
283790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
284790e10f6SSaleem Abdulrasool                               timespec *__ts)
285c7e4239fSAsiri Rathnayake{
286c7e4239fSAsiri Rathnayake  return pthread_cond_timedwait(__cv, __m, __ts);
287c7e4239fSAsiri Rathnayake}
288c7e4239fSAsiri Rathnayake
289c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
290c7e4239fSAsiri Rathnayake{
291c7e4239fSAsiri Rathnayake  return pthread_cond_destroy(__cv);
292c7e4239fSAsiri Rathnayake}
293c7e4239fSAsiri Rathnayake
294205d7d3fSAsiri Rathnayake// Execute once
295205d7d3fSAsiri Rathnayakeint __libcpp_execute_once(__libcpp_exec_once_flag *flag,
296205d7d3fSAsiri Rathnayake                          void (*init_routine)(void)) {
297205d7d3fSAsiri Rathnayake  return pthread_once(flag, init_routine);
298205d7d3fSAsiri Rathnayake}
299205d7d3fSAsiri Rathnayake
300205d7d3fSAsiri Rathnayake// Thread id
301c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0
302c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
303c7e4239fSAsiri Rathnayake{
304c7e4239fSAsiri Rathnayake  return pthread_equal(t1, t2) != 0;
305c7e4239fSAsiri Rathnayake}
306c7e4239fSAsiri Rathnayake
307c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0
308c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
309c7e4239fSAsiri Rathnayake{
310c7e4239fSAsiri Rathnayake  return t1 < t2;
311c7e4239fSAsiri Rathnayake}
312c7e4239fSAsiri Rathnayake
313c7e4239fSAsiri Rathnayake// Thread
314af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
315af762e91SAsiri Rathnayake  return *__t == 0;
316af762e91SAsiri Rathnayake}
317af762e91SAsiri Rathnayake
318790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
319790e10f6SSaleem Abdulrasool                           void *__arg)
320c7e4239fSAsiri Rathnayake{
321c7e4239fSAsiri Rathnayake  return pthread_create(__t, 0, __func, __arg);
322c7e4239fSAsiri Rathnayake}
323c7e4239fSAsiri Rathnayake
324c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id()
325c7e4239fSAsiri Rathnayake{
326c7e4239fSAsiri Rathnayake  return pthread_self();
327c7e4239fSAsiri Rathnayake}
328c7e4239fSAsiri Rathnayake
329c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
330c7e4239fSAsiri Rathnayake{
331c7e4239fSAsiri Rathnayake  return *__t;
332c7e4239fSAsiri Rathnayake}
333c7e4239fSAsiri Rathnayake
334c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t)
335c7e4239fSAsiri Rathnayake{
336c7e4239fSAsiri Rathnayake  return pthread_join(*__t, 0);
337c7e4239fSAsiri Rathnayake}
338c7e4239fSAsiri Rathnayake
339c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t)
340c7e4239fSAsiri Rathnayake{
341c7e4239fSAsiri Rathnayake  return pthread_detach(*__t);
342c7e4239fSAsiri Rathnayake}
343c7e4239fSAsiri Rathnayake
344c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield()
345c7e4239fSAsiri Rathnayake{
346c7e4239fSAsiri Rathnayake  sched_yield();
347c7e4239fSAsiri Rathnayake}
348c7e4239fSAsiri Rathnayake
349c7e4239fSAsiri Rathnayake// Thread local storage
3508c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
351c7e4239fSAsiri Rathnayake{
352c7e4239fSAsiri Rathnayake  return pthread_key_create(__key, __at_exit);
353c7e4239fSAsiri Rathnayake}
354c7e4239fSAsiri Rathnayake
3558c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key)
356c7e4239fSAsiri Rathnayake{
357c7e4239fSAsiri Rathnayake  return pthread_getspecific(__key);
358c7e4239fSAsiri Rathnayake}
359c7e4239fSAsiri Rathnayake
360205d7d3fSAsiri Rathnayakeint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
361c7e4239fSAsiri Rathnayake{
362205d7d3fSAsiri Rathnayake    return pthread_setspecific(__key, __p);
363c7e4239fSAsiri Rathnayake}
364c7e4239fSAsiri Rathnayake
3656d7d0becSSaleem Abdulrasool#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
3666d7d0becSSaleem Abdulrasool
3676d7d0becSSaleem Abdulrasool// Mutex
3686d7d0becSSaleem Abdulrasoolint __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
3696d7d0becSSaleem Abdulrasool{
3706d7d0becSSaleem Abdulrasool  InitializeCriticalSection(__m);
3716d7d0becSSaleem Abdulrasool  return 0;
3726d7d0becSSaleem Abdulrasool}
3736d7d0becSSaleem Abdulrasool
3746d7d0becSSaleem Abdulrasoolint __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
3756d7d0becSSaleem Abdulrasool{
3766d7d0becSSaleem Abdulrasool  EnterCriticalSection(__m);
3776d7d0becSSaleem Abdulrasool  return 0;
3786d7d0becSSaleem Abdulrasool}
3796d7d0becSSaleem Abdulrasool
38008e1477cSEric Fiselierbool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
3816d7d0becSSaleem Abdulrasool{
38208e1477cSEric Fiselier  return TryEnterCriticalSection(__m) != 0;
3836d7d0becSSaleem Abdulrasool}
3846d7d0becSSaleem Abdulrasool
3856d7d0becSSaleem Abdulrasoolint __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
3866d7d0becSSaleem Abdulrasool{
3876d7d0becSSaleem Abdulrasool  LeaveCriticalSection(__m);
3886d7d0becSSaleem Abdulrasool  return 0;
3896d7d0becSSaleem Abdulrasool}
3906d7d0becSSaleem Abdulrasool
3916d7d0becSSaleem Abdulrasoolint __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
3926d7d0becSSaleem Abdulrasool{
3934ec493b2SSaleem Abdulrasool  DeleteCriticalSection(__m);
3946d7d0becSSaleem Abdulrasool  return 0;
3956d7d0becSSaleem Abdulrasool}
3966d7d0becSSaleem Abdulrasool
3976d7d0becSSaleem Abdulrasoolint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
3986d7d0becSSaleem Abdulrasool{
3996d7d0becSSaleem Abdulrasool  AcquireSRWLockExclusive(__m);
4006d7d0becSSaleem Abdulrasool  return 0;
4016d7d0becSSaleem Abdulrasool}
4026d7d0becSSaleem Abdulrasool
40308e1477cSEric Fiselierbool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
4046d7d0becSSaleem Abdulrasool{
40508e1477cSEric Fiselier  return TryAcquireSRWLockExclusive(__m) != 0;
4066d7d0becSSaleem Abdulrasool}
4076d7d0becSSaleem Abdulrasool
4086d7d0becSSaleem Abdulrasoolint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
4096d7d0becSSaleem Abdulrasool{
4106d7d0becSSaleem Abdulrasool  ReleaseSRWLockExclusive(__m);
4116d7d0becSSaleem Abdulrasool  return 0;
4126d7d0becSSaleem Abdulrasool}
4136d7d0becSSaleem Abdulrasool
4146d7d0becSSaleem Abdulrasoolint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
4156d7d0becSSaleem Abdulrasool{
4166d7d0becSSaleem Abdulrasool  static_cast<void>(__m);
4176d7d0becSSaleem Abdulrasool  return 0;
4186d7d0becSSaleem Abdulrasool}
4196d7d0becSSaleem Abdulrasool
4206d7d0becSSaleem Abdulrasool// Condition Variable
4216d7d0becSSaleem Abdulrasoolint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
4226d7d0becSSaleem Abdulrasool{
4236d7d0becSSaleem Abdulrasool  WakeConditionVariable(__cv);
4246d7d0becSSaleem Abdulrasool  return 0;
4256d7d0becSSaleem Abdulrasool}
4266d7d0becSSaleem Abdulrasool
4276d7d0becSSaleem Abdulrasoolint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
4286d7d0becSSaleem Abdulrasool{
4296d7d0becSSaleem Abdulrasool  WakeAllConditionVariable(__cv);
4306d7d0becSSaleem Abdulrasool  return 0;
4316d7d0becSSaleem Abdulrasool}
4326d7d0becSSaleem Abdulrasool
4336d7d0becSSaleem Abdulrasoolint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
4346d7d0becSSaleem Abdulrasool{
4356d7d0becSSaleem Abdulrasool  SleepConditionVariableSRW(__cv, __m, INFINITE, 0);
4366d7d0becSSaleem Abdulrasool  return 0;
4376d7d0becSSaleem Abdulrasool}
4386d7d0becSSaleem Abdulrasool
4396d7d0becSSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
4406d7d0becSSaleem Abdulrasool                               timespec *__ts)
4416d7d0becSSaleem Abdulrasool{
4426d7d0becSSaleem Abdulrasool  using namespace _VSTD::chrono;
4436d7d0becSSaleem Abdulrasool
4446d7d0becSSaleem Abdulrasool  auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
4456d7d0becSSaleem Abdulrasool  auto abstime =
4466d7d0becSSaleem Abdulrasool      system_clock::time_point(duration_cast<system_clock::duration>(duration));
4476d7d0becSSaleem Abdulrasool  auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
4486d7d0becSSaleem Abdulrasool
4496d7d0becSSaleem Abdulrasool  if (!SleepConditionVariableSRW(__cv, __m,
4506d7d0becSSaleem Abdulrasool                                 timeout_ms.count() > 0 ? timeout_ms.count()
4516d7d0becSSaleem Abdulrasool                                                        : 0,
4526d7d0becSSaleem Abdulrasool                                 0))
4536d7d0becSSaleem Abdulrasool    return GetLastError();
4546d7d0becSSaleem Abdulrasool  return 0;
4556d7d0becSSaleem Abdulrasool}
4566d7d0becSSaleem Abdulrasool
4576d7d0becSSaleem Abdulrasoolint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
4586d7d0becSSaleem Abdulrasool{
4596d7d0becSSaleem Abdulrasool  static_cast<void>(__cv);
4606d7d0becSSaleem Abdulrasool  return 0;
4616d7d0becSSaleem Abdulrasool}
4626d7d0becSSaleem Abdulrasool
4636d7d0becSSaleem Abdulrasool// Execute Once
4646d7d0becSSaleem Abdulrasoolstatic inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK
4656d7d0becSSaleem Abdulrasool__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
4666d7d0becSSaleem Abdulrasool                                      PVOID *__context)
4676d7d0becSSaleem Abdulrasool{
4686d7d0becSSaleem Abdulrasool  static_cast<void>(__init_once);
4696d7d0becSSaleem Abdulrasool  static_cast<void>(__context);
4706d7d0becSSaleem Abdulrasool
4716d7d0becSSaleem Abdulrasool  void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
4726d7d0becSSaleem Abdulrasool  init_routine();
4736d7d0becSSaleem Abdulrasool  return TRUE;
4746d7d0becSSaleem Abdulrasool}
4756d7d0becSSaleem Abdulrasool
4766d7d0becSSaleem Abdulrasoolint __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
4776d7d0becSSaleem Abdulrasool                          void (*__init_routine)(void))
4786d7d0becSSaleem Abdulrasool{
4796d7d0becSSaleem Abdulrasool  if (!InitOnceExecuteOnce(__flag, __libcpp_init_once_execute_once_thunk,
4806d7d0becSSaleem Abdulrasool                           reinterpret_cast<void *>(__init_routine), NULL))
4816d7d0becSSaleem Abdulrasool    return GetLastError();
4826d7d0becSSaleem Abdulrasool  return 0;
4836d7d0becSSaleem Abdulrasool}
4846d7d0becSSaleem Abdulrasool
4856d7d0becSSaleem Abdulrasool// Thread ID
4866d7d0becSSaleem Abdulrasoolbool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
4876d7d0becSSaleem Abdulrasool                              __libcpp_thread_id __rhs)
4886d7d0becSSaleem Abdulrasool{
4896d7d0becSSaleem Abdulrasool  return __lhs == __rhs;
4906d7d0becSSaleem Abdulrasool}
4916d7d0becSSaleem Abdulrasool
4926d7d0becSSaleem Abdulrasoolbool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
4936d7d0becSSaleem Abdulrasool{
4946d7d0becSSaleem Abdulrasool  return __lhs < __rhs;
4956d7d0becSSaleem Abdulrasool}
4966d7d0becSSaleem Abdulrasool
4976d7d0becSSaleem Abdulrasool// Thread
4986d7d0becSSaleem Abdulrasoolstruct __libcpp_beginthreadex_thunk_data
4996d7d0becSSaleem Abdulrasool{
5006d7d0becSSaleem Abdulrasool  void *(*__func)(void *);
5016d7d0becSSaleem Abdulrasool  void *__arg;
5026d7d0becSSaleem Abdulrasool};
5036d7d0becSSaleem Abdulrasool
504d75a9d25SEric Fiselierstatic inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI
5056f38b6abSEric Fiselier__libcpp_beginthreadex_thunk(void *__raw_data)
5066d7d0becSSaleem Abdulrasool{
5076f38b6abSEric Fiselier  auto *__data =
5086f38b6abSEric Fiselier      static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
5096f38b6abSEric Fiselier  auto *__func = __data->__func;
5106f38b6abSEric Fiselier  void *__arg = __data->__arg;
5116f38b6abSEric Fiselier  delete __data;
512d75a9d25SEric Fiselier  return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
5136d7d0becSSaleem Abdulrasool}
5146d7d0becSSaleem Abdulrasool
515af762e91SAsiri Rathnayakebool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
516af762e91SAsiri Rathnayake  return *__t == 0;
517af762e91SAsiri Rathnayake}
518af762e91SAsiri Rathnayake
5196d7d0becSSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
5206d7d0becSSaleem Abdulrasool                           void *__arg)
5216d7d0becSSaleem Abdulrasool{
5226f38b6abSEric Fiselier  auto *__data = new __libcpp_beginthreadex_thunk_data;
5236f38b6abSEric Fiselier  __data->__func = __func;
5246f38b6abSEric Fiselier  __data->__arg = __arg;
5256d7d0becSSaleem Abdulrasool
526d75a9d25SEric Fiselier  *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
527d75a9d25SEric Fiselier                                                 __libcpp_beginthreadex_thunk,
528d75a9d25SEric Fiselier                                                 __data, 0, nullptr));
529d75a9d25SEric Fiselier
5306d7d0becSSaleem Abdulrasool  if (*__t)
5316d7d0becSSaleem Abdulrasool    return 0;
5326d7d0becSSaleem Abdulrasool  return GetLastError();
5336d7d0becSSaleem Abdulrasool}
5346d7d0becSSaleem Abdulrasool
5356d7d0becSSaleem Abdulrasool__libcpp_thread_id __libcpp_thread_get_current_id()
5366d7d0becSSaleem Abdulrasool{
5376d7d0becSSaleem Abdulrasool  return GetCurrentThreadId();
5386d7d0becSSaleem Abdulrasool}
5396d7d0becSSaleem Abdulrasool
5406d7d0becSSaleem Abdulrasool__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
5416d7d0becSSaleem Abdulrasool{
5426d7d0becSSaleem Abdulrasool  return GetThreadId(*__t);
5436d7d0becSSaleem Abdulrasool}
5446d7d0becSSaleem Abdulrasool
5456d7d0becSSaleem Abdulrasoolint __libcpp_thread_join(__libcpp_thread_t *__t)
5466d7d0becSSaleem Abdulrasool{
5476d7d0becSSaleem Abdulrasool  if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
5486d7d0becSSaleem Abdulrasool    return GetLastError();
5496d7d0becSSaleem Abdulrasool  if (!CloseHandle(*__t))
5506d7d0becSSaleem Abdulrasool    return GetLastError();
5516d7d0becSSaleem Abdulrasool  return 0;
5526d7d0becSSaleem Abdulrasool}
5536d7d0becSSaleem Abdulrasool
5546d7d0becSSaleem Abdulrasoolint __libcpp_thread_detach(__libcpp_thread_t *__t)
5556d7d0becSSaleem Abdulrasool{
5566d7d0becSSaleem Abdulrasool  if (!CloseHandle(*__t))
5576d7d0becSSaleem Abdulrasool    return GetLastError();
5586d7d0becSSaleem Abdulrasool  return 0;
5596d7d0becSSaleem Abdulrasool}
5606d7d0becSSaleem Abdulrasool
5616d7d0becSSaleem Abdulrasoolvoid __libcpp_thread_yield()
5626d7d0becSSaleem Abdulrasool{
5636d7d0becSSaleem Abdulrasool  SwitchToThread();
5646d7d0becSSaleem Abdulrasool}
5656d7d0becSSaleem Abdulrasool
5666d7d0becSSaleem Abdulrasool// Thread Local Storage
5676d7d0becSSaleem Abdulrasoolint __libcpp_tls_create(__libcpp_tls_key* __key,
5686d7d0becSSaleem Abdulrasool                        void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
5696d7d0becSSaleem Abdulrasool{
5706d7d0becSSaleem Abdulrasool  *__key = FlsAlloc(__at_exit);
5716d7d0becSSaleem Abdulrasool  if (*__key == FLS_OUT_OF_INDEXES)
5726d7d0becSSaleem Abdulrasool    return GetLastError();
5736d7d0becSSaleem Abdulrasool  return 0;
5746d7d0becSSaleem Abdulrasool}
5756d7d0becSSaleem Abdulrasool
5766d7d0becSSaleem Abdulrasoolvoid *__libcpp_tls_get(__libcpp_tls_key __key)
5776d7d0becSSaleem Abdulrasool{
5786d7d0becSSaleem Abdulrasool  return FlsGetValue(__key);
5796d7d0becSSaleem Abdulrasool}
5806d7d0becSSaleem Abdulrasool
5816d7d0becSSaleem Abdulrasoolint __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
5826d7d0becSSaleem Abdulrasool{
5836d7d0becSSaleem Abdulrasool  if (!FlsSetValue(__key, __p))
5846d7d0becSSaleem Abdulrasool    return GetLastError();
5856d7d0becSSaleem Abdulrasool  return 0;
5866d7d0becSSaleem Abdulrasool}
5876d7d0becSSaleem Abdulrasool
588790e10f6SSaleem Abdulrasool#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
589c7e4239fSAsiri Rathnayake
59000f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
59100f6beaeSEric Fiselier
592c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD
593c7e4239fSAsiri Rathnayake
59400f6beaeSEric Fiselier#endif // !_LIBCPP_HAS_NO_THREADS
595c7e4239fSAsiri Rathnayake
596c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT
597