]> git.sesse.net Git - vlc/blob - src/misc/pthread.c
update.c: ifdef some win32 specific code
[vlc] / src / misc / pthread.c
1 /*****************************************************************************
2  * pthread.c : pthread back-end for LibVLC
3  *****************************************************************************
4  * Copyright (C) 1999-2009 the VideoLAN team
5  *
6  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
7  *          Samuel Hocevar <sam@zoy.org>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *          Clément Sténac
10  *          Rémi Denis-Courmont
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32
33 #include "libvlc.h"
34 #include <stdarg.h>
35 #include <assert.h>
36 #include <unistd.h> /* fsync() */
37 #include <signal.h>
38 #include <errno.h>
39
40 #include <sched.h>
41 #ifdef __linux__
42 # include <sys/syscall.h> /* SYS_gettid */
43 #endif
44
45 #ifdef HAVE_EXECINFO_H
46 # include <execinfo.h>
47 #endif
48
49 #ifdef __APPLE__
50 # include <sys/time.h> /* gettimeofday in vlc_cond_timedwait */
51 #endif
52
53 /**
54  * Print a backtrace to the standard error for debugging purpose.
55  */
56 void vlc_trace (const char *fn, const char *file, unsigned line)
57 {
58      fprintf (stderr, "at %s:%u in %s\n", file, line, fn);
59      fflush (stderr); /* needed before switch to low-level I/O */
60 #ifdef HAVE_BACKTRACE
61      void *stack[20];
62      int len = backtrace (stack, sizeof (stack) / sizeof (stack[0]));
63      backtrace_symbols_fd (stack, len, 2);
64 #endif
65      fsync (2);
66 }
67
68 static inline unsigned long vlc_threadid (void)
69 {
70 #if defined (__linux__)
71      /* glibc does not provide a call for this */
72      return syscall (SYS_gettid);
73
74 #else
75      union { pthread_t th; unsigned long int i; } v = { };
76      v.th = pthread_self ();
77      return v.i;
78
79 #endif
80 }
81
82 #ifndef NDEBUG
83 /*****************************************************************************
84  * vlc_thread_fatal: Report an error from the threading layer
85  *****************************************************************************
86  * This is mostly meant for debugging.
87  *****************************************************************************/
88 static void
89 vlc_thread_fatal (const char *action, int error,
90                   const char *function, const char *file, unsigned line)
91 {
92     int canc = vlc_savecancel ();
93     fprintf (stderr, "LibVLC fatal error %s (%d) in thread %lu ",
94              action, error, vlc_threadid ());
95     vlc_trace (function, file, line);
96
97     /* Sometimes strerror_r() crashes too, so make sure we print an error
98      * message before we invoke it */
99 #ifdef __GLIBC__
100     /* Avoid the strerror_r() prototype brain damage in glibc */
101     errno = error;
102     fprintf (stderr, " Error message: %m\n");
103 #else
104     char buf[1000];
105     const char *msg;
106
107     switch (strerror_r (error, buf, sizeof (buf)))
108     {
109         case 0:
110             msg = buf;
111             break;
112         case ERANGE: /* should never happen */
113             msg = "unknwon (too big to display)";
114             break;
115         default:
116             msg = "unknown (invalid error number)";
117             break;
118     }
119     fprintf (stderr, " Error message: %s\n", msg);
120 #endif
121     fflush (stderr);
122
123     vlc_restorecancel (canc);
124     abort ();
125 }
126
127 # define VLC_THREAD_ASSERT( action ) \
128     if (unlikely(val)) \
129         vlc_thread_fatal (action, val, __func__, __FILE__, __LINE__)
130 #else
131 # define VLC_THREAD_ASSERT( action ) ((void)val)
132 #endif
133
134 #if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6)
135 /* This is not prototyped under glibc, though it exists. */
136 int pthread_mutexattr_setkind_np( pthread_mutexattr_t *attr, int kind );
137 #endif
138
139 /*****************************************************************************
140  * vlc_mutex_init: initialize a mutex
141  *****************************************************************************/
142 void vlc_mutex_init( vlc_mutex_t *p_mutex )
143 {
144     pthread_mutexattr_t attr;
145
146     if (unlikely(pthread_mutexattr_init (&attr)))
147         abort();
148 #ifdef NDEBUG
149     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_NORMAL );
150 #else
151     /* Create error-checking mutex to detect problems more easily. */
152 # if defined (__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 6)
153     pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
154 # else
155     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK );
156 # endif
157 #endif
158     if (unlikely(pthread_mutex_init (p_mutex, &attr)))
159         abort();
160     pthread_mutexattr_destroy( &attr );
161 }
162
163 /*****************************************************************************
164  * vlc_mutex_init: initialize a recursive mutex (Do not use)
165  *****************************************************************************/
166 void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
167 {
168     pthread_mutexattr_t attr;
169
170     if (unlikely(pthread_mutexattr_init (&attr)))
171         abort();
172 #if defined (__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 6)
173     pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
174 #else
175     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
176 #endif
177     if (unlikely(pthread_mutex_init (p_mutex, &attr)))
178         abort();
179     pthread_mutexattr_destroy( &attr );
180 }
181
182
183 /**
184  * Destroys a mutex. The mutex must not be locked.
185  *
186  * @param p_mutex mutex to destroy
187  * @return always succeeds
188  */
189 void vlc_mutex_destroy (vlc_mutex_t *p_mutex)
190 {
191     int val = pthread_mutex_destroy( p_mutex );
192     VLC_THREAD_ASSERT ("destroying mutex");
193 }
194
195 #ifndef NDEBUG
196 # ifdef HAVE_VALGRIND_VALGRIND_H
197 #  include <valgrind/valgrind.h>
198 # else
199 #  define RUNNING_ON_VALGRIND (0)
200 # endif
201
202 void vlc_assert_locked (vlc_mutex_t *p_mutex)
203 {
204     if (RUNNING_ON_VALGRIND > 0)
205         return;
206     assert (pthread_mutex_lock (p_mutex) == EDEADLK);
207 }
208 #endif
209
210 /**
211  * Acquires a mutex. If needed, waits for any other thread to release it.
212  * Beware of deadlocks when locking multiple mutexes at the same time,
213  * or when using mutexes from callbacks.
214  * This function is not a cancellation-point.
215  *
216  * @param p_mutex mutex initialized with vlc_mutex_init() or
217  *                vlc_mutex_init_recursive()
218  */
219 void vlc_mutex_lock (vlc_mutex_t *p_mutex)
220 {
221     int val = pthread_mutex_lock( p_mutex );
222     VLC_THREAD_ASSERT ("locking mutex");
223 }
224
225 /**
226  * Acquires a mutex if and only if it is not currently held by another thread.
227  * This function never sleeps and can be used in delay-critical code paths.
228  * This function is not a cancellation-point.
229  *
230  * <b>Beware</b>: If this function fails, then the mutex is held... by another
231  * thread. The calling thread must deal with the error appropriately. That
232  * typically implies postponing the operations that would have required the
233  * mutex. If the thread cannot defer those operations, then it must use
234  * vlc_mutex_lock(). If in doubt, use vlc_mutex_lock() instead.
235  *
236  * @param p_mutex mutex initialized with vlc_mutex_init() or
237  *                vlc_mutex_init_recursive()
238  * @return 0 if the mutex could be acquired, an error code otherwise.
239  */
240 int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
241 {
242     int val = pthread_mutex_trylock( p_mutex );
243
244     if (val != EBUSY)
245         VLC_THREAD_ASSERT ("locking mutex");
246     return val;
247 }
248
249 /**
250  * Releases a mutex (or crashes if the mutex is not locked by the caller).
251  * @param p_mutex mutex locked with vlc_mutex_lock().
252  */
253 void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
254 {
255     int val = pthread_mutex_unlock( p_mutex );
256     VLC_THREAD_ASSERT ("unlocking mutex");
257 }
258
259 /**
260  * Initializes a condition variable.
261  */
262 void vlc_cond_init (vlc_cond_t *p_condvar)
263 {
264     pthread_condattr_t attr;
265
266     if (unlikely(pthread_condattr_init (&attr)))
267         abort ();
268 #if !defined (_POSIX_CLOCK_SELECTION)
269    /* Fairly outdated POSIX support (that was defined in 2001) */
270 # define _POSIX_CLOCK_SELECTION (-1)
271 #endif
272 #if (_POSIX_CLOCK_SELECTION >= 0)
273     /* NOTE: This must be the same clock as the one in mtime.c */
274     pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);
275 #endif
276
277     if (unlikely(pthread_cond_init (p_condvar, &attr)))
278         abort ();
279     pthread_condattr_destroy (&attr);
280 }
281
282 /**
283  * Initializes a condition variable.
284  * Contrary to vlc_cond_init(), the wall clock will be used as a reference for
285  * the vlc_cond_timedwait() time-out parameter.
286  */
287 void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
288 {
289     if (unlikely(pthread_cond_init (p_condvar, NULL)))
290         abort ();
291 }
292
293 /**
294  * Destroys a condition variable. No threads shall be waiting or signaling the
295  * condition.
296  * @param p_condvar condition variable to destroy
297  */
298 void vlc_cond_destroy (vlc_cond_t *p_condvar)
299 {
300     int val = pthread_cond_destroy( p_condvar );
301     VLC_THREAD_ASSERT ("destroying condition");
302 }
303
304 /**
305  * Wakes up one thread waiting on a condition variable, if any.
306  * @param p_condvar condition variable
307  */
308 void vlc_cond_signal (vlc_cond_t *p_condvar)
309 {
310     int val = pthread_cond_signal( p_condvar );
311     VLC_THREAD_ASSERT ("signaling condition variable");
312 }
313
314 /**
315  * Wakes up all threads (if any) waiting on a condition variable.
316  * @param p_cond condition variable
317  */
318 void vlc_cond_broadcast (vlc_cond_t *p_condvar)
319 {
320     pthread_cond_broadcast (p_condvar);
321 }
322
323 /**
324  * Waits for a condition variable. The calling thread will be suspended until
325  * another thread calls vlc_cond_signal() or vlc_cond_broadcast() on the same
326  * condition variable, the thread is cancelled with vlc_cancel(), or the
327  * system causes a "spurious" unsolicited wake-up.
328  *
329  * A mutex is needed to wait on a condition variable. It must <b>not</b> be
330  * a recursive mutex. Although it is possible to use the same mutex for
331  * multiple condition, it is not valid to use different mutexes for the same
332  * condition variable at the same time from different threads.
333  *
334  * In case of thread cancellation, the mutex is always locked before
335  * cancellation proceeds.
336  *
337  * The canonical way to use a condition variable to wait for event foobar is:
338  @code
339    vlc_mutex_lock (&lock);
340    mutex_cleanup_push (&lock); // release the mutex in case of cancellation
341
342    while (!foobar)
343        vlc_cond_wait (&wait, &lock);
344
345    --- foobar is now true, do something about it here --
346
347    vlc_cleanup_run (); // release the mutex
348   @endcode
349  *
350  * @param p_condvar condition variable to wait on
351  * @param p_mutex mutex which is unlocked while waiting,
352  *                then locked again when waking up.
353  * @param deadline <b>absolute</b> timeout
354  *
355  * @return 0 if the condition was signaled, an error code in case of timeout.
356  */
357 void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
358 {
359     int val = pthread_cond_wait( p_condvar, p_mutex );
360     VLC_THREAD_ASSERT ("waiting on condition");
361 }
362
363 /**
364  * Waits for a condition variable up to a certain date.
365  * This works like vlc_cond_wait(), except for the additional time-out.
366  *
367  * If the variable was initialized with vlc_cond_init(), the timeout has the
368  * same arbitrary origin as mdate(). If the variable was initialized with
369  * vlc_cond_init_daytime(), the timeout is expressed from the Unix epoch.
370  *
371  * @param p_condvar condition variable to wait on
372  * @param p_mutex mutex which is unlocked while waiting,
373  *                then locked again when waking up.
374  * @param deadline <b>absolute</b> timeout
375  *
376  * @return 0 if the condition was signaled, an error code in case of timeout.
377  */
378 int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
379                         mtime_t deadline)
380 {
381 #if defined(__APPLE__) && !defined(__powerpc__) && !defined( __ppc__ ) && !defined( __ppc64__ )
382     /* mdate() is mac_absolute_time on OSX, which we must convert to do
383      * the same base than gettimeofday() which pthread_cond_timedwait
384      * relies on. */
385     mtime_t oldbase = mdate();
386     struct timeval tv;
387     gettimeofday(&tv, NULL);
388     mtime_t newbase = (mtime_t)tv.tv_sec * 1000000 + (mtime_t) tv.tv_usec;
389     deadline = deadline - oldbase + newbase;
390 #endif
391     lldiv_t d = lldiv( deadline, CLOCK_FREQ );
392     struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };
393
394     int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
395     if (val != ETIMEDOUT)
396         VLC_THREAD_ASSERT ("timed-waiting on condition");
397     return val;
398 }
399
400 /**
401  * Initializes a semaphore.
402  */
403 void vlc_sem_init (vlc_sem_t *sem, unsigned value)
404 {
405     if (unlikely(sem_init (sem, 0, value)))
406         abort ();
407 }
408
409 /**
410  * Destroys a semaphore.
411  */
412 void vlc_sem_destroy (vlc_sem_t *sem)
413 {
414     if (likely(sem_destroy (sem) == 0))
415         return;
416
417     int val = errno;
418     VLC_THREAD_ASSERT ("destroying semaphore");
419 }
420
421 /**
422  * Increments the value of a semaphore.
423  * @return 0 on success, EOVERFLOW in case of integer overflow
424  */
425 int vlc_sem_post (vlc_sem_t *sem)
426 {
427     if (likely(sem_post (sem) == 0))
428         return 0;
429
430     int val = errno;
431     if (unlikely(val != EOVERFLOW))
432         VLC_THREAD_ASSERT ("unlocking semaphore");
433     return val;
434 }
435
436 /**
437  * Atomically wait for the semaphore to become non-zero (if needed),
438  * then decrements it.
439  */
440 void vlc_sem_wait (vlc_sem_t *sem)
441 {
442     int val;
443
444     do
445         if (likely(sem_wait (sem) == 0))
446             return;
447     while ((val = errno) == EINTR);
448
449     VLC_THREAD_ASSERT ("locking semaphore");
450 }
451
452 /**
453  * Initializes a read/write lock.
454  */
455 void vlc_rwlock_init (vlc_rwlock_t *lock)
456 {
457     if (unlikely(pthread_rwlock_init (lock, NULL)))
458         abort ();
459 }
460
461 /**
462  * Destroys an initialized unused read/write lock.
463  */
464 void vlc_rwlock_destroy (vlc_rwlock_t *lock)
465 {
466     int val = pthread_rwlock_destroy (lock);
467     VLC_THREAD_ASSERT ("destroying R/W lock");
468 }
469
470 /**
471  * Acquires a read/write lock for reading. Recursion is allowed.
472  */
473 void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
474 {
475     int val = pthread_rwlock_rdlock (lock);
476     VLC_THREAD_ASSERT ("acquiring R/W lock for reading");
477 }
478
479 /**
480  * Acquires a read/write lock for writing. Recursion is not allowed.
481  */
482 void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
483 {
484     int val = pthread_rwlock_wrlock (lock);
485     VLC_THREAD_ASSERT ("acquiring R/W lock for writing");
486 }
487
488 /**
489  * Releases a read/write lock.
490  */
491 void vlc_rwlock_unlock (vlc_rwlock_t *lock)
492 {
493     int val = pthread_rwlock_unlock (lock);
494     VLC_THREAD_ASSERT ("releasing R/W lock");
495 }
496
497 /**
498  * Allocates a thread-specific variable.
499  * @param key where to store the thread-specific variable handle
500  * @param destr a destruction callback. It is called whenever a thread exits
501  * and the thread-specific variable has a non-NULL value.
502  * @return 0 on success, a system error code otherwise. This function can
503  * actually fail because there is a fixed limit on the number of
504  * thread-specific variable in a process on most systems.
505  */
506 int vlc_threadvar_create (vlc_threadvar_t *key, void (*destr) (void *))
507 {
508     return pthread_key_create (key, destr);
509 }
510
511 void vlc_threadvar_delete (vlc_threadvar_t *p_tls)
512 {
513     pthread_key_delete (*p_tls);
514 }
515
516 /**
517  * Sets a thread-specific variable.
518  * @param key thread-local variable key (created with vlc_threadvar_create())
519  * @param value new value for the variable for the calling thread
520  * @return 0 on success, a system error code otherwise.
521  */
522 int vlc_threadvar_set (vlc_threadvar_t key, void *value)
523 {
524     return pthread_setspecific (key, value);
525 }
526
527 /**
528  * Gets the value of a thread-local variable for the calling thread.
529  * This function cannot fail.
530  * @return the value associated with the given variable for the calling
531  * or NULL if there is no value.
532  */
533 void *vlc_threadvar_get (vlc_threadvar_t key)
534 {
535     return pthread_getspecific (key);
536 }
537
538 static bool rt_priorities = false;
539 static int rt_offset;
540
541 void vlc_threads_setup (libvlc_int_t *p_libvlc)
542 {
543     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
544     static bool initialized = false;
545
546     vlc_mutex_lock (&lock);
547     /* Initializes real-time priorities before any thread is created,
548      * just once per process. */
549     if (!initialized)
550     {
551 #ifndef __APPLE__
552         if (var_InheritBool (p_libvlc, "rt-priority"))
553 #endif
554         {
555             rt_offset = var_InheritInteger (p_libvlc, "rt-offset");
556             rt_priorities = true;
557         }
558         initialized = true;
559     }
560     vlc_mutex_unlock (&lock);
561 }
562
563 /**
564  * Creates and starts new thread.
565  *
566  * @param p_handle [OUT] pointer to write the handle of the created thread to
567  * @param entry entry point for the thread
568  * @param data data parameter given to the entry point
569  * @param priority thread priority value
570  * @return 0 on success, a standard error code on error.
571  */
572 int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
573                int priority)
574 {
575     int ret;
576
577     pthread_attr_t attr;
578     pthread_attr_init (&attr);
579
580     /* Block the signals that signals interface plugin handles.
581      * If the LibVLC caller wants to handle some signals by itself, it should
582      * block these before whenever invoking LibVLC. And it must obviously not
583      * start the VLC signals interface plugin.
584      *
585      * LibVLC will normally ignore any interruption caused by an asynchronous
586      * signal during a system call. But there may well be some buggy cases
587      * where it fails to handle EINTR (bug reports welcome). Some underlying
588      * libraries might also not handle EINTR properly.
589      */
590     sigset_t oldset;
591     {
592         sigset_t set;
593         sigemptyset (&set);
594         sigdelset (&set, SIGHUP);
595         sigaddset (&set, SIGINT);
596         sigaddset (&set, SIGQUIT);
597         sigaddset (&set, SIGTERM);
598
599         sigaddset (&set, SIGPIPE); /* We don't want this one, really! */
600         pthread_sigmask (SIG_BLOCK, &set, &oldset);
601     }
602
603 #if defined (_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING >= 0) \
604  && defined (_POSIX_THREAD_PRIORITY_SCHEDULING) \
605  && (_POSIX_THREAD_PRIORITY_SCHEDULING >= 0)
606     if (rt_priorities)
607     {
608         struct sched_param sp = { .sched_priority = priority + rt_offset, };
609         int policy;
610
611         if (sp.sched_priority <= 0)
612             sp.sched_priority += sched_get_priority_max (policy = SCHED_OTHER);
613         else
614             sp.sched_priority += sched_get_priority_min (policy = SCHED_RR);
615
616         pthread_attr_setschedpolicy (&attr, policy);
617         pthread_attr_setschedparam (&attr, &sp);
618     }
619 #else
620     (void) priority;
621 #endif
622
623     /* The thread stack size.
624      * The lower the value, the less address space per thread, the highest
625      * maximum simultaneous threads per process. Too low values will cause
626      * stack overflows and weird crashes. Set with caution. Also keep in mind
627      * that 64-bits platforms consume more stack than 32-bits one.
628      *
629      * Thanks to on-demand paging, thread stack size only affects address space
630      * consumption. In terms of memory, threads only use what they need
631      * (rounded up to the page boundary).
632      *
633      * For example, on Linux i386, the default is 2 mega-bytes, which supports
634      * about 320 threads per processes. */
635 #define VLC_STACKSIZE (128 * sizeof (void *) * 1024)
636
637 #ifdef VLC_STACKSIZE
638     ret = pthread_attr_setstacksize (&attr, VLC_STACKSIZE);
639     assert (ret == 0); /* fails iif VLC_STACKSIZE is invalid */
640 #endif
641
642     ret = pthread_create (p_handle, &attr, entry, data);
643     pthread_sigmask (SIG_SETMASK, &oldset, NULL);
644     pthread_attr_destroy (&attr);
645     return ret;
646 }
647
648 /**
649  * Marks a thread as cancelled. Next time the target thread reaches a
650  * cancellation point (while not having disabled cancellation), it will
651  * run its cancellation cleanup handler, the thread variable destructors, and
652  * terminate. vlc_join() must be used afterward regardless of a thread being
653  * cancelled or not.
654  */
655 void vlc_cancel (vlc_thread_t thread_id)
656 {
657     pthread_cancel (thread_id);
658 }
659
660 /**
661  * Waits for a thread to complete (if needed), then destroys it.
662  * This is a cancellation point; in case of cancellation, the join does _not_
663  * occur.
664  * @warning
665  * A thread cannot join itself (normally VLC will abort if this is attempted).
666  * Also, a detached thread <b>cannot</b> be joined.
667  *
668  * @param handle thread handle
669  * @param p_result [OUT] pointer to write the thread return value or NULL
670  */
671 void vlc_join (vlc_thread_t handle, void **result)
672 {
673     int val = pthread_join (handle, result);
674     VLC_THREAD_ASSERT ("joining thread");
675 }
676
677 /**
678  * Detaches a thread. When the specified thread completes, it will be
679  * automatically destroyed (in particular, its stack will be reclaimed),
680  * instead of waiting for another thread to call vlc_join(). If the thread has
681  * already completed, it will be destroyed immediately.
682  *
683  * When a thread performs some work asynchronously and may complete much
684  * earlier than it can be joined, detaching the thread can save memory.
685  * However, care must be taken that any resources used by a detached thread
686  * remains valid until the thread completes. This will typically involve some
687  * kind of thread-safe signaling.
688  *
689  * A thread may detach itself.
690  *
691  * @param handle thread handle
692  */
693 void vlc_detach (vlc_thread_t handle)
694 {
695     int val = pthread_detach (handle);
696     VLC_THREAD_ASSERT ("detaching thread");
697 }
698
699 /**
700  * Save the current cancellation state (enabled or disabled), then disable
701  * cancellation for the calling thread.
702  * This function must be called before entering a piece of code that is not
703  * cancellation-safe, unless it can be proven that the calling thread will not
704  * be cancelled.
705  * @return Previous cancellation state (opaque value for vlc_restorecancel()).
706  */
707 int vlc_savecancel (void)
708 {
709     int state;
710     int val = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
711
712     VLC_THREAD_ASSERT ("saving cancellation");
713     return state;
714 }
715
716 /**
717  * Restore the cancellation state for the calling thread.
718  * @param state previous state as returned by vlc_savecancel().
719  * @return Nothing, always succeeds.
720  */
721 void vlc_restorecancel (int state)
722 {
723 #ifndef NDEBUG
724     int oldstate, val;
725
726     val = pthread_setcancelstate (state, &oldstate);
727     /* This should fail if an invalid value for given for state */
728     VLC_THREAD_ASSERT ("restoring cancellation");
729
730     if (unlikely(oldstate != PTHREAD_CANCEL_DISABLE))
731          vlc_thread_fatal ("restoring cancellation while not disabled", EINVAL,
732                            __func__, __FILE__, __LINE__);
733 #else
734     pthread_setcancelstate (state, NULL);
735 #endif
736 }
737
738 /**
739  * Issues an explicit deferred cancellation point.
740  * This has no effect if thread cancellation is disabled.
741  * This can be called when there is a rather slow non-sleeping operation.
742  * This is also used to force a cancellation point in a function that would
743  * otherwise "not always" be a one (block_FifoGet() is an example).
744  */
745 void vlc_testcancel (void)
746 {
747     pthread_testcancel ();
748 }
749
750 void vlc_control_cancel (int cmd, ...)
751 {
752     (void) cmd;
753     assert (0);
754 }
755
756
757 struct vlc_timer
758 {
759     vlc_thread_t thread;
760     vlc_mutex_t  lock;
761     vlc_cond_t   wait;
762     void       (*func) (void *);
763     void        *data;
764     mtime_t      value, interval;
765     unsigned     users;
766     unsigned     overruns;
767 };
768
769 static void *vlc_timer_do (void *data)
770 {
771     struct vlc_timer *timer = data;
772
773     timer->func (timer->data);
774
775     vlc_mutex_lock (&timer->lock);
776     assert (timer->users > 0);
777     if (--timer->users == 0)
778         vlc_cond_signal (&timer->wait);
779     vlc_mutex_unlock (&timer->lock);
780     return NULL;
781 }
782
783 static void *vlc_timer_thread (void *data)
784 {
785     struct vlc_timer *timer = data;
786     mtime_t value, interval;
787
788     vlc_mutex_lock (&timer->lock);
789     value = timer->value;
790     interval = timer->interval;
791     vlc_mutex_unlock (&timer->lock);
792
793     for (;;)
794     {
795          vlc_thread_t th;
796
797          mwait (value);
798
799          vlc_mutex_lock (&timer->lock);
800          if (vlc_clone (&th, vlc_timer_do, timer, VLC_THREAD_PRIORITY_INPUT))
801              timer->overruns++;
802          else
803          {
804              vlc_detach (th);
805              timer->users++;
806          }
807          vlc_mutex_unlock (&timer->lock);
808
809          if (interval == 0)
810              return NULL;
811
812          value += interval;
813     }
814 }
815
816 /**
817  * Initializes an asynchronous timer.
818  * @warning Asynchronous timers are processed from an unspecified thread.
819  * Also, multiple occurences of an interval timer can run concurrently.
820  *
821  * @param id pointer to timer to be initialized
822  * @param func function that the timer will call
823  * @param data parameter for the timer function
824  * @return 0 on success, a system error code otherwise.
825  */
826 int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
827 {
828     struct vlc_timer *timer = malloc (sizeof (*timer));
829
830     if (unlikely(timer == NULL))
831         return ENOMEM;
832     vlc_mutex_init (&timer->lock);
833     vlc_cond_init (&timer->wait);
834     assert (func);
835     timer->func = func;
836     timer->data = data;
837     timer->value = 0;
838     timer->interval = 0;
839     timer->users = 0;
840     timer->overruns = 0;
841     *id = timer;
842     return 0;
843 }
844
845 /**
846  * Destroys an initialized timer. If needed, the timer is first disarmed.
847  * This function is undefined if the specified timer is not initialized.
848  *
849  * @warning This function <b>must</b> be called before the timer data can be
850  * freed and before the timer callback function can be unloaded.
851  *
852  * @param timer timer to destroy
853  */
854 void vlc_timer_destroy (vlc_timer_t timer)
855 {
856     vlc_timer_schedule (timer, false, 0, 0);
857     vlc_mutex_lock (&timer->lock);
858     while (timer->users != 0)
859         vlc_cond_wait (&timer->wait, &timer->lock);
860     vlc_mutex_unlock (&timer->lock);
861
862     vlc_cond_destroy (&timer->wait);
863     vlc_mutex_destroy (&timer->lock);
864     free (timer);
865 }
866
867 /**
868  * Arm or disarm an initialized timer.
869  * This functions overrides any previous call to itself.
870  *
871  * @note A timer can fire later than requested due to system scheduling
872  * limitations. An interval timer can fail to trigger sometimes, either because
873  * the system is busy or suspended, or because a previous iteration of the
874  * timer is still running. See also vlc_timer_getoverrun().
875  *
876  * @param timer initialized timer
877  * @param absolute the timer value origin is the same as mdate() if true,
878  *                 the timer value is relative to now if false.
879  * @param value zero to disarm the timer, otherwise the initial time to wait
880  *              before firing the timer.
881  * @param interval zero to fire the timer just once, otherwise the timer
882  *                 repetition interval.
883  */
884 void vlc_timer_schedule (vlc_timer_t timer, bool absolute,
885                          mtime_t value, mtime_t interval)
886 {
887     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
888
889     vlc_mutex_lock (&lock);
890     vlc_mutex_lock (&timer->lock);
891     if (timer->value)
892     {
893         vlc_mutex_unlock (&timer->lock);
894         vlc_cancel (timer->thread);
895         vlc_join (timer->thread, NULL);
896         vlc_mutex_lock (&timer->lock);
897         timer->value = 0;
898     }
899     if ((value != 0)
900      && (vlc_clone (&timer->thread, vlc_timer_thread, timer,
901                     VLC_THREAD_PRIORITY_INPUT) == 0))
902     {
903         timer->value = (absolute ? 0 : mdate ()) + value;
904         timer->interval = interval;
905     }
906     vlc_mutex_unlock (&timer->lock);
907     vlc_mutex_unlock (&lock);
908 }
909
910 /**
911  * Fetch and reset the overrun counter for a timer.
912  * @param timer initialized timer
913  * @return the timer overrun counter, i.e. the number of times that the timer
914  * should have run but did not since the last actual run. If all is well, this
915  * is zero.
916  */
917 unsigned vlc_timer_getoverrun (vlc_timer_t timer)
918 {
919     unsigned ret;
920
921     vlc_mutex_lock (&timer->lock);
922     ret = timer->overruns;
923     timer->overruns = 0;
924     vlc_mutex_unlock (&timer->lock);
925     return ret;
926 }