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
cnd_signal
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...
Definition: threads-pthread.c:80
tss_dtor_t
void(* tss_dtor_t)(void *)
The function pointer type used for a destructor for a thread-specific storage pointer.
Definition: threads.h:157
thrd_t
pthread_t thrd_t
A complete object type that holds an identifier for a thread.
Definition: threads.h:85
thrd_create
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
Creates a new thread executing func(arg).
Definition: threads-pthread.c:194
thrd_join
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...
Definition: threads-pthread.c:244
threads.h
thrd_nomem
@ thrd_nomem
Indicates that the requested operation failed because it was unable to allocate memory.
Definition: threads.h:138
cnd_timedwait
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...
Definition: threads-pthread.c:91
mtx_unlock
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
Definition: threads-pthread.c:183
mtx_lock
int mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
Definition: threads-pthread.c:150
tss_get
void * tss_get(tss_t key)
Returns the value for the current thread held in the thread-specific storage identified by key.
Definition: threads-pthread.c:301
thrd_error
@ thrd_error
Indicates that the requested operation failed.
Definition: threads.h:123
tss_t
pthread_key_t tss_t
A complete object type that holds an identifier for a thread-specific storage pointer.
Definition: threads.h:95
libc.h
thrd_detach
int thrd_detach(thrd_t thr)
Tells the operating system to dispose of any resources allocated to the thread identified by thr when...
Definition: threads-pthread.c:218
mtx_t
pthread_mutex_t mtx_t
A complete object type that holds an identifier for a mutex.
Definition: threads.h:102
cnd_t
pthread_cond_t cnd_t
A complete object type that holds an identifier for a condition variable.
Definition: threads.h:78
tss_delete
void tss_delete(tss_t key)
Releases any resources used by the thread-specific storage identified by key.
Definition: threads-pthread.c:295
thrd_exit
_Noreturn void thrd_exit(int res)
Terminates execution of the calling thread and sets its result code to res.
Definition: threads-pthread.c:235
thrd_success
@ thrd_success
Indicates that the requested operation succeeded.
Definition: threads.h:121
mtx_trylock
int mtx_trylock(mtx_t *mtx)
Endeavors to lock the mutex at mtx.
Definition: threads-pthread.c:172
_Noreturn
#define _Noreturn
A function declared with a _Noreturn function specifier SHALL not return to its caller.
Definition: features.h:224
tss_create
int tss_create(tss_t *key, tss_dtor_t dtor)
Creates a thread-specific storage pointer with destructor dtor, which may be NULL.
Definition: threads-pthread.c:284
once_flag
pthread_once_t once_flag
A complete object type that holds a flag for use by call_once().
Definition: threads.h:143
cnd_init
int cnd_init(cnd_t *cond)
Creates a condition variable.
Definition: threads-pthread.c:69
tss_set
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.
Definition: threads-pthread.c:307
mtx_recursive
@ mtx_recursive
A mutex type that supports recursive locking.
Definition: threads.h:111
mtx_init
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:
Definition: threads-pthread.c:119
stdint.h
thrd_busy
@ thrd_busy
Indicates that the requested operation failed because a resource requested by a test and return funct...
Definition: threads.h:133
thrd_timedout
@ thrd_timedout
Indicates that the time specified in the call was reached without acquiring the requested resource.
Definition: threads.h:128
thrd_sleep
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 ...
Definition: threads-pthread.c:258
cnd_broadcast
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...
Definition: threads-pthread.c:52
thrd_equal
int thrd_equal(thrd_t thr0, thrd_t thr1)
Determines whether the thread identified by thr0 refers to the thread identified by thr1.
Definition: threads-pthread.c:229
cnd_destroy
void cnd_destroy(cnd_t *cond)
Releases all resources used by the condition variable at cond.
Definition: threads-pthread.c:63
mtx_timedlock
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...
Definition: threads-pthread.c:161
cnd_wait
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...
Definition: threads-pthread.c:102
mtx_destroy
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
Definition: threads-pthread.c:113
thrd_start_t
int(* thrd_start_t)(void *)
The function pointer type that is passed to thrd_create() to create a new thread.
Definition: threads.h:168
call_once
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()...
Definition: threads-pthread.c:46
thrd_yield
void thrd_yield(void)
Endeavors to permit other threads to run, even if the current thread would ordinarily continue to run...
Definition: threads-pthread.c:277
thrd_current
thrd_t thrd_current(void)
Identifies the thread that called it.
Definition: threads-pthread.c:212