thread: add generic futex-based muteces
[vlc.git] / include / vlc_threads.h
1 /*****************************************************************************
2  * vlc_threads.h : threads implementation for the VideoLAN client
3  * This header provides portable declarations for mutexes & conditions
4  *****************************************************************************
5  * Copyright (C) 1999, 2002 VLC authors and VideoLAN
6  * Copyright © 2007-2016 Rémi Denis-Courmont
7  *
8  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
9  *          Samuel Hocevar <sam@via.ecp.fr>
10  *          Gildas Bazin <gbazin@netcourrier.com>
11  *          Christophe Massiot <massiot@via.ecp.fr>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU Lesser General Public License as published by
15  * the Free Software Foundation; either version 2.1 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 #ifndef VLC_THREADS_H_
29 #define VLC_THREADS_H_
30
31 #ifndef __cplusplus
32 #include <stdatomic.h>
33 #endif
34
35 /**
36  * \ingroup os
37  * \defgroup thread Threads and synchronization primitives
38  * @{
39  * \file
40  * Thread primitive declarations
41  */
42
43 /**
44  * Issues an explicit deferred cancellation point.
45  *
46  * This has no effects if thread cancellation is disabled.
47  * This can be called when there is a rather slow non-sleeping operation.
48  * This is also used to force a cancellation point in a function that would
49  * otherwise <em>not always</em> be one (block_FifoGet() is an example).
50  */
51 VLC_API void vlc_testcancel(void);
52
53 #if defined (_WIN32)
54 # include <process.h>
55 # ifndef ETIMEDOUT
56 #  define ETIMEDOUT 10060 /* This is the value in winsock.h. */
57 # endif
58
59 typedef struct vlc_thread *vlc_thread_t;
60 # define VLC_THREAD_CANCELED NULL
61
62 typedef unsigned long vlc_osthread_t;
63 #define vlc_thread_equal(a,b) ((a) == (b))
64
65 # define LIBVLC_NEED_SLEEP
66 typedef struct
67 {
68     bool dynamic;
69     union
70     {
71         struct
72         {
73             bool locked;
74             unsigned long contention;
75         };
76         CRITICAL_SECTION mutex;
77     };
78 } vlc_mutex_t;
79 #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
80 #define LIBVLC_DONT_WANT_MUTEX
81 #define LIBVLC_NEED_RWLOCK
82 typedef INIT_ONCE vlc_once_t;
83 #define VLC_STATIC_ONCE INIT_ONCE_STATIC_INIT
84 typedef struct vlc_threadvar *vlc_threadvar_t;
85 typedef struct vlc_timer *vlc_timer_t;
86
87 # define VLC_THREAD_PRIORITY_LOW      0
88 # define VLC_THREAD_PRIORITY_INPUT    THREAD_PRIORITY_ABOVE_NORMAL
89 # define VLC_THREAD_PRIORITY_AUDIO    THREAD_PRIORITY_HIGHEST
90 # define VLC_THREAD_PRIORITY_VIDEO    0
91 # define VLC_THREAD_PRIORITY_OUTPUT   THREAD_PRIORITY_ABOVE_NORMAL
92 # define VLC_THREAD_PRIORITY_HIGHEST  THREAD_PRIORITY_TIME_CRITICAL
93
94 static inline int vlc_poll(struct pollfd *fds, unsigned nfds, int timeout)
95 {
96     int val;
97
98     vlc_testcancel();
99     val = poll(fds, nfds, timeout);
100     if (val < 0)
101         vlc_testcancel();
102     return val;
103 }
104 # define poll(u,n,t) vlc_poll(u, n, t)
105
106 #elif defined (__OS2__)
107 # include <errno.h>
108
109 typedef struct vlc_thread *vlc_thread_t;
110 #define VLC_THREAD_CANCELED NULL
111
112 typedef unsigned long vlc_osthread_t;
113 #define vlc_thread_equal(a,b) ((a) == (b))
114
115 typedef struct
116 {
117     bool dynamic;
118     union
119     {
120         struct
121         {
122             bool locked;
123             unsigned long contention;
124         };
125         HMTX hmtx;
126     };
127 } vlc_mutex_t;
128 #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
129 #define LIBVLC_DONT_WANT_MUTEX
130 #define LIBVLC_NEED_RWLOCK
131 typedef struct
132 {
133     unsigned done;
134     vlc_mutex_t mutex;
135 } vlc_once_t;
136 #define VLC_STATIC_ONCE { 0, VLC_STATIC_MUTEX }
137 typedef struct vlc_threadvar *vlc_threadvar_t;
138 typedef struct vlc_timer *vlc_timer_t;
139
140 # define VLC_THREAD_PRIORITY_LOW      0
141 # define VLC_THREAD_PRIORITY_INPUT \
142                                     MAKESHORT(PRTYD_MAXIMUM / 2, PRTYC_REGULAR)
143 # define VLC_THREAD_PRIORITY_AUDIO    MAKESHORT(PRTYD_MAXIMUM, PRTYC_REGULAR)
144 # define VLC_THREAD_PRIORITY_VIDEO    0
145 # define VLC_THREAD_PRIORITY_OUTPUT \
146                                     MAKESHORT(PRTYD_MAXIMUM / 2, PRTYC_REGULAR)
147 # define VLC_THREAD_PRIORITY_HIGHEST  MAKESHORT(0, PRTYC_TIMECRITICAL)
148
149 # define pthread_sigmask  sigprocmask
150
151 static inline int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
152 {
153     static int (*vlc_poll_os2)(struct pollfd *, unsigned, int) = NULL;
154
155     if (!vlc_poll_os2)
156     {
157         HMODULE hmod;
158         CHAR szFailed[CCHMAXPATH];
159
160         if (DosLoadModule(szFailed, sizeof(szFailed), "vlccore", &hmod))
161             return -1;
162
163         if (DosQueryProcAddr(hmod, 0, "_vlc_poll_os2", (PFN *)&vlc_poll_os2))
164             return -1;
165     }
166
167     return (*vlc_poll_os2)(fds, nfds, timeout);
168 }
169 # define poll(u,n,t) vlc_poll(u, n, t)
170
171 #elif defined (__ANDROID__)      /* pthreads subset without pthread_cancel() */
172 # include <unistd.h>
173 # include <pthread.h>
174 # include <poll.h>
175 # define LIBVLC_USE_PTHREAD_CLEANUP   1
176 # define LIBVLC_NEED_SLEEP
177 # define LIBVLC_NEED_RWLOCK
178
179 typedef struct vlc_thread *vlc_thread_t;
180 #define VLC_THREAD_CANCELED NULL
181 typedef pthread_t vlc_osthread_t;
182 #define vlc_thread_equal(a,b) pthread_equal(a,b)
183 typedef pthread_mutex_t vlc_mutex_t;
184 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
185 #define LIBVLC_DONT_WANT_MUTEX
186 typedef pthread_once_t  vlc_once_t;
187 #define VLC_STATIC_ONCE   PTHREAD_ONCE_INIT
188 typedef pthread_key_t   vlc_threadvar_t;
189 typedef struct vlc_timer *vlc_timer_t;
190
191 # define VLC_THREAD_PRIORITY_LOW      0
192 # define VLC_THREAD_PRIORITY_INPUT    0
193 # define VLC_THREAD_PRIORITY_AUDIO    0
194 # define VLC_THREAD_PRIORITY_VIDEO    0
195 # define VLC_THREAD_PRIORITY_OUTPUT   0
196 # define VLC_THREAD_PRIORITY_HIGHEST  0
197
198 static inline int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
199 {
200     int val;
201
202     do
203     {
204         int ugly_timeout = ((unsigned)timeout >= 50) ? 50 : timeout;
205         if (timeout >= 0)
206             timeout -= ugly_timeout;
207
208         vlc_testcancel ();
209         val = poll (fds, nfds, ugly_timeout);
210     }
211     while (val == 0 && timeout != 0);
212
213     return val;
214 }
215
216 # define poll(u,n,t) vlc_poll(u, n, t)
217
218 #elif defined (__APPLE__)
219 # define _APPLE_C_SOURCE    1 /* Proper pthread semantics on OSX */
220 # include <unistd.h>
221 # include <pthread.h>
222 /* Unnamed POSIX semaphores not supported on Mac OS X */
223 # include <mach/semaphore.h>
224 # include <mach/task.h>
225 # define LIBVLC_USE_PTHREAD_CLEANUP   1
226
227 typedef pthread_t       vlc_thread_t;
228 #define VLC_THREAD_CANCELED PTHREAD_CANCELED
229 typedef pthread_t       vlc_osthread_t;
230 #define vlc_thread_equal(a,b) pthread_equal(a,b)
231 typedef pthread_mutex_t vlc_mutex_t;
232 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
233 #define LIBVLC_DONT_WANT_MUTEX
234 typedef pthread_rwlock_t vlc_rwlock_t;
235 #define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER
236 typedef pthread_once_t  vlc_once_t;
237 #define VLC_STATIC_ONCE   PTHREAD_ONCE_INIT
238 typedef pthread_key_t   vlc_threadvar_t;
239 typedef struct vlc_timer *vlc_timer_t;
240
241 # define VLC_THREAD_PRIORITY_LOW      0
242 # define VLC_THREAD_PRIORITY_INPUT   22
243 # define VLC_THREAD_PRIORITY_AUDIO   22
244 # define VLC_THREAD_PRIORITY_VIDEO    0
245 # define VLC_THREAD_PRIORITY_OUTPUT  22
246 # define VLC_THREAD_PRIORITY_HIGHEST 22
247
248 #else /* POSIX threads */
249 # include <unistd.h> /* _POSIX_SPIN_LOCKS */
250 # include <pthread.h>
251
252 /**
253  * Whether LibVLC threads are based on POSIX threads.
254  */
255 # define LIBVLC_USE_PTHREAD           1
256
257 /**
258  * Whether LibVLC thread cancellation is based on POSIX threads.
259  */
260 # define LIBVLC_USE_PTHREAD_CLEANUP   1
261
262 /**
263  * Thread handle.
264  */
265 typedef struct
266 {
267     pthread_t handle;
268 } vlc_thread_t;
269
270 /**
271  * Return value of a canceled thread.
272  */
273 #define VLC_THREAD_CANCELED PTHREAD_CANCELED
274
275 typedef pthread_t vlc_osthread_t;
276 #define vlc_thread_equal(a,b) pthread_equal(a,b)
277
278 typedef pthread_mutex_t vlc_mutex_t;
279 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
280 #define LIBVLC_DONT_WANT_MUTEX
281
282 /**
283  * Read/write lock.
284  *
285  * Storage space for a slim reader/writer lock.
286  *
287  * \ingroup rwlock
288  */
289 typedef pthread_rwlock_t vlc_rwlock_t;
290
291 /**
292  * Static initializer for (static) read/write lock.
293  *
294  * \ingroup rwlock
295  */
296 #define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER
297
298 /**
299  * One-time initialization.
300  *
301  * A one-time initialization object must always be initialized assigned to
302  * \ref VLC_STATIC_ONCE before use.
303  */
304 typedef pthread_once_t  vlc_once_t;
305
306 /**
307  * Static initializer for one-time initialization.
308  */
309 #define VLC_STATIC_ONCE   PTHREAD_ONCE_INIT
310
311 /**
312  * Thread-local key handle.
313  *
314  * \ingroup threadvar
315  */
316 typedef pthread_key_t   vlc_threadvar_t;
317
318 /**
319  * Threaded timer handle.
320  *
321  * \ingroup timer
322  */
323 typedef struct vlc_timer *vlc_timer_t;
324
325 # define VLC_THREAD_PRIORITY_LOW      0
326 # define VLC_THREAD_PRIORITY_INPUT   10
327 # define VLC_THREAD_PRIORITY_AUDIO    5
328 # define VLC_THREAD_PRIORITY_VIDEO    0
329 # define VLC_THREAD_PRIORITY_OUTPUT  15
330 # define VLC_THREAD_PRIORITY_HIGHEST 20
331
332 #endif
333
334 /**
335  * \defgroup mutex Mutual exclusion locks
336  * @{
337  */
338 #ifndef LIBVLC_DONT_WANT_MUTEX
339 /**
340  * Mutex.
341  *
342  * Storage space for a mutual exclusion lock.
343  */
344 typedef struct
345 {
346     union {
347 #ifndef __cplusplus
348         struct {
349             atomic_uint value;
350             atomic_uint recursion;
351             const void *_Atomic owner;
352         };
353 #endif
354         struct {
355             unsigned int value;
356             unsigned int recursion;
357             const void *owner;
358         } dummy;
359     };
360 } vlc_mutex_t;
361
362 /**
363  * Static initializer for (static) mutex.
364  *
365  * \note This only works in C code.
366  * In C++, consider using a global \ref vlc::threads::mutex instance instead.
367  */
368 #define VLC_STATIC_MUTEX { \
369     .value = ATOMIC_VAR_INIT(0), \
370     .recursion = ATOMIC_VAR_INIT(0), \
371     .owner = ATOMIC_VAR_INIT(NULL), \
372 }
373 #endif
374
375 /**
376  * Initializes a fast mutex.
377  *
378  * Recursive locking of a fast mutex is undefined behaviour. (In debug builds,
379  * recursive locking will cause an assertion failure.)
380  */
381 VLC_API void vlc_mutex_init(vlc_mutex_t *);
382
383 /**
384  * Initializes a recursive mutex.
385  * \warning This is strongly discouraged. Please use normal mutexes.
386  */
387 VLC_API void vlc_mutex_init_recursive(vlc_mutex_t *);
388
389 /**
390  * Deinitializes a mutex.
391  *
392  * The mutex must not be locked, otherwise behaviour is undefined.
393  */
394 VLC_API void vlc_mutex_destroy(vlc_mutex_t *);
395
396 /**
397  * Acquires a mutex.
398  *
399  * If needed, this waits for any other thread to release it.
400  *
401  * \warning Beware of deadlocks when locking multiple mutexes at the same time,
402  * or when using mutexes from callbacks.
403  *
404  * \note This function is not a cancellation point.
405  */
406 VLC_API void vlc_mutex_lock(vlc_mutex_t *);
407
408 /**
409  * Tries to acquire a mutex.
410  *
411  * This function acquires the mutex if and only if it is not currently held by
412  * another thread. This function never sleeps and can be used in delay-critical
413  * code paths.
414  *
415  * \note This function is not a cancellation point.
416  *
417  * \warning If this function fails, then the mutex is held... by another
418  * thread. The calling thread must deal with the error appropriately. That
419  * typically implies postponing the operations that would have required the
420  * mutex. If the thread cannot defer those operations, then it must use
421  * vlc_mutex_lock(). If in doubt, use vlc_mutex_lock() instead.
422  *
423  * @return 0 if the mutex could be acquired, an error code otherwise.
424  */
425 VLC_API int vlc_mutex_trylock( vlc_mutex_t * ) VLC_USED;
426
427 /**
428  * Releases a mutex.
429  *
430  * If the mutex is not held by the calling thread, the behaviour is undefined.
431  *
432  * \note This function is not a cancellation point.
433  */
434 VLC_API void vlc_mutex_unlock(vlc_mutex_t *);
435
436 /**
437  * Checks if a mutex is locked.
438  *
439  * Do not use this function directly. Use vlc_mutex_assert() instead.
440  *
441  * @note
442  * This function has no effects.
443  * It is only meant to be use in run-time assertions.
444  *
445  * @retval false in debug builds of LibVLC,
446  *               if the mutex is not locked by the calling thread;
447  * @retval true in debug builds of LibVLC,
448  *              if the mutex is locked by the calling thread;
449  * @retval true in release builds of LibVLC.
450  */
451 VLC_API bool vlc_mutex_marked(const vlc_mutex_t *) VLC_USED;
452
453 /**
454  * Asserts that a mutex is locked by the calling thread.
455  */
456 #define vlc_mutex_assert(m) assert(vlc_mutex_marked(m))
457
458 /** @} */
459
460 /**
461  * \defgroup condvar Condition variables
462  *
463  * The condition variable is the most common and generic mean for threads to
464  * wait for events triggered by other threads.
465  *
466  * See also POSIX @c pthread_cond_t .
467  * @{
468  */
469
470 struct vlc_cond_waiter;
471
472 /**
473  * Condition variable.
474  *
475  * Storage space for a thread condition variable.
476  */
477 typedef struct
478 {
479     struct vlc_cond_waiter *head;
480     vlc_mutex_t lock;
481 } vlc_cond_t;
482
483 /**
484  * Static initializer for (static) condition variable.
485  *
486  * \note
487  * The condition variable will use the default clock, which is OS-dependent.
488  * Therefore, where timed waits are necessary the condition variable should
489  * always be initialized dynamically explicit instead of using this
490  * initializer.
491  */
492 #define VLC_STATIC_COND { NULL, VLC_STATIC_MUTEX }
493
494 /**
495  * Initializes a condition variable.
496  */
497 VLC_API void vlc_cond_init(vlc_cond_t *);
498
499 /**
500  * Initializes a condition variable (wall clock).
501  *
502  * This function initializes a condition variable for timed waiting using the
503  * UTC wall clock time. The time reference is the same as with time() and with
504  * timespec_get() and TIME_UTC.
505  * vlc_cond_timedwait_daytime() must be instead of
506  * vlc_cond_timedwait() for actual waiting.
507  */
508 void vlc_cond_init_daytime(vlc_cond_t *);
509
510 /**
511  * Deinitializes a condition variable.
512  *
513  * No threads shall be waiting or signaling the condition, otherwise the
514  * behavior is undefined.
515  */
516 VLC_API void vlc_cond_destroy(vlc_cond_t *);
517
518 /**
519  * Wakes up one thread waiting on a condition variable.
520  *
521  * If any thread is currently waiting on the condition variable, at least one
522  * of those threads will be woken up. Otherwise, this function has no effects.
523  *
524  * \note This function is not a cancellation point.
525  */
526 VLC_API void vlc_cond_signal(vlc_cond_t *);
527
528 /**
529  * Wakes up all threads waiting on a condition variable.
530  *
531  * \note This function is not a cancellation point.
532  */
533 VLC_API void vlc_cond_broadcast(vlc_cond_t *);
534
535 /**
536  * Waits on a condition variable.
537  *
538  * The calling thread will be suspended until another thread calls
539  * vlc_cond_signal() or vlc_cond_broadcast() on the same condition variable,
540  * the thread is cancelled with vlc_cancel(), or the system causes a
541  * <em>spurious</em> unsolicited wake-up.
542  *
543  * A mutex is needed to wait on a condition variable. It must <b>not</b> be
544  * a recursive mutex. Although it is possible to use the same mutex for
545  * multiple condition, it is not valid to use different mutexes for the same
546  * condition variable at the same time from different threads.
547  *
548  * The canonical way to use a condition variable to wait for event foobar is:
549  @code
550    vlc_mutex_lock(&lock);
551    mutex_cleanup_push(&lock); // release the mutex in case of cancellation
552
553    while (!foobar)
554        vlc_cond_wait(&wait, &lock);
555
556    // -- foobar is now true, do something about it here --
557
558    vlc_cleanup_pop();
559    vlc_mutex_unlock(&lock);
560   @endcode
561  *
562  * \note This function is a cancellation point. In case of thread cancellation,
563  * the mutex is always locked before cancellation proceeds.
564  *
565  * \param cond condition variable to wait on
566  * \param mutex mutex which is unlocked while waiting,
567  *              then locked again when waking up.
568  */
569 VLC_API void vlc_cond_wait(vlc_cond_t *cond, vlc_mutex_t *mutex);
570
571 /**
572  * Waits on a condition variable up to a certain date.
573  *
574  * This works like vlc_cond_wait() but with an additional time-out.
575  * The time-out is expressed as an absolute timestamp using the same arbitrary
576  * time reference as the vlc_tick_now() and vlc_tick_wait() functions.
577  *
578  * \note This function is a cancellation point. In case of thread cancellation,
579  * the mutex is always locked before cancellation proceeds.
580  *
581  * \param cond condition variable to wait on
582  * \param mutex mutex which is unlocked while waiting,
583  *              then locked again when waking up
584  * \param deadline <b>absolute</b> timeout
585  *
586  * \warning If the variable was initialized with vlc_cond_init_daytime(), or
587  * was statically initialized with \ref VLC_STATIC_COND, the time reference
588  * used by this function is unspecified (depending on the implementation, it
589  * might be the Unix epoch or the vlc_tick_now() clock).
590  *
591  * \return 0 if the condition was signaled, an error code in case of timeout.
592  */
593 VLC_API int vlc_cond_timedwait(vlc_cond_t *cond, vlc_mutex_t *mutex,
594                                vlc_tick_t deadline);
595
596 int vlc_cond_timedwait_daytime(vlc_cond_t *, vlc_mutex_t *, time_t);
597
598 /** @} */
599
600 /**
601  * \defgroup semaphore Semaphores
602  *
603  * The semaphore is the simplest thread synchronization primitive, consisting
604  * of a simple counter.
605  *
606  * See also POSIX @c sem_t .
607  *
608  * @{
609  */
610 /**
611  * Semaphore.
612  *
613  * Storage space for a thread-safe semaphore.
614  */
615 typedef struct
616 {
617     union {
618 #ifndef __cplusplus
619         atomic_uint value;
620 #endif
621         int dummy;
622    };
623 } vlc_sem_t;
624
625 /**
626  * Initializes a semaphore.
627  *
628  * @param count initial semaphore value (typically 0)
629  */
630 VLC_API void vlc_sem_init(vlc_sem_t *, unsigned count);
631
632 /**
633  * Increments the value of a semaphore.
634  *
635  * \note This function is not a cancellation point.
636  *
637  * \return 0 on success, EOVERFLOW in case of integer overflow.
638  */
639 VLC_API int vlc_sem_post(vlc_sem_t *);
640
641 /**
642  * Waits on a semaphore.
643  *
644  * This function atomically waits for the semaphore to become non-zero then
645  * decrements it, and returns. If the semaphore is non-zero on entry, it is
646  * immediately decremented.
647  *
648  * \note This function may be a point of cancellation.
649  */
650 VLC_API void vlc_sem_wait(vlc_sem_t *);
651
652 /**
653  * Waits on a semaphore within a deadline.
654  *
655  * This function waits for the semaphore just like vlc_sem_wait(), but only
656  * up to a given deadline.
657  *
658  * \param sem semaphore to wait for
659  * \param deadline deadline to wait until
660  *
661  * \retval 0 the semaphore was decremented
662  * \retval ETIMEDOUT the deadline was reached
663  */
664 VLC_API int vlc_sem_timedwait(vlc_sem_t *sem, vlc_tick_t deadline) VLC_USED;
665
666 /** @} */
667
668 /**
669  * \defgroup rwlock Read/write locks
670  *
671  * Read/write locks are a type of thread synchronization primitive meant to
672  * protect access to data that is mostly read, and rarely written.
673  * As long as no threads tries to acquire the lock for "writing", any number of
674  * threads can acquire the lock for "reading".
675  *
676  * See also POSIX @c pthread_rwlock_t .
677  *
678  * @{
679  */
680
681 #ifdef LIBVLC_NEED_RWLOCK
682 typedef struct vlc_rwlock
683 {
684     vlc_mutex_t   mutex;
685     vlc_cond_t    wait;
686     long          state;
687 } vlc_rwlock_t;
688 # define VLC_STATIC_RWLOCK { VLC_STATIC_MUTEX, VLC_STATIC_COND, 0 }
689 #endif
690
691 /**
692  * Initializes a read/write lock.
693  *
694  * After use, a read/write lock must be deinitialized with
695  * vlc_rwlock_destroy().
696  */
697 VLC_API void vlc_rwlock_init(vlc_rwlock_t *);
698
699 /**
700  * Destroys an initialized unused read/write lock.
701  */
702 VLC_API void vlc_rwlock_destroy(vlc_rwlock_t *);
703
704 /**
705  * Acquires a read/write lock for reading.
706  *
707  * \note Recursion is allowed.
708  * \note This function may be a point of cancellation.
709  */
710 VLC_API void vlc_rwlock_rdlock(vlc_rwlock_t *);
711
712 /**
713  * Acquires a read/write lock for writing. Recursion is not allowed.
714  * \note This function may be a point of cancellation.
715  */
716 VLC_API void vlc_rwlock_wrlock(vlc_rwlock_t *);
717
718 /**
719  * Releases a read/write lock.
720  *
721  * The calling thread must hold the lock. Otherwise behaviour is undefined.
722  *
723  * \note This function is not a cancellation point.
724  */
725 VLC_API void vlc_rwlock_unlock(vlc_rwlock_t *);
726
727 /** @} */
728
729 /**
730  * Executes a function one time.
731  *
732  * The first time this function is called with a given one-time initialization
733  * object, it executes the provided callback.
734  * Any further call with the same object will be a no-op.
735  *
736  * In the corner case that the first time execution is ongoing in another
737  * thread, then the function will wait for completion on the other thread
738  * (and then synchronize memory) before it returns.
739  * This ensures that, no matter what, the callback has been executed exactly
740  * once and its side effects are visible after the function returns.
741  *
742  * \param once a one-time initialization object
743  * \param cb callback to execute (the first time)
744  */
745 VLC_API void vlc_once(vlc_once_t *restrict once, void (*cb)(void));
746
747 /**
748  * \defgroup threadvar Thread-specific variables
749  * @{
750  */
751 /**
752  * Allocates a thread-specific variable.
753  *
754  * @param key where to store the thread-specific variable handle
755  * @param destr a destruction callback. It is called whenever a thread exits
756  * and the thread-specific variable has a non-NULL value.
757  *
758  * @return 0 on success, a system error code otherwise.
759  * This function can actually fail: on most systems, there is a fixed limit to
760  * the number of thread-specific variables in a given process.
761  */
762 VLC_API int vlc_threadvar_create(vlc_threadvar_t *key, void (*destr) (void *));
763
764 /**
765  * Deallocates a thread-specific variable.
766  */
767 VLC_API void vlc_threadvar_delete(vlc_threadvar_t *);
768
769 /**
770  * Sets a thread-specific variable.
771
772  * \param key thread-local variable key (created with vlc_threadvar_create())
773  * \param value new value for the variable for the calling thread
774  * \return 0 on success, a system error code otherwise.
775  */
776 VLC_API int vlc_threadvar_set(vlc_threadvar_t key, void *value);
777
778 /**
779  * Gets the value of a thread-local variable for the calling thread.
780  * This function cannot fail.
781  *
782  * \return the value associated with the given variable for the calling
783  * or NULL if no value was set.
784  */
785 VLC_API void *vlc_threadvar_get(vlc_threadvar_t);
786
787 /** @} */
788
789 /**
790  * Waits on an address.
791  *
792  * Puts the calling thread to sleep if a specific unsigned 32-bits value is
793  * stored at a specified address. The thread will sleep until it is woken up by
794  * a call to vlc_atomic_notify_one() or vlc_atomic_notify_all() in another
795  * thread, or spuriously.
796  *
797  * If the value does not match, do nothing and return immediately.
798  *
799  * \param addr address to check for
800  * \param val value to match at the address
801  */
802 void vlc_atomic_wait(void *addr, unsigned val);
803
804 /**
805  * Waits on an address with a time-out.
806  *
807  * This function operates as vlc_atomic_wait() but provides an additional
808  * time-out. If the deadline is reached, the thread resumes and the function
809  * returns.
810  *
811  * \param addr address to check for
812  * \param val value to match at the address
813  * \param deadline deadline to wait until
814  *
815  * \retval 0 the function was woken up before the time-out
816  * \retval ETIMEDOUT the deadline was reached
817  */
818 int vlc_atomic_timedwait(void *addr, unsigned val, vlc_tick_t deadline);
819
820 int vlc_atomic_timedwait_daytime(void *addr, unsigned val, time_t deadline);
821
822 /**
823  * Wakes up one thread on an address.
824  *
825  * Wakes up (at least) one of the thread sleeping on the specified address.
826  * The address must be equal to the first parameter given by at least one
827  * thread sleeping within the vlc_atomic_wait() or vlc_atomic_timedwait()
828  * functions. If no threads are found, this function does nothing.
829  *
830  * \param addr address identifying which threads may be woken up
831  */
832 void vlc_atomic_notify_one(void *addr);
833
834 /**
835  * Wakes up all thread on an address.
836  *
837  * Wakes up all threads sleeping on the specified address (if any).
838  * Any thread sleeping within a call to vlc_atomic_wait() or
839  * vlc_atomic_timedwait() with the specified address as first call parameter
840  * will be woken up.
841  *
842  * \param addr address identifying which threads to wake up
843  */
844 void vlc_atomic_notify_all(void *addr);
845
846 /**
847  * Creates and starts a new thread.
848  *
849  * The thread must be <i>joined</i> with vlc_join() to reclaim resources
850  * when it is not needed anymore.
851  *
852  * @param th storage space for the handle of the new thread (cannot be NULL)
853  *           [OUT]
854  * @param entry entry point for the thread
855  * @param data data parameter given to the entry point
856  * @param priority thread priority value
857  * @return 0 on success, a standard error code on error.
858  * @note In case of error, the value of *th is undefined.
859  */
860 VLC_API int vlc_clone(vlc_thread_t *th, void *(*entry)(void *), void *data,
861                       int priority) VLC_USED;
862
863 /**
864  * Marks a thread as cancelled.
865  *
866  * Next time the target thread reaches a cancellation point (while not having
867  * disabled cancellation), it will run its cancellation cleanup handler, the
868  * thread variable destructors, and terminate.
869  *
870  * vlc_join() must be used regardless of a thread being cancelled or not, to
871  * avoid leaking resources.
872  */
873 VLC_API void vlc_cancel(vlc_thread_t);
874
875 /**
876  * Waits for a thread to complete (if needed), then destroys it.
877  *
878  * \note This is a cancellation point. In case of cancellation, the thread is
879  * <b>not</b> joined.
880
881  * \warning A thread cannot join itself (normally VLC will abort if this is
882  * attempted). Also a detached thread <b>cannot</b> be joined.
883  *
884  * @param th thread handle
885  * @param result [OUT] pointer to write the thread return value or NULL
886  */
887 VLC_API void vlc_join(vlc_thread_t th, void **result);
888
889 /**
890  * Disables thread cancellation.
891  *
892  * This functions saves the current cancellation state (enabled or disabled),
893  * then disables cancellation for the calling thread. It must be called before
894  * entering a piece of code that is not cancellation-safe, unless it can be
895  * proven that the calling thread will not be cancelled.
896  *
897  * \note This function is not a cancellation point.
898  *
899  * \return Previous cancellation state (opaque value for vlc_restorecancel()).
900  */
901 VLC_API int vlc_savecancel(void);
902
903 /**
904  * Restores the cancellation state.
905  *
906  * This function restores the cancellation state of the calling thread to
907  * a state previously saved by vlc_savecancel().
908  *
909  * \note This function is not a cancellation point.
910  *
911  * \param state previous state as returned by vlc_savecancel().
912  */
913 VLC_API void vlc_restorecancel(int state);
914
915 typedef struct vlc_cleanup_t vlc_cleanup_t;
916
917 /**
918  * Internal handler for thread cancellation.
919  *
920  * Do not call this function directly. Use wrapper macros instead:
921  * vlc_cleanup_push(), vlc_cleanup_pop().
922  */
923 VLC_API void vlc_control_cancel(vlc_cleanup_t *);
924
925 /**
926  * Thread handle.
927  *
928  * This function returns the thread handle of the calling thread.
929  * This works even if the thread was <b>not</b> created with vlc_clone().
930  * As a consequence, depending on the platform, this might or might not be the
931  * same as the @ref vlc_thread_t thread handle returned by vlc_clone().
932  *
933  * Also depending on the platform, this might be an integer type, a pointer
934  * type, or a compound type of any (reasonable) size. To compare two thread
935  * handles, use the vlc_thread_equal() macro, not a hand-coded comparison.
936  * Comparing the calling thread for equality with another thread is in fact
937  * pretty much the only purpose of this function.
938  *
939  * \note If you need an integer identifier, use vlc_thread_id() instead.
940  *
941  * \return the OS run-time thread handle
942  */
943 VLC_API vlc_osthread_t vlc_thread_self(void) VLC_USED;
944
945 /**
946  * Thread identifier.
947  *
948  * This function returns the identifier of the calling thread. The identifier
949  * cannot change for the entire duration of the thread, and no other thread can
950  * have the same identifier at the same time in the same process. Typically,
951  * the identifier is also unique across all running threads of all existing
952  * processes, but that depends on the operating system.
953  *
954  * There are no particular semantics to the thread ID with LibVLC.
955  * It is provided mainly for tracing and debugging.
956  *
957  * See also vlc_thread_self().
958  *
959  * \warning This function is not currently implemented on all supported
960  * platforms. Where not implemented, it returns (unsigned long)-1.
961  *
962  * \return the thread identifier (or -1 if unimplemented)
963  */
964 VLC_API unsigned long vlc_thread_id(void) VLC_USED;
965
966 /**
967  * Precision monotonic clock.
968  *
969  * In principles, the clock has a precision of 1 MHz. But the actual resolution
970  * may be much lower, especially when it comes to sleeping with vlc_tick_wait() or
971  * vlc_tick_sleep(). Most general-purpose operating systems provide a resolution of
972  * only 100 to 1000 Hz.
973  *
974  * \warning The origin date (time value "zero") is not specified. It is
975  * typically the time the kernel started, but this is platform-dependent.
976  * If you need wall clock time, use gettimeofday() instead.
977  *
978  * \return a timestamp in microseconds.
979  */
980 VLC_API vlc_tick_t vlc_tick_now(void);
981
982 /**
983  * Waits until a deadline.
984  *
985  * \param deadline timestamp to wait for (\ref vlc_tick_now())
986  *
987  * \note The deadline may be exceeded due to OS scheduling.
988  * \note This function is a cancellation point.
989  */
990 VLC_API void vlc_tick_wait(vlc_tick_t deadline);
991
992 /**
993  * Waits for an interval of time.
994  *
995  * \param delay how long to wait (in microseconds)
996  *
997  * \note The delay may be exceeded due to OS scheduling.
998  * \note This function is a cancellation point.
999  */
1000 VLC_API void vlc_tick_sleep(vlc_tick_t delay);
1001
1002 #define VLC_HARD_MIN_SLEEP  VLC_TICK_FROM_MS(10)   /* 10 milliseconds = 1 tick at 100Hz */
1003 #define VLC_SOFT_MIN_SLEEP  VLC_TICK_FROM_SEC(9)   /* 9 seconds */
1004
1005 #if defined (__GNUC__) && !defined (__clang__)
1006 /* Linux has 100, 250, 300 or 1000Hz
1007  *
1008  * HZ=100 by default on FreeBSD, but some architectures use a 1000Hz timer
1009  */
1010
1011 static
1012 __attribute__((unused))
1013 __attribute__((noinline))
1014 __attribute__((error("sorry, cannot sleep for such short a time")))
1015 vlc_tick_t impossible_delay( vlc_tick_t delay )
1016 {
1017     (void) delay;
1018     return VLC_HARD_MIN_SLEEP;
1019 }
1020
1021 static
1022 __attribute__((unused))
1023 __attribute__((noinline))
1024 __attribute__((warning("use proper event handling instead of short delay")))
1025 vlc_tick_t harmful_delay( vlc_tick_t delay )
1026 {
1027     return delay;
1028 }
1029
1030 # define check_delay( d ) \
1031     ((__builtin_constant_p(d < VLC_HARD_MIN_SLEEP) \
1032    && (d < VLC_HARD_MIN_SLEEP)) \
1033        ? impossible_delay(d) \
1034        : ((__builtin_constant_p(d < VLC_SOFT_MIN_SLEEP) \
1035        && (d < VLC_SOFT_MIN_SLEEP)) \
1036            ? harmful_delay(d) \
1037            : d))
1038
1039 static
1040 __attribute__((unused))
1041 __attribute__((noinline))
1042 __attribute__((error("deadlines can not be constant")))
1043 vlc_tick_t impossible_deadline( vlc_tick_t deadline )
1044 {
1045     return deadline;
1046 }
1047
1048 # define check_deadline( d ) \
1049     (__builtin_constant_p(d) ? impossible_deadline(d) : d)
1050 #else
1051 # define check_delay(d) (d)
1052 # define check_deadline(d) (d)
1053 #endif
1054
1055 #define vlc_tick_sleep(d) vlc_tick_sleep(check_delay(d))
1056 #define vlc_tick_wait(d) vlc_tick_wait(check_deadline(d))
1057
1058 /**
1059  * \defgroup timer Asynchronous/threaded timers
1060  * @{
1061  */
1062 /**
1063  * Initializes an asynchronous timer.
1064  *
1065  * \param id pointer to timer to be initialized
1066  * \param func function that the timer will call
1067  * \param data parameter for the timer function
1068  * \return 0 on success, a system error code otherwise.
1069  *
1070  * \warning Asynchronous timers are processed from an unspecified thread.
1071  * \note Multiple occurrences of a single interval timer are serialized:
1072  * they cannot run concurrently.
1073  */
1074 VLC_API int vlc_timer_create(vlc_timer_t *id, void (*func)(void *), void *data)
1075 VLC_USED;
1076
1077 /**
1078  * Destroys an initialized timer.
1079  *
1080  * If needed, the timer is first disarmed. Behaviour is undefined if the
1081  * specified timer is not initialized.
1082  *
1083  * \warning This function <b>must</b> be called before the timer data can be
1084  * freed and before the timer callback function can be unmapped/unloaded.
1085  *
1086  * \param timer timer to destroy
1087  */
1088 VLC_API void vlc_timer_destroy(vlc_timer_t timer);
1089
1090 #define VLC_TIMER_DISARM    (0)
1091 #define VLC_TIMER_FIRE_ONCE (0)
1092
1093 /**
1094  * Arms or disarms an initialized timer.
1095  *
1096  * This functions overrides any previous call to itself.
1097  *
1098  * \note A timer can fire later than requested due to system scheduling
1099  * limitations. An interval timer can fail to trigger sometimes, either because
1100  * the system is busy or suspended, or because a previous iteration of the
1101  * timer is still running. See also vlc_timer_getoverrun().
1102  *
1103  * \param timer initialized timer
1104  * \param absolute the timer value origin is the same as vlc_tick_now() if true,
1105  *                 the timer value is relative to now if false.
1106  * \param value zero to disarm the timer, otherwise the initial time to wait
1107  *              before firing the timer.
1108  * \param interval zero to fire the timer just once, otherwise the timer
1109  *                 repetition interval.
1110  */
1111 VLC_API void vlc_timer_schedule(vlc_timer_t timer, bool absolute,
1112                                 vlc_tick_t value, vlc_tick_t interval);
1113
1114 static inline void vlc_timer_disarm(vlc_timer_t timer)
1115 {
1116     vlc_timer_schedule( timer, false, VLC_TIMER_DISARM, 0 );
1117 }
1118
1119 static inline void vlc_timer_schedule_asap(vlc_timer_t timer, vlc_tick_t interval)
1120 {
1121     vlc_timer_schedule(timer, false, 1, interval);
1122 }
1123
1124 /**
1125  * Fetches and resets the overrun counter for a timer.
1126  *
1127  * This functions returns the number of times that the interval timer should
1128  * have fired, but the callback was not invoked due to scheduling problems.
1129  * The call resets the counter to zero.
1130  *
1131  * \param timer initialized timer
1132  * \return the timer overrun counter (typically zero)
1133  */
1134 VLC_API unsigned vlc_timer_getoverrun(vlc_timer_t) VLC_USED;
1135
1136 /** @} */
1137
1138 /**
1139  * Count CPUs.
1140  *
1141  * \return number of available (logical) CPUs.
1142  */
1143 VLC_API unsigned vlc_GetCPUCount(void);
1144
1145 #if defined (LIBVLC_USE_PTHREAD_CLEANUP)
1146 /**
1147  * Registers a thread cancellation handler.
1148  *
1149  * This pushes a function to run if the thread is cancelled (or otherwise
1150  * exits prematurely).
1151  *
1152  * If multiple procedures are registered,
1153  * they are handled in last-in first-out order.
1154  *
1155  * \note Any call to vlc_cleanup_push() <b>must</b> paired with a call to
1156  * vlc_cleanup_pop().
1157  * \warning Branching into or out of the block between these two function calls
1158  * is not allowed (read: it will likely crash the whole process).
1159  *
1160  * \param routine procedure to call if the thread ends
1161  * \param arg argument for the procedure
1162  */
1163 # define vlc_cleanup_push( routine, arg ) pthread_cleanup_push (routine, arg)
1164
1165 /**
1166  * Unregisters the last cancellation handler.
1167  *
1168  * This pops the cancellation handler that was last pushed with
1169  * vlc_cleanup_push() in the calling thread.
1170  */
1171 # define vlc_cleanup_pop( ) pthread_cleanup_pop (0)
1172
1173 #else /* !LIBVLC_USE_PTHREAD_CLEANUP */
1174 struct vlc_cleanup_t
1175 {
1176     vlc_cleanup_t *next;
1177     void         (*proc) (void *);
1178     void          *data;
1179 };
1180
1181 # ifndef __cplusplus
1182 /* This macros opens a code block on purpose: It reduces the chance of
1183  * not pairing the push and pop. It also matches the POSIX Thread internals.
1184  * That way, Win32 developers will not accidentally break other platforms.
1185  */
1186 # define vlc_cleanup_push( routine, arg ) \
1187     do { \
1188         vlc_control_cancel(&(vlc_cleanup_t){ NULL, routine, arg })
1189
1190 #  define vlc_cleanup_pop( ) \
1191         vlc_control_cancel (NULL); \
1192     } while (0)
1193 # else
1194 #  define vlc_cleanup_push(routine, arg) \
1195     static_assert(false, "don't use vlc_cleanup_push in portable C++ code")
1196 #  define vlc_cleanup_pop() \
1197     static_assert(false, "don't use vlc_cleanup_pop in portable C++ code")
1198 # endif
1199
1200 #endif /* !LIBVLC_USE_PTHREAD_CLEANUP */
1201
1202 static inline void vlc_cleanup_lock (void *lock)
1203 {
1204     vlc_mutex_unlock ((vlc_mutex_t *)lock);
1205 }
1206 #define mutex_cleanup_push( lock ) vlc_cleanup_push (vlc_cleanup_lock, lock)
1207
1208 #ifndef __cplusplus
1209 void vlc_cancel_addr_set(atomic_uint *addr);
1210 void vlc_cancel_addr_clear(atomic_uint *addr);
1211 #else
1212 /**
1213  * Helper C++ class to lock a mutex.
1214  *
1215  * The mutex is locked when the object is created, and unlocked when the object
1216  * is destroyed.
1217  */
1218 class vlc_mutex_locker
1219 {
1220     private:
1221         vlc_mutex_t *lock;
1222     public:
1223         vlc_mutex_locker (vlc_mutex_t *m) : lock (m)
1224         {
1225             vlc_mutex_lock (lock);
1226         }
1227
1228         ~vlc_mutex_locker (void)
1229         {
1230             vlc_mutex_unlock (lock);
1231         }
1232 };
1233
1234 #endif
1235
1236 enum
1237 {
1238    VLC_AVCODEC_MUTEX = 0,
1239    VLC_GCRYPT_MUTEX,
1240    VLC_XLIB_MUTEX,
1241    VLC_MOSAIC_MUTEX,
1242 #ifdef _WIN32
1243    VLC_MTA_MUTEX,
1244 #endif
1245    /* Insert new entry HERE */
1246    VLC_MAX_MUTEX
1247 };
1248
1249 /**
1250  * Internal handler for global mutexes.
1251  *
1252  * Do not use this function directly. Use helper macros instead:
1253  * vlc_global_lock(), vlc_global_unlock().
1254  */
1255 VLC_API void vlc_global_mutex(unsigned, bool);
1256
1257 /**
1258  * Acquires a global mutex.
1259  */
1260 #define vlc_global_lock( n ) vlc_global_mutex(n, true)
1261
1262 /**
1263  * Releases a global mutex.
1264  */
1265 #define vlc_global_unlock( n ) vlc_global_mutex(n, false)
1266
1267 /** @} */
1268
1269 #endif /* !_VLC_THREADS_H */