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