Lely core libraries  2.3.4
threads-pthread.c
Go to the documentation of this file.
1 
23 #include "libc.h"
24 #include <lely/libc/threads.h>
25 
26 #if !LELY_NO_THREADS && LELY_HAVE_PTHREAD_H
27 
28 #if LELY_NO_ERRNO
29 #error This file requires errno.
30 #endif
31 
32 #include <errno.h>
33 #include <stdint.h>
34 
35 #if _WIN32
36 #include <processthreadsapi.h>
37 #endif
38 
39 #undef LELY_HAVE_SCHED
40 #if _POSIX_C_SOURCE >= 200112L && defined(_POSIX_PRIORITY_SCHEDULING)
41 #define LELY_HAVE_SCHED 1
42 #include <sched.h>
43 #endif
44 
45 void
46 call_once(once_flag *flag, void (*func)(void))
47 {
48  pthread_once(flag, func);
49 }
50 
51 int
53 {
54  int errsv = pthread_cond_broadcast(cond);
55  if (errsv) {
56  errno = errsv;
57  return thrd_error;
58  }
59  return thrd_success;
60 }
61 
62 void
64 {
65  pthread_cond_destroy(cond);
66 }
67 
68 int
70 {
71  int errsv = pthread_cond_init(cond, NULL);
72  if (errsv) {
73  errno = errsv;
74  return errsv == ENOMEM ? thrd_nomem : thrd_error;
75  }
76  return thrd_success;
77 }
78 
79 int
81 {
82  int errsv = pthread_cond_signal(cond);
83  if (errsv) {
84  errno = errsv;
85  return thrd_error;
86  }
87  return thrd_success;
88 }
89 
90 int
91 cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
92 {
93  int errsv = pthread_cond_timedwait(cond, mtx, ts);
94  if (errsv) {
95  errno = errsv;
96  return errsv == ETIMEDOUT ? thrd_timedout : thrd_error;
97  }
98  return thrd_success;
99 }
100 
101 int
102 cnd_wait(cnd_t *cond, mtx_t *mtx)
103 {
104  int errsv = pthread_cond_wait(cond, mtx);
105  if (errsv) {
106  errno = errsv;
107  return thrd_error;
108  }
109  return thrd_success;
110 }
111 
112 void
114 {
115  pthread_mutex_destroy(mtx);
116 }
117 
118 int
119 mtx_init(mtx_t *mtx, int type)
120 {
121  int errsv;
122  pthread_mutexattr_t attr;
123 
124  errsv = pthread_mutexattr_init(&attr);
125  if (errsv)
126  goto error_mutexattr_init;
127  // clang-format off
128  errsv = pthread_mutexattr_settype(&attr, (type & mtx_recursive)
129  ? PTHREAD_MUTEX_RECURSIVE
130  : PTHREAD_MUTEX_NORMAL);
131  // clang-format on
132  if (errsv)
133  goto error_mutexattr_settype;
134  errsv = pthread_mutex_init(mtx, &attr);
135  if (errsv)
136  goto error_mutex_init;
137  pthread_mutexattr_destroy(&attr);
138 
139  return thrd_success;
140 
141 error_mutex_init:
142 error_mutexattr_settype:
143  pthread_mutexattr_destroy(&attr);
144 error_mutexattr_init:
145  errno = errsv;
146  return thrd_error;
147 }
148 
149 int
151 {
152  int errsv = pthread_mutex_lock(mtx);
153  if (errsv) {
154  errno = errsv;
155  return thrd_error;
156  }
157  return thrd_success;
158 }
159 
160 int
161 mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
162 {
163  int errsv = pthread_mutex_timedlock(mtx, ts);
164  if (errsv) {
165  errno = errsv;
166  return errsv == ETIMEDOUT ? thrd_timedout : thrd_error;
167  }
168  return thrd_success;
169 }
170 
171 int
173 {
174  int errsv = pthread_mutex_trylock(mtx);
175  if (errsv) {
176  errno = errsv;
177  return errsv == EBUSY ? thrd_busy : thrd_error;
178  }
179  return thrd_success;
180 }
181 
182 int
184 {
185  int errsv = pthread_mutex_unlock(mtx);
186  if (errsv) {
187  errno = errsv;
188  return thrd_error;
189  }
190  return thrd_success;
191 }
192 
193 int
194 thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
195 {
196 #if __GNUC__ >= 8
197 #pragma GCC diagnostic push
198 #pragma GCC diagnostic ignored "-Wcast-function-type"
199 #endif
200  int errsv = pthread_create(thr, NULL, (void *(*)(void *))func, arg);
201 #if __GNUC__ >= 8
202 #pragma GCC diagnostic pop
203 #endif
204  if (errsv) {
205  errno = errsv;
206  return errsv == EAGAIN ? thrd_nomem : thrd_error;
207  }
208  return thrd_success;
209 }
210 
211 thrd_t
213 {
214  return pthread_self();
215 }
216 
217 int
219 {
220  int errsv = pthread_detach(thr);
221  if (errsv) {
222  errno = errsv;
223  return thrd_error;
224  }
225  return thrd_success;
226 }
227 
228 int
230 {
231  return pthread_equal(thr0, thr1);
232 }
233 
234 _Noreturn void
235 thrd_exit(int res)
236 {
237  pthread_exit((void *)(intptr_t)res);
238  // cppcheck-suppress unreachableCode
239  for (;;)
240  ;
241 }
242 
243 int
244 thrd_join(thrd_t thr, int *res)
245 {
246  void *value_ptr = NULL;
247  int errsv = pthread_join((pthread_t)thr, &value_ptr);
248  if (errsv) {
249  errno = errsv;
250  return thrd_error;
251  }
252  if (res)
253  *res = (intptr_t)value_ptr;
254  return thrd_success;
255 }
256 
257 int
258 thrd_sleep(const struct timespec *duration, struct timespec *remaining)
259 {
260  int errsv = errno;
261  int res = nanosleep(duration, remaining);
262  if (res) {
263  res = errno == EINTR ? -1 : -2;
264  errno = errsv;
265  }
266  return res;
267 }
268 
269 #if _WIN32
270 void
271 thrd_yield(void)
272 {
273  SwitchToThread();
274 }
275 #elif LELY_HAVE_SCHED
276 void
278 {
279  sched_yield();
280 }
281 #endif
282 
283 int
285 {
286  int errsv = pthread_key_create(key, dtor);
287  if (errsv) {
288  errno = errsv;
289  return thrd_error;
290  }
291  return thrd_success;
292 }
293 
294 void
296 {
297  pthread_key_delete(key);
298 }
299 
300 void *
302 {
303  return pthread_getspecific(key);
304 }
305 
306 int
307 tss_set(tss_t key, void *val)
308 {
309  int errsv = pthread_setspecific(key, val);
310  if (errsv) {
311  errno = errsv;
312  return thrd_error;
313  }
314  return thrd_success;
315 }
316 
317 #endif // !LELY_NO_THREADS && LELY_HAVE_PTHREAD_H
#define _Noreturn
A function declared with a _Noreturn function specifier SHALL not return to its caller.
Definition: features.h:224
This is the internal header file of the C11 and POSIX compatibility library.
This header file is part of the C11 and POSIX compatibility library; it includes <stdint....
int cnd_init(cnd_t *cond)
Creates a condition variable.
int thrd_equal(thrd_t thr0, thrd_t thr1)
Determines whether the thread identified by thr0 refers to the thread identified by thr1.
void * tss_get(tss_t key)
Returns the value for the current thread held in the thread-specific storage identified by key.
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
Creates a new thread executing func(arg).
int tss_create(tss_t *key, tss_dtor_t dtor)
Creates a thread-specific storage pointer with destructor dtor, which may be NULL.
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
Atomically unlocks the mutex at mtx and endeavors to block until the condition variable at cond is si...
_Noreturn void thrd_exit(int res)
Terminates execution of the calling thread and sets its result code to res.
int tss_set(tss_t key, void *val)
Sets the value for the current thread held in the thread-specific storage identified by key to val.
int cnd_broadcast(cnd_t *cond)
Unblocks all of the threads that are blocked on the condition variable at cond at the time of the cal...
int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
Suspends execution of the calling thread until either the interval specified by duration has elapsed ...
int mtx_init(mtx_t *mtx, int type)
Creates a mutex object with properties indicated by type, which must have one of the four values:
int mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
Endeavors to block until it locks the mutex at mtx or until after the TIME_UTC-based calendar time at...
int thrd_join(thrd_t thr, int *res)
Joins the thread identified by thr with the current thread by blocking until the other thread has ter...
void cnd_destroy(cnd_t *cond)
Releases all resources used by the condition variable at cond.
thrd_t thrd_current(void)
Identifies the thread that called it.
void call_once(once_flag *flag, void(*func)(void))
Uses the once_flag at flag to ensure that func is called exactly once, the first time the call_once()...
int cnd_wait(cnd_t *cond, mtx_t *mtx)
Atomically unlocks the mutex at mtx and endeavors to block until the condition variable at cond is si...
int mtx_trylock(mtx_t *mtx)
Endeavors to lock the mutex at mtx.
void thrd_yield(void)
Endeavors to permit other threads to run, even if the current thread would ordinarily continue to run...
int thrd_detach(thrd_t thr)
Tells the operating system to dispose of any resources allocated to the thread identified by thr when...
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
void tss_delete(tss_t key)
Releases any resources used by the thread-specific storage identified by key.
int cnd_signal(cnd_t *cond)
Unblocks one of the threads that are blocked on the condition variable at cond at the time of the cal...
This header file is part of the C11 and POSIX compatibility library; it includes <threads....
pthread_key_t tss_t
A complete object type that holds an identifier for a thread-specific storage pointer.
Definition: threads.h:95
int(* thrd_start_t)(void *)
The function pointer type that is passed to thrd_create() to create a new thread.
Definition: threads.h:168
pthread_t thrd_t
A complete object type that holds an identifier for a thread.
Definition: threads.h:85
pthread_cond_t cnd_t
A complete object type that holds an identifier for a condition variable.
Definition: threads.h:78
pthread_once_t once_flag
A complete object type that holds a flag for use by call_once().
Definition: threads.h:143
@ thrd_timedout
Indicates that the time specified in the call was reached without acquiring the requested resource.
Definition: threads.h:128
@ thrd_success
Indicates that the requested operation succeeded.
Definition: threads.h:121
@ thrd_busy
Indicates that the requested operation failed because a resource requested by a test and return funct...
Definition: threads.h:133
@ thrd_nomem
Indicates that the requested operation failed because it was unable to allocate memory.
Definition: threads.h:138
@ thrd_error
Indicates that the requested operation failed.
Definition: threads.h:123
pthread_mutex_t mtx_t
A complete object type that holds an identifier for a mutex.
Definition: threads.h:102
@ mtx_recursive
A mutex type that supports recursive locking.
Definition: threads.h:111
void(* tss_dtor_t)(void *)
The function pointer type used for a destructor for a thread-specific storage pointer.
Definition: threads.h:157