KallistiOS  ##version##
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
threads.h
Go to the documentation of this file.
1 /* KallistiOS ##version##
2 
3  threads.h
4  Copyright (C) 2014 Lawrence Sebald
5 */
6 
7 /** \file threads.h
8  \brief C11 threading functionality.
9 
10  This file contains the definitions needed for using C11 threads. The C11
11  standard defines a number of threading-related primitives, which we wrap
12  neatly around KOS' built-in threading support here.
13 
14  If you compile your code with a strict standard set (you use a -std= flag
15  with GCC that doesn't start with gnu), you must use -std=c11 to use this
16  functionality. If you don't pass a -std= flag to GCC, then you're probably
17  fine.
18 
19  \author Lawrence Sebald
20 */
21 
22 #ifndef __THREADS_H
23 #define __THREADS_H
24 
25 #if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 201112L)
26 
27 #include <sys/cdefs.h>
28 #include <time.h>
29 
30 /* Bring in all the threading-related stuff we'll need. */
31 #include <kos/thread.h>
32 #include <kos/once.h>
33 #include <kos/mutex.h>
34 #include <kos/cond.h>
35 #include <kos/tls.h>
36 
37 __BEGIN_DECLS
38 
39 /** \defgroup c11_thd_rvs C11 Thread function return values
40 
41  Most of the C11 thread-related functions that return a result code return
42  one of these.
43 
44  @{
45 */
46 #define thrd_success 0 /**< \brief Success */
47 #define thrd_error -1 /**< \brief Uncategorized error */
48 #define thrd_timedout -2 /**< \brief Time out error */
49 #define thrd_busy -3 /**< \brief Resource busy */
50 #define thrd_nomem -4 /**< \brief Out of memory */
51 /** @} */
52 
53 /** \brief Object type backing call_once.
54 
55  This object type holds a flag that is used by the call_once function to call
56  a function one time. It should always be initialized with the ONCE_FLAG_INIT
57  macro.
58 
59  \headerfile threads.h
60 */
62 
63 /** \brief Macro to initiallize a once_flag object. */
64 #define ONCE_FLAG_INIT KTHREAD_ONCE_INIT
65 
66 /** \brief Call a function one time, no matter how many threads try.
67 
68  This function uses the once_flag object passed in to ensure that a given
69  function is called exactly once, regardless of how many threads attempt to
70  call through the once_flag.
71 
72  \param flag The once_flag to run against.
73  \param func The function to call.
74 */
75 extern void call_once(once_flag *flag, void (*func)(void));
76 
77 /** \brief C11 mutual exclusion lock type.
78 
79  This type holds an identifier for a mutual exclusion (mutex) lock to be used
80  with C11 threading support.
81 
82  \headerfile threads.h
83 */
84 typedef mutex_t mtx_t;
85 
86 /** \defgroup c11_mutex_types C11 mutual exclusion lock types
87 
88  These are the possible types of mutex locks that C11 allows for. Note that
89  mtx_plain or mtx_recursive can be ORed with mtx_timed as well.
90 
91  @{
92 */
93 #define mtx_plain (1 << 0) /**< \brief Plain mutex */
94 #define mtx_recursive (1 << 1) /**< \brief Recursive mutex */
95 #define mtx_timed (1 << 2) /**< \brief Mutex supporting the
96  mtx_timedlock function. */
97 /** @} */
98 
99 /** \brief Deinitialize a mutex lock.
100 
101  This function deinitializes a mutex lock that was previously created with
102  mtx_init().
103 
104  \param mtx The mutex to deinitialize.
105 */
106 extern void mtx_destroy(mtx_t *mtx);
107 
108 /** \brief Initialize a mutex lock.
109 
110  This function initializes a mutex lock of the given type for later use to
111  protect critical sections of code.
112 
113  \param mtx The mutex to initialize.
114  \param type The type of mutex desired (see
115  \ref c11_mutex_types).
116  \retval thrd_success On success.
117  \retval thrd_error If the request could not be honored.
118 */
119 extern int mtx_init(mtx_t *mtx, int type);
120 
121 /** \brief Lock a mutex lock.
122 
123  This function locks the specified mutex, preventing any other threads from
124  obtaining the same lock.
125 
126  This function will block until the lock can be obtained.
127 
128  \param mtx The mutex to lock.
129  \retval thrd_success On success.
130  \retval thrd_error If the request could not be honored.
131 
132  \note Calling this function in an interrupt will result in an error being
133  returned.
134 */
135 extern int mtx_lock(mtx_t *mtx);
136 
137 /** \brief Lock a mutex lock with a timeout.
138 
139  This function locks the specified mutex, assuming that the lock can be
140  obtained in the time period specified.
141 
142  This function will block until the lock can be obtained or the timeout
143  expires.
144 
145  \param mtx The mutex to lock.
146  \param ts The amount of time to wait before timing out.
147  \retval thrd_success On success.
148  \retval thrd_error If the request could not be honored for some other
149  reason than a timeout.
150  \retval thrd_timedout If the timeout specified passes without obtaining
151  the lock.
152 
153  \note Calling this function in an interrupt will result in an error being
154  returned.
155  \note Although timeouts are specified in seconds and nanoseconds, the
156  timeout will be rounded up to the nearest millisecond.
157 */
158 extern int mtx_timedlock(mtx_t *restrict mtx,
159  const struct timespec *restrict ts);
160 
161 /** \brief Attempt to acquire a mutex lock.
162 
163  This function attempts to acquire the specififed mutex and will not block if
164  it cannot be obtained.
165 
166  \param mtx The mutex to lock.
167  \retval thrd_success On success.
168  \retval thrd_busy If the lock is already locked by a thread.
169  \retval thrd_error If the request could not be honored for some other
170  reason.
171 
172  \note This function is safe to call in an interrupt.
173  \note Always check the return value to ensure that the lock was obtained.
174 */
175 extern int mtx_trylock(mtx_t *mtx);
176 
177 /** \brief Unlock a previously acquired lock.
178 
179  This function releases the specified mutex lock, allowing other threads to
180  acquire it.
181 
182  \param mtx The mutex to unlock.
183  \retval thrd_success On success.
184  \retval thrd_error If the request cannot be honored.
185 
186  \note Unlocking a mutex that was not previously locked by the calling
187  thread results in undefined behavior.
188 */
189 extern int mtx_unlock(mtx_t *mtx);
190 
191 /** \brief C11 condition variable type.
192 
193  This type holds an identifier for a condition variable object that is to be
194  used with C11 threading support.
195 
196  \headerfile threads.h
197 */
198 typedef condvar_t cnd_t;
200 /** \brief Broadcast to all threads locked on a condition variable.
201 
202  This function wakes all threads that are blocked on the condition variable
203  cond at the time of the call. If no threads are currently blocked on cond,
204  this call does nothing.
205 
206  \param cond The condition variable to signal.
207  \retval thrd_success On success.
208  \retval thrd_error If the request cannot be honored.
209 */
210 extern int cnd_broadcast(cnd_t *cond);
211 
212 /** \brief Deinitialize a condition variable.
213 
214  This function cleans up all resources associated with the given condition
215  variable. You must ensure that no threads are currently blocked on the
216  condition variable before calling this function.
217 
218  \param cond The condition variable to deinitialize.
219 
220  \note Deinitializing a condition variable that is currently being waited
221  on by threads results in undefined behavior.
222 */
223 extern void cnd_destroy(cnd_t *cond);
224 
225 /** \brief Initialize a condition variable.
226 
227  This function initializes the specified condition variable for use.
228 
229  \param cond The condition variable to signal.
230  \retval thrd_success On success.
231  \retval thrd_nomem If memory cannot be allocated for the new condition
232  variable.
233  \retval thrd_error If the request cannot be honored for some other
234  reason.
235 */
236 extern int cnd_init(cnd_t *cond);
237 
238 /** \brief Signal one thread locked on a condition variable.
239 
240  This function wakes one thread that is blocked on the condition variable
241  cond at the time of the call. If no threads are currently blocked on cond,
242  this call does nothing.
243 
244  \param cond The condition variable to signal.
245  \retval thrd_success On success.
246  \retval thrd_error If the request cannot be honored.
247 */
248 extern int cnd_signal(cnd_t *cond);
249 
250 /** \brief Wait on a condition variable (with a timeout).
251 
252  This function puts the calling thread to sleep until either the condition
253  variable is signaled or the timeout specified expires, whichever happens
254  first. The specified mutex must be held by the calling thread when calling
255  this function and will be held by the thread again when it is unblocked.
256 
257  \param cond The condition variable to wait on.
258  \param mtx The mutex associated with the condition variable.
259  \param ts The time to wait before timing out.
260  \retval thrd_success On success.
261  \retval thrd_timedout If the timeout was reached before the condition
262  variable was signaled.
263  \retval thrd_error If the request cannot be honored for some other
264  reason.
265 
266  \note Calling this function in an interrupt will result in an error being
267  returned.
268  \note Although timeouts are specified in seconds and nanoseconds, the
269  timeout will be rounded up to the nearest millisecond.
270 */
271 extern int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx,
272  const struct timespec *restrict ts);
273 
274 /** \brief Wait on a condition variable.
275 
276  This function puts the calling thread to sleep until the condition variable
277  is signaled. The specified mutex must be held by the calling thread when
278  calling this function and will be held by the thread again when it is
279  unblocked.
280 
281  \param cond The condition variable to wait on.
282  \param mtx The mutex associated with the condition variable.
283  \retval thrd_success On success.
284  \retval thrd_error If the request cannot be honored.
285 
286  \note Calling this function in an interrupt will result in an error being
287  returned.
288 */
289 extern int cnd_wait(cnd_t *cond, mtx_t *mtx);
290 
291 /** \brief C11 thread identifier type.
292 
293  This type holds an identifier for a C11 thread.
294 
295  \headerfile threads.h
296 */
297 typedef kthread_t *thrd_t;
299 /** \brief C11 thread start function type.
300 
301  This is a function pointer type representing a function used to begin a
302  thread. The thread exits when the function returns or calls thrd_exit().
303 
304  \headerfile threads.h
305 */
306 typedef int (*thrd_start_t)(void *);
308 /** \brief Create and start a new thread.
309 
310  This function creates a new thread, calling the function specified. The
311  thread is immediately added to the runnable queue of the scheduler and can
312  start at any moment after that. The thread ends when either the function
313  specified returns or when the thread calls thrd_exit().
314 
315  \param thr Storage for the thread identifier.
316  \param func The function to call in the new thread.
317  \param arg Argument to pass to the function called.
318  \retval thrd_success On success.
319  \retval thrd_nomem If memory cannot be allocated to satisfy the
320  request.
321  \retval thrd_error If the request cannot be honored for some other
322  reason.
323 
324  \note All threads created are joinable threads by default. That means that
325  in order to free all resources at thread termination, the thread
326  must be joined with the thrd_join() function or detached at some
327  point with thrd_detach().
328 */
329 extern int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
330 
331 /** \brief Return the identifier of the currently running thread.
332 
333  \return The current thread's ID.
334 */
335 extern thrd_t thrd_current(void);
336 
337 /** \brief Detach a running thread.
338 
339  This function detaches a thread, which informs the kernel that any resources
340  associated with the thread should be freed immediately when it terminates.
341 
342  \param thr The thread to detach.
343  \retval thrd_success On success.
344  \retval thrd_error If the request cannot be honored.
345 
346  \note Detaching an already detached thread has no effect.
347  \note Detaching a thread that has been joined with another thread results
348  in undefined behavior.
349 */
350 extern int thrd_detach(thrd_t thr);
351 
352 /** \brief Compare two threads for equality.
353 
354  This function checks the two two thread identifiers passed in to see if they
355  refer to the same thread.
356 
357  \param thr0 The first thread to compare.
358  \param thr1 The second thread to compare.
359  \return 0 if the threads are not equal, nonzero if the
360  threads are equal.
361 */
362 extern int thrd_equal(thrd_t thr0, thrd_t thr1);
363 
364 /** \brief Terminate the current thread immediately.
365 
366  This function terminates the calling thread immediately, setting the return
367  value of the thread to the value specified.
368 
369  \param res The return value of the thread.
370  \note This function will not return.
371 */
372 extern _Noreturn void thrd_exit(int res);
373 
374 /** \brief Join a running thread.
375 
376  This function joins the current thread with the specified thread, blocking
377  until that thread has terminated.
378 
379  \param thr The thread to join with.
380  \param res Pointer to storage for the result code of the other
381  thread. Set to NULL if you don't care about the
382  result value.
383  \retval thrd_success On success.
384  \retval thrd_error If the request cannot be honored.
385 
386  \note Joining with a previously detached thread results in undefined
387  behavior.
388  \note Joining with a thread that has already been joined to another thread
389  results in undefined behavior.
390  \note Calling this function in an interrupt will result in an error being
391  returned.
392 */
393 extern int thrd_join(thrd_t thr, int *res);
394 
395 /** \brief Put the currently running thread to sleep.
396 
397  This function puts the currently running thread to sleep for the specified
398  duration of time, returning any left over time (if interrupted by a signal,
399  for instance) in the second parameter.
400 
401  \param duration The amount of time to sleep.
402  \param remaining Any remaining time from the duration that the thread
403  did not sleep for.
404  \return 0 if the requested time elapsed, a negative value
405  otherwise.
406 
407  \note Although the duration is expressed in seconds and nanoseconds, all
408  sleeping is done in millisecond increments. The value specified will
409  be rounded up if it is not an even number of milliseconds.
410  \note KOS does not support signals, so remaining will only ever have a
411  value after the function if there is some sort of error.
412  \note Calling this function in an interrupt will result in an error being
413  returned.
414 */
415 extern int thrd_sleep(const struct timespec *duration,
416  struct timespec *remaining);
417 
418 /** \brief Yield the current thread's timeslice.
419 
420  This function immediately pauses the current thread's execution and switches
421  to another thread in the ready queue (if there are any threads ready to
422  execute).
423 
424  \note Calling this function in an interrupt will not have any effect.
425 */
426 extern void thrd_yield(void);
427 
428 /** \brief Maximum number of iterations over TSS destructors.
429 
430  This macro defines the maximum number of iterations that will be performed
431  over the destructors for thread-specific storage objects when a thread
432  terminates.
433 */
434 #define TSS_DTOR_ITERATIONS 1
436 /** \brief C11 thread-specific storage type.
437 
438  This type holds a thread-specific storage identifier, which allows a value
439  to be associated with it for each and every thread running.
440 
441  \headerfile threads.h
442 */
443 typedef kthread_key_t tss_t;
445 /** \brief C11 thread-specific storage destructor type.
446 
447  This is a function pointer type which describes a destructor for a
448  thread-specific storage object.
449 
450  \headerfile threads.h
451 */
452 typedef void (*tss_dtor_t)(void *);
454 /** \brief Create a thread-specific storage pointer.
455 
456  This function creates a thread-specific storage pointer and associates the
457  destructor function supplied with it. After creating the pointer, each
458  thread may associate a piece of data with the key.
459 
460  \param key The key to initialize.
461  \param dtor The destructor to associate with the key.
462  \retval thrd_success On success.
463  \retval thrd_error On failure.
464 */
465 extern int tss_create(tss_t *key, tss_dtor_t dtor);
466 
467 /** \brief Free resources associated with a thread-specific storage key.
468 
469  This function releases any resources used by the thread-specific storage
470  key specified. Note that this DOES NOT call any destructors.
471 
472  \param key The key to deinitialize.
473 */
474 extern void tss_delete(tss_t key);
475 
476 /** \brief Retrieve the value associated with a thread-specific storage key.
477 
478  This function retrieves the value associated with the specified
479  thread-specific storage key and returns it to the caller. If no value has
480  been set in the current thread, NULL is returned.
481 
482  \param key The key to look up the value associated with.
483  \return The value associated with the key.
484 */
485 extern void *tss_get(tss_t key);
486 
487 /** \brief Set the value associated with a thread-specific storage key.
488 
489  This function sets the value to be associated with the specified
490  thread-specific storage key, overwriting any previous keys. Note that this
491  DOES NOT call any destructors.
492 
493  \param key The key to set the value for.
494  \param val The value to set.
495  \retval thrd_success On success.
496  \retval thrd_error If the request cannot be honored.
497 */
498 extern int tss_set(tss_t key, void *val);
499 
500 __END_DECLS
501 
502 #endif /* !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 201112L) */
503 
504 #endif /* !__THREADS_H */
Thread-local storage support.
int mtx_trylock(mtx_t *mtx)
Attempt to acquire a mutex lock.
condvar_t cnd_t
C11 condition variable type.
Definition: threads.h:199
Object type backing kthread_once.
Definition: once.h:34
int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts)
Lock a mutex lock with a timeout.
kthread_t * thrd_t
C11 thread identifier type.
Definition: threads.h:298
void mtx_destroy(mtx_t *mtx)
Deinitialize a mutex lock.
int cnd_signal(cnd_t *cond)
Signal one thread locked on a condition variable.
_Noreturn void thrd_exit(int res)
Terminate the current thread immediately.
int thrd_detach(thrd_t thr)
Detach a running thread.
void * tss_get(tss_t key)
Retrieve the value associated with a thread-specific storage key.
kthread_once_t once_flag
Object type backing call_once.
Definition: threads.h:61
int mtx_unlock(mtx_t *mtx)
Unlock a previously acquired lock.
mutex_t mtx_t
C11 mutual exclusion lock type.
Definition: threads.h:84
int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
Put the currently running thread to sleep.
int mtx_lock(mtx_t *mtx)
Lock a mutex lock.
Threading support.
thrd_t thrd_current(void)
Return the identifier of the currently running thread.
Dynamic package initialization.
int thrd_join(thrd_t thr, int *res)
Join a running thread.
int cnd_init(cnd_t *cond)
Initialize a condition variable.
Condition variable.
Definition: cond.h:61
Mutual exclusion lock type.
Definition: mutex.h:70
int thrd_equal(thrd_t thr0, thrd_t thr1)
Compare two threads for equality.
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
Create and start a new thread.
void thrd_yield(void)
Yield the current thread's timeslice.
void(* tss_dtor_t)(void *)
C11 thread-specific storage destructor type.
Definition: threads.h:453
void call_once(once_flag *flag, void(*func)(void))
Call a function one time, no matter how many threads try.
Structure describing one running thread.
Definition: thread.h:90
int tss_set(tss_t key, void *val)
Set the value associated with a thread-specific storage key.
Mutual exclusion locks.
int cnd_wait(cnd_t *cond, mtx_t *mtx)
Wait on a condition variable.
kthread_key_t tss_t
C11 thread-specific storage type.
Definition: threads.h:444
int(* thrd_start_t)(void *)
C11 thread start function type.
Definition: threads.h:307
void cnd_destroy(cnd_t *cond)
Deinitialize a condition variable.
int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts)
Wait on a condition variable (with a timeout).
Condition variables.
int tss_create(tss_t *key, tss_dtor_t dtor)
Create a thread-specific storage pointer.
void tss_delete(tss_t key)
Free resources associated with a thread-specific storage key.
int kthread_key_t
Thread-local storage key type.
Definition: tls.h:27
int cnd_broadcast(cnd_t *cond)
Broadcast to all threads locked on a condition variable.
int mtx_init(mtx_t *mtx, int type)
Initialize a mutex lock.