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
20c7e4239fSAsiri Rathnayake#ifndef _LIBCPP_HAS_NO_THREADS
21c7e4239fSAsiri Rathnayake
223cf2f7bcSAsiri Rathnayake#ifndef __libcpp_has_include
233cf2f7bcSAsiri Rathnayake  #ifndef __has_include
243cf2f7bcSAsiri Rathnayake    #define __libcpp_has_include(x) 0
253cf2f7bcSAsiri Rathnayake  #else
263cf2f7bcSAsiri Rathnayake    #define __libcpp_has_include(x) __has_include(x)
27d547ac0dSAsiri Rathnayake  #endif
28d547ac0dSAsiri Rathnayake#endif
29d547ac0dSAsiri Rathnayake
303cf2f7bcSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \
31*6cb0d41cSAsiri Rathnayake    !__libcpp_has_include(<__external_threading>)
32*6cb0d41cSAsiri Rathnayake// If the <__external_threading> header is absent, build libc++ against a
33*6cb0d41cSAsiri Rathnayake// pthread-oriented thread api but leave out its implementation. This setup
34*6cb0d41cSAsiri Rathnayake// allows building+testing of an externally-threaded library variant (on any
35*6cb0d41cSAsiri Rathnayake// platform that supports pthreads). Here, an 'externally-threaded' library
36*6cb0d41cSAsiri Rathnayake// variant is one where the implementation of the libc++ thread api is provided
37*6cb0d41cSAsiri Rathnayake// as a separate library.
38*6cb0d41cSAsiri Rathnayake#define _LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD
39*6cb0d41cSAsiri Rathnayake#endif
40*6cb0d41cSAsiri Rathnayake
41*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) && \
423cf2f7bcSAsiri Rathnayake    __libcpp_has_include(<__external_threading>)
433cf2f7bcSAsiri Rathnayake#include <__external_threading>
443cf2f7bcSAsiri Rathnayake#else
45790e10f6SSaleem Abdulrasool
46*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \
47*6cb0d41cSAsiri Rathnayake    defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD)
48c7e4239fSAsiri Rathnayake#include <pthread.h>
49c7e4239fSAsiri Rathnayake#include <sched.h>
50790e10f6SSaleem Abdulrasool#endif
51c7e4239fSAsiri Rathnayake
528c2bf45dSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_EXTERNAL)
538c2bf45dSAsiri Rathnayake#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS
548c2bf45dSAsiri Rathnayake#else
558c2bf45dSAsiri Rathnayake#define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
568c2bf45dSAsiri Rathnayake#endif
578c2bf45dSAsiri Rathnayake
58c7e4239fSAsiri Rathnayake_LIBCPP_BEGIN_NAMESPACE_STD
59c7e4239fSAsiri Rathnayake
60*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \
61*6cb0d41cSAsiri Rathnayake    defined(_LIBCPP_HAS_THREAD_API_EXTERNAL_PTHREAD)
62c7e4239fSAsiri Rathnayake// Mutex
63c7e4239fSAsiri Rathnayaketypedef pthread_mutex_t __libcpp_mutex_t;
648c2bf45dSAsiri Rathnayake#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
65c7e4239fSAsiri Rathnayake
66790e10f6SSaleem Abdulrasool// Condition Variable
67790e10f6SSaleem Abdulrasooltypedef pthread_cond_t __libcpp_condvar_t;
68790e10f6SSaleem Abdulrasool#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
69790e10f6SSaleem Abdulrasool
70790e10f6SSaleem Abdulrasool// THread ID
71790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_id;
72790e10f6SSaleem Abdulrasool
73790e10f6SSaleem Abdulrasool// Thread
74790e10f6SSaleem Abdulrasooltypedef pthread_t __libcpp_thread_t;
75790e10f6SSaleem Abdulrasool
76790e10f6SSaleem Abdulrasool// Thrad Local Storage
77790e10f6SSaleem Abdulrasooltypedef pthread_key_t __libcpp_tls_key;
78790e10f6SSaleem Abdulrasool#endif
79790e10f6SSaleem Abdulrasool
80790e10f6SSaleem Abdulrasool// Mutex
818c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
828c2bf45dSAsiri Rathnayakeint __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m);
83790e10f6SSaleem Abdulrasool
848c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
858c2bf45dSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m);
86790e10f6SSaleem Abdulrasool
878c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
888c2bf45dSAsiri Rathnayakeint __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
89790e10f6SSaleem Abdulrasool
908c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
918c2bf45dSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
92790e10f6SSaleem Abdulrasool
938c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
948c2bf45dSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m);
958c2bf45dSAsiri Rathnayake
968c2bf45dSAsiri Rathnayake// Condition variable
978c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
988c2bf45dSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t* __cv);
99790e10f6SSaleem Abdulrasool
1008c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1018c2bf45dSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
102790e10f6SSaleem Abdulrasool
1038c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1048c2bf45dSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
105790e10f6SSaleem Abdulrasool
1068c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
107790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
108790e10f6SSaleem Abdulrasool                               timespec *__ts);
109790e10f6SSaleem Abdulrasool
1108c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1118c2bf45dSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t* __cv);
1128c2bf45dSAsiri Rathnayake
113790e10f6SSaleem Abdulrasool// Thread ID
1148c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1158c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2);
116790e10f6SSaleem Abdulrasool
1178c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1188c2bf45dSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2);
1198c2bf45dSAsiri Rathnayake
1208c2bf45dSAsiri Rathnayake// Thread
1218c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
122790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
123790e10f6SSaleem Abdulrasool                           void *__arg);
124790e10f6SSaleem Abdulrasool
1258c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1268c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id();
127790e10f6SSaleem Abdulrasool
1288c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1298c2bf45dSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t);
130790e10f6SSaleem Abdulrasool
1318c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1328c2bf45dSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t);
133790e10f6SSaleem Abdulrasool
1348c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1358c2bf45dSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t);
136790e10f6SSaleem Abdulrasool
1378c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1388c2bf45dSAsiri Rathnayakevoid __libcpp_thread_yield();
1398c2bf45dSAsiri Rathnayake
1408c2bf45dSAsiri Rathnayake// Thread local storage
1418c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1428c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *));
143790e10f6SSaleem Abdulrasool
1448c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1458c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key);
146790e10f6SSaleem Abdulrasool
1478c2bf45dSAsiri Rathnayake_LIBCPP_THREAD_ABI_VISIBILITY
1488c2bf45dSAsiri Rathnayakevoid __libcpp_tls_set(__libcpp_tls_key __key, void *__p);
1498c2bf45dSAsiri Rathnayake
150*6cb0d41cSAsiri Rathnayake#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) || \
151*6cb0d41cSAsiri Rathnayake    defined(_LIBCPP_BUILDING_THREAD_API_EXTERNAL_PTHREAD)
1528c2bf45dSAsiri Rathnayake
153c7e4239fSAsiri Rathnayakeint __libcpp_recursive_mutex_init(__libcpp_mutex_t *__m)
154c7e4239fSAsiri Rathnayake{
155c7e4239fSAsiri Rathnayake  pthread_mutexattr_t attr;
156c7e4239fSAsiri Rathnayake  int __ec = pthread_mutexattr_init(&attr);
157c7e4239fSAsiri Rathnayake  if (__ec)
158790e10f6SSaleem Abdulrasool    return __ec;
159790e10f6SSaleem Abdulrasool  __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
160790e10f6SSaleem Abdulrasool  if (__ec) {
161c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
162c7e4239fSAsiri Rathnayake    return __ec;
163c7e4239fSAsiri Rathnayake  }
164c7e4239fSAsiri Rathnayake  __ec = pthread_mutex_init(__m, &attr);
165790e10f6SSaleem Abdulrasool  if (__ec) {
166c7e4239fSAsiri Rathnayake    pthread_mutexattr_destroy(&attr);
167c7e4239fSAsiri Rathnayake    return __ec;
168c7e4239fSAsiri Rathnayake  }
169c7e4239fSAsiri Rathnayake  __ec = pthread_mutexattr_destroy(&attr);
170790e10f6SSaleem Abdulrasool  if (__ec) {
171c7e4239fSAsiri Rathnayake    pthread_mutex_destroy(__m);
172c7e4239fSAsiri Rathnayake    return __ec;
173c7e4239fSAsiri Rathnayake  }
174c7e4239fSAsiri Rathnayake  return 0;
175c7e4239fSAsiri Rathnayake}
176c7e4239fSAsiri Rathnayake
177c7e4239fSAsiri Rathnayakeint __libcpp_mutex_lock(__libcpp_mutex_t *__m)
178c7e4239fSAsiri Rathnayake{
179c7e4239fSAsiri Rathnayake  return pthread_mutex_lock(__m);
180c7e4239fSAsiri Rathnayake}
181c7e4239fSAsiri Rathnayake
182c7e4239fSAsiri Rathnayakeint __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
183c7e4239fSAsiri Rathnayake{
184c7e4239fSAsiri Rathnayake  return pthread_mutex_trylock(__m);
185c7e4239fSAsiri Rathnayake}
186c7e4239fSAsiri Rathnayake
187c7e4239fSAsiri Rathnayakeint __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
188c7e4239fSAsiri Rathnayake{
189c7e4239fSAsiri Rathnayake  return pthread_mutex_unlock(__m);
190c7e4239fSAsiri Rathnayake}
191c7e4239fSAsiri Rathnayake
192c7e4239fSAsiri Rathnayakeint __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
193c7e4239fSAsiri Rathnayake{
194c7e4239fSAsiri Rathnayake  return pthread_mutex_destroy(__m);
195c7e4239fSAsiri Rathnayake}
196c7e4239fSAsiri Rathnayake
197790e10f6SSaleem Abdulrasool// Condition Variable
198c7e4239fSAsiri Rathnayakeint __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
199c7e4239fSAsiri Rathnayake{
200c7e4239fSAsiri Rathnayake  return pthread_cond_signal(__cv);
201c7e4239fSAsiri Rathnayake}
202c7e4239fSAsiri Rathnayake
203c7e4239fSAsiri Rathnayakeint __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
204c7e4239fSAsiri Rathnayake{
205c7e4239fSAsiri Rathnayake  return pthread_cond_broadcast(__cv);
206c7e4239fSAsiri Rathnayake}
207c7e4239fSAsiri Rathnayake
208c7e4239fSAsiri Rathnayakeint __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
209c7e4239fSAsiri Rathnayake{
210c7e4239fSAsiri Rathnayake  return pthread_cond_wait(__cv, __m);
211c7e4239fSAsiri Rathnayake}
212c7e4239fSAsiri Rathnayake
213790e10f6SSaleem Abdulrasoolint __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
214790e10f6SSaleem Abdulrasool                               timespec *__ts)
215c7e4239fSAsiri Rathnayake{
216c7e4239fSAsiri Rathnayake  return pthread_cond_timedwait(__cv, __m, __ts);
217c7e4239fSAsiri Rathnayake}
218c7e4239fSAsiri Rathnayake
219c7e4239fSAsiri Rathnayakeint __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
220c7e4239fSAsiri Rathnayake{
221c7e4239fSAsiri Rathnayake  return pthread_cond_destroy(__cv);
222c7e4239fSAsiri Rathnayake}
223c7e4239fSAsiri Rathnayake
224c7e4239fSAsiri Rathnayake// Returns non-zero if the thread ids are equal, otherwise 0
225c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
226c7e4239fSAsiri Rathnayake{
227c7e4239fSAsiri Rathnayake  return pthread_equal(t1, t2) != 0;
228c7e4239fSAsiri Rathnayake}
229c7e4239fSAsiri Rathnayake
230c7e4239fSAsiri Rathnayake// Returns non-zero if t1 < t2, otherwise 0
231c7e4239fSAsiri Rathnayakebool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
232c7e4239fSAsiri Rathnayake{
233c7e4239fSAsiri Rathnayake  return t1 < t2;
234c7e4239fSAsiri Rathnayake}
235c7e4239fSAsiri Rathnayake
236c7e4239fSAsiri Rathnayake// Thread
237790e10f6SSaleem Abdulrasoolint __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
238790e10f6SSaleem Abdulrasool                           void *__arg)
239c7e4239fSAsiri Rathnayake{
240c7e4239fSAsiri Rathnayake  return pthread_create(__t, 0, __func, __arg);
241c7e4239fSAsiri Rathnayake}
242c7e4239fSAsiri Rathnayake
243c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_current_id()
244c7e4239fSAsiri Rathnayake{
245c7e4239fSAsiri Rathnayake  return pthread_self();
246c7e4239fSAsiri Rathnayake}
247c7e4239fSAsiri Rathnayake
248c7e4239fSAsiri Rathnayake__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
249c7e4239fSAsiri Rathnayake{
250c7e4239fSAsiri Rathnayake  return *__t;
251c7e4239fSAsiri Rathnayake}
252c7e4239fSAsiri Rathnayake
253c7e4239fSAsiri Rathnayakeint __libcpp_thread_join(__libcpp_thread_t *__t)
254c7e4239fSAsiri Rathnayake{
255c7e4239fSAsiri Rathnayake  return pthread_join(*__t, 0);
256c7e4239fSAsiri Rathnayake}
257c7e4239fSAsiri Rathnayake
258c7e4239fSAsiri Rathnayakeint __libcpp_thread_detach(__libcpp_thread_t *__t)
259c7e4239fSAsiri Rathnayake{
260c7e4239fSAsiri Rathnayake  return pthread_detach(*__t);
261c7e4239fSAsiri Rathnayake}
262c7e4239fSAsiri Rathnayake
263c7e4239fSAsiri Rathnayakevoid __libcpp_thread_yield()
264c7e4239fSAsiri Rathnayake{
265c7e4239fSAsiri Rathnayake  sched_yield();
266c7e4239fSAsiri Rathnayake}
267c7e4239fSAsiri Rathnayake
268c7e4239fSAsiri Rathnayake// Thread local storage
2698c2bf45dSAsiri Rathnayakeint __libcpp_tls_create(__libcpp_tls_key *__key, void (*__at_exit)(void *))
270c7e4239fSAsiri Rathnayake{
271c7e4239fSAsiri Rathnayake  return pthread_key_create(__key, __at_exit);
272c7e4239fSAsiri Rathnayake}
273c7e4239fSAsiri Rathnayake
2748c2bf45dSAsiri Rathnayakevoid *__libcpp_tls_get(__libcpp_tls_key __key)
275c7e4239fSAsiri Rathnayake{
276c7e4239fSAsiri Rathnayake  return pthread_getspecific(__key);
277c7e4239fSAsiri Rathnayake}
278c7e4239fSAsiri Rathnayake
2798c2bf45dSAsiri Rathnayakevoid __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
280c7e4239fSAsiri Rathnayake{
281c7e4239fSAsiri Rathnayake  pthread_setspecific(__key, __p);
282c7e4239fSAsiri Rathnayake}
283c7e4239fSAsiri Rathnayake
284790e10f6SSaleem Abdulrasool#endif // _LIBCPP_HAS_THREAD_API_PTHREAD
285c7e4239fSAsiri Rathnayake
286c7e4239fSAsiri Rathnayake_LIBCPP_END_NAMESPACE_STD
287c7e4239fSAsiri Rathnayake
2883cf2f7bcSAsiri Rathnayake#endif // !_LIBCPP_HAS_THREAD_API_EXTERNAL || !__libcpp_has_include(<__external_threading>)
28981c0be3fSAsiri Rathnayake
290c7e4239fSAsiri Rathnayake#endif // _LIBCPP_HAS_NO_THREADS
291c7e4239fSAsiri Rathnayake
292c7e4239fSAsiri Rathnayake#endif // _LIBCPP_THREADING_SUPPORT
293