blob: 49fdca2780615a37a9d79321e555d4d351983b9e [file] [log] [blame]
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +00001// -*- 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
16#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
17#pragma GCC system_header
18#endif
19
20#ifndef _LIBCPP_HAS_NO_THREADS
21
22#if defined(_LIBCPP_THREAD_API_PTHREAD)
23#include <pthread.h>
24#include <sched.h>
25#endif
26
27_LIBCPP_BEGIN_NAMESPACE_STD
28
29#if defined(_LIBCPP_THREAD_API_PTHREAD)
30
31// Mutex
32#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
33typedef pthread_mutex_t __libcpp_mutex_t;
34
35inline _LIBCPP_ALWAYS_INLINE
36int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m)
37{
38 pthread_mutexattr_t attr;
39 int __ec = pthread_mutexattr_init(&attr);
40 if (__ec) return __ec;
41 __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
42 if (__ec)
43 {
44 pthread_mutexattr_destroy(&attr);
45 return __ec;
46 }
47 __ec = pthread_mutex_init(__m, &attr);
48 if (__ec)
49 {
50 pthread_mutexattr_destroy(&attr);
51 return __ec;
52 }
53 __ec = pthread_mutexattr_destroy(&attr);
54 if (__ec)
55 {
56 pthread_mutex_destroy(__m);
57 return __ec;
58 }
59 return 0;
60}
61
62inline _LIBCPP_ALWAYS_INLINE
63int __libcpp_mutex_lock(__libcpp_mutex_t* __m)
64{
65 return pthread_mutex_lock(__m);
66}
67
68inline _LIBCPP_ALWAYS_INLINE
69int __libcpp_mutex_trylock(__libcpp_mutex_t* __m)
70{
71 return pthread_mutex_trylock(__m);
72}
73
74inline _LIBCPP_ALWAYS_INLINE
75int __libcpp_mutex_unlock(__libcpp_mutex_t* __m)
76{
77 return pthread_mutex_unlock(__m);
78}
79
80inline _LIBCPP_ALWAYS_INLINE
81int __libcpp_mutex_destroy(__libcpp_mutex_t* __m)
82{
83 return pthread_mutex_destroy(__m);
84}
85
86// Condition variable
87#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER
88typedef pthread_cond_t __libcpp_condvar_t;
89
90inline _LIBCPP_ALWAYS_INLINE
91int __libcpp_condvar_signal(__libcpp_condvar_t* __cv)
92{
93 return pthread_cond_signal(__cv);
94}
95
96inline _LIBCPP_ALWAYS_INLINE
97int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv)
98{
99 return pthread_cond_broadcast(__cv);
100}
101
102inline _LIBCPP_ALWAYS_INLINE
103int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m)
104{
105 return pthread_cond_wait(__cv, __m);
106}
107
108inline _LIBCPP_ALWAYS_INLINE
109int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts)
110{
111 return pthread_cond_timedwait(__cv, __m, __ts);
112}
113
114inline _LIBCPP_ALWAYS_INLINE
115int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv)
116{
117 return pthread_cond_destroy(__cv);
118}
119
120// Thread id
121typedef pthread_t __libcpp_thread_id;
122
123// Returns non-zero if the thread ids are equal, otherwise 0
124inline _LIBCPP_ALWAYS_INLINE
125bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2)
126{
127 return pthread_equal(t1, t2) != 0;
128}
129
130// Returns non-zero if t1 < t2, otherwise 0
131inline _LIBCPP_ALWAYS_INLINE
132bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2)
133{
134 return t1 < t2;
135}
136
137// Thread
138typedef pthread_t __libcpp_thread_t;
139
140inline _LIBCPP_ALWAYS_INLINE
141int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg)
142{
143 return pthread_create(__t, 0, __func, __arg);
144}
145
146inline _LIBCPP_ALWAYS_INLINE
147__libcpp_thread_id __libcpp_thread_get_current_id()
148{
149 return pthread_self();
150}
151
152inline _LIBCPP_ALWAYS_INLINE
153__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t)
154{
155 return *__t;
156}
157
158inline _LIBCPP_ALWAYS_INLINE
159int __libcpp_thread_join(__libcpp_thread_t* __t)
160{
161 return pthread_join(*__t, 0);
162}
163
164inline _LIBCPP_ALWAYS_INLINE
165int __libcpp_thread_detach(__libcpp_thread_t* __t)
166{
167 return pthread_detach(*__t);
168}
169
170inline _LIBCPP_ALWAYS_INLINE
171void __libcpp_thread_yield()
172{
173 sched_yield();
174}
175
176// Thread local storage
177typedef pthread_key_t __libcpp_tl_key;
178
179inline _LIBCPP_ALWAYS_INLINE
180int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit)(void*))
181{
182 return pthread_key_create(__key, __at_exit);
183}
184
185inline _LIBCPP_ALWAYS_INLINE
186void* __libcpp_tl_get(__libcpp_tl_key __key)
187{
188 return pthread_getspecific(__key);
189}
190
191inline _LIBCPP_ALWAYS_INLINE
192void __libcpp_tl_set(__libcpp_tl_key __key, void* __p)
193{
194 pthread_setspecific(__key, __p);
195}
196
197#else // !_LIBCPP_THREAD_API_PTHREAD
198 #error "No thread API selected."
199#endif
200
201_LIBCPP_END_NAMESPACE_STD
202
203#endif // _LIBCPP_HAS_NO_THREADS
204
205#endif // _LIBCPP_THREADING_SUPPORT