]> git.sesse.net Git - vlc/blob - src/posix/thread.c
Split mdate(), mwait(), msleep() to POSIX and Win32 files
[vlc] / src / posix / thread.c
1 /*****************************************************************************
2  * thread.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 #include <vlc_atomic.h>
33
34 #include "libvlc.h"
35 #include <stdarg.h>
36 #include <assert.h>
37 #include <unistd.h> /* fsync() */
38 #include <signal.h>
39 #include <errno.h>
40 #include <time.h>
41
42 #include <sched.h>
43 #ifdef __linux__
44 # include <sys/syscall.h> /* SYS_gettid */
45 #endif
46
47 #ifdef HAVE_EXECINFO_H
48 # include <execinfo.h>
49 #endif
50
51 #ifdef __APPLE__
52 # include <sys/time.h> /* gettimeofday in vlc_cond_timedwait */
53 # include <mach/mach_init.h> /* mach_task_self in semaphores */
54 # include <sys/sysctl.h>
55 #endif
56
57 #if defined(__OpenBSD__)
58 # include <sys/param.h>
59 # include <sys/sysctl.h>
60 # include <machine/cpu.h>
61 #endif
62
63 #if defined(__SunOS)
64 # include <unistd.h>
65 # include <sys/types.h>
66 # include <sys/processor.h>
67 # include <sys/pset.h>
68 #endif
69
70 #if !defined (_POSIX_TIMERS)
71 # define _POSIX_TIMERS (-1)
72 #endif
73 #if !defined (_POSIX_CLOCK_SELECTION)
74 /* Clock selection was defined in 2001 and became mandatory in 2008. */
75 # define _POSIX_CLOCK_SELECTION (-1)
76 #endif
77 #if !defined (_POSIX_MONOTONIC_CLOCK)
78 # define _POSIX_MONOTONIC_CLOCK (-1)
79 #endif
80
81 #if (_POSIX_TIMERS > 0)
82 static unsigned vlc_clock_prec;
83
84 # if (_POSIX_CLOCK_SELECTION > 0)
85 /* POSIX clock selection is needed so that vlc_cond_timewait() is consistent
86  * with mdate() and mwait(). Otherwise, the monotonic clock cannot be used.
87  * Fortunately, clock selection has become mandatory as of 2008 so that really
88  * only broken old systems still lack it. */
89
90 #  if (_POSIX_MONOTONIC_CLOCK > 0)
91 /* Compile-time POSIX monotonic clock support */
92 #   define vlc_clock_id (CLOCK_MONOTONIC)
93
94 #  elif (_POSIX_MONOTONIC_CLOCK == 0)
95 /* Run-time POSIX monotonic clock support (see clock_setup() below) */
96 static clockid_t vlc_clock_id;
97
98 #  else
99 /* No POSIX monotonic clock support */
100 #   define vlc_clock_id (CLOCK_REALTIME)
101 #   warning Monotonic clock not available. Expect timing issues.
102
103 #  endif /* _POSIX_MONOTONIC_CLOKC */
104 # else
105 /* No POSIX clock selection. */
106 #  define pthread_condattr_setclock(attr, clock) (attr, clock, 0)
107 #  warning Clock selection not available. Expect timing issues.
108
109 # endif /* _POSIX_CLOCK_SELECTION */
110
111 static void vlc_clock_setup_once (void)
112 {
113 # if (_POSIX_MONOTONIC_CLOCK == 0)
114     long val = sysconf (_SC_MONOTONIC_CLOCK);
115     assert (val != 0);
116     vlc_clock_id = (val < 0) ? CLOCK_REALTIME : CLOCK_MONOTONIC;
117 # endif
118
119     struct timespec res;
120     if (unlikely(clock_getres (vlc_clock_id, &res) != 0 || res.tv_sec != 0))
121         abort ();
122     vlc_clock_prec = (res.tv_nsec + 500) / 1000;
123 }
124
125 static pthread_once_t vlc_clock_once = PTHREAD_ONCE_INIT;
126
127 # define vlc_clock_setup() \
128     pthread_once(&vlc_clock_once, vlc_clock_setup_once)
129
130 #else /* _POSIX_TIMERS */
131
132 # include <sys/time.h> /* gettimeofday() */
133 # if defined (HAVE_DECL_NANOSLEEP) && !HAVE_DECL_NANOSLEEP
134 int nanosleep (struct timespec *, struct timespec *);
135 # endif
136
137 #endif /* _POSIX_TIMERS */
138
139 /**
140  * Print a backtrace to the standard error for debugging purpose.
141  */
142 void vlc_trace (const char *fn, const char *file, unsigned line)
143 {
144      fprintf (stderr, "at %s:%u in %s\n", file, line, fn);
145      fflush (stderr); /* needed before switch to low-level I/O */
146 #ifdef HAVE_BACKTRACE
147      void *stack[20];
148      int len = backtrace (stack, sizeof (stack) / sizeof (stack[0]));
149      backtrace_symbols_fd (stack, len, 2);
150 #endif
151      fsync (2);
152 }
153
154 static inline unsigned long vlc_threadid (void)
155 {
156 #if defined (__linux__)
157      /* glibc does not provide a call for this */
158      return syscall (SYS_gettid);
159
160 #else
161      union { pthread_t th; unsigned long int i; } v = { };
162      v.th = pthread_self ();
163      return v.i;
164
165 #endif
166 }
167
168 #ifndef NDEBUG
169 /*****************************************************************************
170  * vlc_thread_fatal: Report an error from the threading layer
171  *****************************************************************************
172  * This is mostly meant for debugging.
173  *****************************************************************************/
174 static void
175 vlc_thread_fatal (const char *action, int error,
176                   const char *function, const char *file, unsigned line)
177 {
178     int canc = vlc_savecancel ();
179     fprintf (stderr, "LibVLC fatal error %s (%d) in thread %lu ",
180              action, error, vlc_threadid ());
181     vlc_trace (function, file, line);
182
183     /* Sometimes strerror_r() crashes too, so make sure we print an error
184      * message before we invoke it */
185 #ifdef __GLIBC__
186     /* Avoid the strerror_r() prototype brain damage in glibc */
187     errno = error;
188     fprintf (stderr, " Error message: %m\n");
189 #else
190     char buf[1000];
191     const char *msg;
192
193     switch (strerror_r (error, buf, sizeof (buf)))
194     {
195         case 0:
196             msg = buf;
197             break;
198         case ERANGE: /* should never happen */
199             msg = "unknown (too big to display)";
200             break;
201         default:
202             msg = "unknown (invalid error number)";
203             break;
204     }
205     fprintf (stderr, " Error message: %s\n", msg);
206 #endif
207     fflush (stderr);
208
209     vlc_restorecancel (canc);
210     abort ();
211 }
212
213 # define VLC_THREAD_ASSERT( action ) \
214     if (unlikely(val)) \
215         vlc_thread_fatal (action, val, __func__, __FILE__, __LINE__)
216 #else
217 # define VLC_THREAD_ASSERT( action ) ((void)val)
218 #endif
219
220 #if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6)
221 /* This is not prototyped under glibc, though it exists. */
222 int pthread_mutexattr_setkind_np( pthread_mutexattr_t *attr, int kind );
223 #endif
224
225 /*****************************************************************************
226  * vlc_mutex_init: initialize a mutex
227  *****************************************************************************/
228 void vlc_mutex_init( vlc_mutex_t *p_mutex )
229 {
230     pthread_mutexattr_t attr;
231
232     if (unlikely(pthread_mutexattr_init (&attr)))
233         abort();
234 #ifdef NDEBUG
235     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_NORMAL );
236 #else
237     /* Create error-checking mutex to detect problems more easily. */
238 # if defined (__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 6)
239     pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
240 # else
241     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK );
242 # endif
243 #endif
244     if (unlikely(pthread_mutex_init (p_mutex, &attr)))
245         abort();
246     pthread_mutexattr_destroy( &attr );
247 }
248
249 /*****************************************************************************
250  * vlc_mutex_init: initialize a recursive mutex (Do not use)
251  *****************************************************************************/
252 void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
253 {
254     pthread_mutexattr_t attr;
255
256     if (unlikely(pthread_mutexattr_init (&attr)))
257         abort();
258 #if defined (__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 6)
259     pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_RECURSIVE_NP );
260 #else
261     pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
262 #endif
263     if (unlikely(pthread_mutex_init (p_mutex, &attr)))
264         abort();
265     pthread_mutexattr_destroy( &attr );
266 }
267
268
269 /**
270  * Destroys a mutex. The mutex must not be locked.
271  *
272  * @param p_mutex mutex to destroy
273  * @return always succeeds
274  */
275 void vlc_mutex_destroy (vlc_mutex_t *p_mutex)
276 {
277     int val = pthread_mutex_destroy( p_mutex );
278     VLC_THREAD_ASSERT ("destroying mutex");
279 }
280
281 #ifndef NDEBUG
282 # ifdef HAVE_VALGRIND_VALGRIND_H
283 #  include <valgrind/valgrind.h>
284 # else
285 #  define RUNNING_ON_VALGRIND (0)
286 # endif
287
288 void vlc_assert_locked (vlc_mutex_t *p_mutex)
289 {
290     if (RUNNING_ON_VALGRIND > 0)
291         return;
292     assert (pthread_mutex_lock (p_mutex) == EDEADLK);
293 }
294 #endif
295
296 /**
297  * Acquires a mutex. If needed, waits for any other thread to release it.
298  * Beware of deadlocks when locking multiple mutexes at the same time,
299  * or when using mutexes from callbacks.
300  * This function is not a cancellation-point.
301  *
302  * @param p_mutex mutex initialized with vlc_mutex_init() or
303  *                vlc_mutex_init_recursive()
304  */
305 void vlc_mutex_lock (vlc_mutex_t *p_mutex)
306 {
307     int val = pthread_mutex_lock( p_mutex );
308     VLC_THREAD_ASSERT ("locking mutex");
309 }
310
311 /**
312  * Acquires a mutex if and only if it is not currently held by another thread.
313  * This function never sleeps and can be used in delay-critical code paths.
314  * This function is not a cancellation-point.
315  *
316  * <b>Beware</b>: If this function fails, then the mutex is held... by another
317  * thread. The calling thread must deal with the error appropriately. That
318  * typically implies postponing the operations that would have required the
319  * mutex. If the thread cannot defer those operations, then it must use
320  * vlc_mutex_lock(). If in doubt, use vlc_mutex_lock() instead.
321  *
322  * @param p_mutex mutex initialized with vlc_mutex_init() or
323  *                vlc_mutex_init_recursive()
324  * @return 0 if the mutex could be acquired, an error code otherwise.
325  */
326 int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
327 {
328     int val = pthread_mutex_trylock( p_mutex );
329
330     if (val != EBUSY)
331         VLC_THREAD_ASSERT ("locking mutex");
332     return val;
333 }
334
335 /**
336  * Releases a mutex (or crashes if the mutex is not locked by the caller).
337  * @param p_mutex mutex locked with vlc_mutex_lock().
338  */
339 void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
340 {
341     int val = pthread_mutex_unlock( p_mutex );
342     VLC_THREAD_ASSERT ("unlocking mutex");
343 }
344
345 /**
346  * Initializes a condition variable.
347  */
348 void vlc_cond_init (vlc_cond_t *p_condvar)
349 {
350     pthread_condattr_t attr;
351
352     vlc_clock_setup ();
353     if (unlikely(pthread_condattr_init (&attr)))
354         abort ();
355     pthread_condattr_setclock (&attr, vlc_clock_id);
356
357     if (unlikely(pthread_cond_init (p_condvar, &attr)))
358         abort ();
359     pthread_condattr_destroy (&attr);
360 }
361
362 /**
363  * Initializes a condition variable.
364  * Contrary to vlc_cond_init(), the wall clock will be used as a reference for
365  * the vlc_cond_timedwait() time-out parameter.
366  */
367 void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
368 {
369     if (unlikely(pthread_cond_init (p_condvar, NULL)))
370         abort ();
371 }
372
373 /**
374  * Destroys a condition variable. No threads shall be waiting or signaling the
375  * condition.
376  * @param p_condvar condition variable to destroy
377  */
378 void vlc_cond_destroy (vlc_cond_t *p_condvar)
379 {
380     int val = pthread_cond_destroy( p_condvar );
381     VLC_THREAD_ASSERT ("destroying condition");
382 }
383
384 /**
385  * Wakes up one thread waiting on a condition variable, if any.
386  * @param p_condvar condition variable
387  */
388 void vlc_cond_signal (vlc_cond_t *p_condvar)
389 {
390     int val = pthread_cond_signal( p_condvar );
391     VLC_THREAD_ASSERT ("signaling condition variable");
392 }
393
394 /**
395  * Wakes up all threads (if any) waiting on a condition variable.
396  * @param p_cond condition variable
397  */
398 void vlc_cond_broadcast (vlc_cond_t *p_condvar)
399 {
400     pthread_cond_broadcast (p_condvar);
401 }
402
403 /**
404  * Waits for a condition variable. The calling thread will be suspended until
405  * another thread calls vlc_cond_signal() or vlc_cond_broadcast() on the same
406  * condition variable, the thread is cancelled with vlc_cancel(), or the
407  * system causes a "spurious" unsolicited wake-up.
408  *
409  * A mutex is needed to wait on a condition variable. It must <b>not</b> be
410  * a recursive mutex. Although it is possible to use the same mutex for
411  * multiple condition, it is not valid to use different mutexes for the same
412  * condition variable at the same time from different threads.
413  *
414  * In case of thread cancellation, the mutex is always locked before
415  * cancellation proceeds.
416  *
417  * The canonical way to use a condition variable to wait for event foobar is:
418  @code
419    vlc_mutex_lock (&lock);
420    mutex_cleanup_push (&lock); // release the mutex in case of cancellation
421
422    while (!foobar)
423        vlc_cond_wait (&wait, &lock);
424
425    --- foobar is now true, do something about it here --
426
427    vlc_cleanup_run (); // release the mutex
428   @endcode
429  *
430  * @param p_condvar condition variable to wait on
431  * @param p_mutex mutex which is unlocked while waiting,
432  *                then locked again when waking up.
433  * @param deadline <b>absolute</b> timeout
434  */
435 void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
436 {
437     int val = pthread_cond_wait( p_condvar, p_mutex );
438     VLC_THREAD_ASSERT ("waiting on condition");
439 }
440
441 /**
442  * Waits for a condition variable up to a certain date.
443  * This works like vlc_cond_wait(), except for the additional time-out.
444  *
445  * If the variable was initialized with vlc_cond_init(), the timeout has the
446  * same arbitrary origin as mdate(). If the variable was initialized with
447  * vlc_cond_init_daytime(), the timeout is expressed from the Unix epoch.
448  *
449  * @param p_condvar condition variable to wait on
450  * @param p_mutex mutex which is unlocked while waiting,
451  *                then locked again when waking up.
452  * @param deadline <b>absolute</b> timeout
453  *
454  * @return 0 if the condition was signaled, an error code in case of timeout.
455  */
456 int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
457                         mtime_t deadline)
458 {
459 #if defined(__APPLE__) && !defined(__powerpc__) && !defined( __ppc__ ) && !defined( __ppc64__ )
460     /* mdate() is the monotonic clock, timedwait origin is gettimeofday() which
461      * isn't monotonic. Use imedwait_relative_np() instead
462     */
463     mtime_t base = mdate();
464     deadline -= base;
465     if (deadline < 0)
466         deadline = 0;
467     lldiv_t d = lldiv( deadline, CLOCK_FREQ );
468     struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };
469
470     int val = pthread_cond_timedwait_relative_np(p_condvar, p_mutex, &ts);
471 #else
472     lldiv_t d = lldiv( deadline, CLOCK_FREQ );
473     struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) };
474     int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
475 #endif
476     if (val != ETIMEDOUT)
477         VLC_THREAD_ASSERT ("timed-waiting on condition");
478     return val;
479 }
480
481 /**
482  * Initializes a semaphore.
483  */
484 void vlc_sem_init (vlc_sem_t *sem, unsigned value)
485 {
486 #if defined(__APPLE__)
487     if (unlikely(semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value) != KERN_SUCCESS))
488         abort ();
489 #else
490     if (unlikely(sem_init (sem, 0, value)))
491         abort ();
492 #endif
493 }
494
495 /**
496  * Destroys a semaphore.
497  */
498 void vlc_sem_destroy (vlc_sem_t *sem)
499 {
500     int val;
501
502 #if defined(__APPLE__)
503     if (likely(semaphore_destroy(mach_task_self(), *sem) == KERN_SUCCESS))
504         return;
505
506     val = EINVAL;
507 #else
508     if (likely(sem_destroy (sem) == 0))
509         return;
510
511     val = errno;
512 #endif
513
514     VLC_THREAD_ASSERT ("destroying semaphore");
515 }
516
517 /**
518  * Increments the value of a semaphore.
519  * @return 0 on success, EOVERFLOW in case of integer overflow
520  */
521 int vlc_sem_post (vlc_sem_t *sem)
522 {
523     int val;
524
525 #if defined(__APPLE__)
526     if (likely(semaphore_signal(*sem) == KERN_SUCCESS))
527         return 0;
528
529     val = EINVAL;
530 #else
531     if (likely(sem_post (sem) == 0))
532         return 0;
533
534     val = errno;
535 #endif
536
537     if (unlikely(val != EOVERFLOW))
538         VLC_THREAD_ASSERT ("unlocking semaphore");
539     return val;
540 }
541
542 /**
543  * Atomically wait for the semaphore to become non-zero (if needed),
544  * then decrements it.
545  */
546 void vlc_sem_wait (vlc_sem_t *sem)
547 {
548     int val;
549
550 #if defined(__APPLE__)
551     if (likely(semaphore_wait(*sem) == KERN_SUCCESS))
552         return;
553
554     val = EINVAL;
555 #else
556     do
557         if (likely(sem_wait (sem) == 0))
558             return;
559     while ((val = errno) == EINTR);
560 #endif
561
562     VLC_THREAD_ASSERT ("locking semaphore");
563 }
564
565 /**
566  * Initializes a read/write lock.
567  */
568 void vlc_rwlock_init (vlc_rwlock_t *lock)
569 {
570     if (unlikely(pthread_rwlock_init (lock, NULL)))
571         abort ();
572 }
573
574 /**
575  * Destroys an initialized unused read/write lock.
576  */
577 void vlc_rwlock_destroy (vlc_rwlock_t *lock)
578 {
579     int val = pthread_rwlock_destroy (lock);
580     VLC_THREAD_ASSERT ("destroying R/W lock");
581 }
582
583 /**
584  * Acquires a read/write lock for reading. Recursion is allowed.
585  */
586 void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
587 {
588     int val = pthread_rwlock_rdlock (lock);
589     VLC_THREAD_ASSERT ("acquiring R/W lock for reading");
590 }
591
592 /**
593  * Acquires a read/write lock for writing. Recursion is not allowed.
594  */
595 void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
596 {
597     int val = pthread_rwlock_wrlock (lock);
598     VLC_THREAD_ASSERT ("acquiring R/W lock for writing");
599 }
600
601 /**
602  * Releases a read/write lock.
603  */
604 void vlc_rwlock_unlock (vlc_rwlock_t *lock)
605 {
606     int val = pthread_rwlock_unlock (lock);
607     VLC_THREAD_ASSERT ("releasing R/W lock");
608 }
609
610 /**
611  * Allocates a thread-specific variable.
612  * @param key where to store the thread-specific variable handle
613  * @param destr a destruction callback. It is called whenever a thread exits
614  * and the thread-specific variable has a non-NULL value.
615  * @return 0 on success, a system error code otherwise. This function can
616  * actually fail because there is a fixed limit on the number of
617  * thread-specific variable in a process on most systems.
618  */
619 int vlc_threadvar_create (vlc_threadvar_t *key, void (*destr) (void *))
620 {
621     return pthread_key_create (key, destr);
622 }
623
624 void vlc_threadvar_delete (vlc_threadvar_t *p_tls)
625 {
626     pthread_key_delete (*p_tls);
627 }
628
629 /**
630  * Sets a thread-specific variable.
631  * @param key thread-local variable key (created with vlc_threadvar_create())
632  * @param value new value for the variable for the calling thread
633  * @return 0 on success, a system error code otherwise.
634  */
635 int vlc_threadvar_set (vlc_threadvar_t key, void *value)
636 {
637     return pthread_setspecific (key, value);
638 }
639
640 /**
641  * Gets the value of a thread-local variable for the calling thread.
642  * This function cannot fail.
643  * @return the value associated with the given variable for the calling
644  * or NULL if there is no value.
645  */
646 void *vlc_threadvar_get (vlc_threadvar_t key)
647 {
648     return pthread_getspecific (key);
649 }
650
651 static bool rt_priorities = false;
652 static int rt_offset;
653
654 void vlc_threads_setup (libvlc_int_t *p_libvlc)
655 {
656     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
657     static bool initialized = false;
658
659     vlc_mutex_lock (&lock);
660     /* Initializes real-time priorities before any thread is created,
661      * just once per process. */
662     if (!initialized)
663     {
664 #ifndef __APPLE__
665         if (var_InheritBool (p_libvlc, "rt-priority"))
666 #endif
667         {
668             rt_offset = var_InheritInteger (p_libvlc, "rt-offset");
669             rt_priorities = true;
670         }
671         initialized = true;
672     }
673     vlc_mutex_unlock (&lock);
674 }
675
676
677 static int vlc_clone_attr (vlc_thread_t *th, pthread_attr_t *attr,
678                            void *(*entry) (void *), void *data, int priority)
679 {
680     int ret;
681
682     /* Block the signals that signals interface plugin handles.
683      * If the LibVLC caller wants to handle some signals by itself, it should
684      * block these before whenever invoking LibVLC. And it must obviously not
685      * start the VLC signals interface plugin.
686      *
687      * LibVLC will normally ignore any interruption caused by an asynchronous
688      * signal during a system call. But there may well be some buggy cases
689      * where it fails to handle EINTR (bug reports welcome). Some underlying
690      * libraries might also not handle EINTR properly.
691      */
692     sigset_t oldset;
693     {
694         sigset_t set;
695         sigemptyset (&set);
696         sigdelset (&set, SIGHUP);
697         sigaddset (&set, SIGINT);
698         sigaddset (&set, SIGQUIT);
699         sigaddset (&set, SIGTERM);
700
701         sigaddset (&set, SIGPIPE); /* We don't want this one, really! */
702         pthread_sigmask (SIG_BLOCK, &set, &oldset);
703     }
704
705 #if defined (_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING >= 0) \
706  && defined (_POSIX_THREAD_PRIORITY_SCHEDULING) \
707  && (_POSIX_THREAD_PRIORITY_SCHEDULING >= 0)
708     if (rt_priorities)
709     {
710         struct sched_param sp = { .sched_priority = priority + rt_offset, };
711         int policy;
712
713         if (sp.sched_priority <= 0)
714             sp.sched_priority += sched_get_priority_max (policy = SCHED_OTHER);
715         else
716             sp.sched_priority += sched_get_priority_min (policy = SCHED_RR);
717
718         pthread_attr_setschedpolicy (attr, policy);
719         pthread_attr_setschedparam (attr, &sp);
720     }
721 #else
722     (void) priority;
723 #endif
724
725     /* The thread stack size.
726      * The lower the value, the less address space per thread, the highest
727      * maximum simultaneous threads per process. Too low values will cause
728      * stack overflows and weird crashes. Set with caution. Also keep in mind
729      * that 64-bits platforms consume more stack than 32-bits one.
730      *
731      * Thanks to on-demand paging, thread stack size only affects address space
732      * consumption. In terms of memory, threads only use what they need
733      * (rounded up to the page boundary).
734      *
735      * For example, on Linux i386, the default is 2 mega-bytes, which supports
736      * about 320 threads per processes. */
737 #define VLC_STACKSIZE (128 * sizeof (void *) * 1024)
738
739 #ifdef VLC_STACKSIZE
740     ret = pthread_attr_setstacksize (attr, VLC_STACKSIZE);
741     assert (ret == 0); /* fails iif VLC_STACKSIZE is invalid */
742 #endif
743
744     ret = pthread_create (th, attr, entry, data);
745     pthread_sigmask (SIG_SETMASK, &oldset, NULL);
746     pthread_attr_destroy (attr);
747     return ret;
748 }
749
750 /**
751  * Creates and starts new thread.
752  *
753  * The thread must be <i>joined</i> with vlc_join() to reclaim resources
754  * when it is not needed anymore.
755  *
756  * @param th [OUT] pointer to write the handle of the created thread to
757  *                 (mandatory, must be non-NULL)
758  * @param entry entry point for the thread
759  * @param data data parameter given to the entry point
760  * @param priority thread priority value
761  * @return 0 on success, a standard error code on error.
762  */
763 int vlc_clone (vlc_thread_t *th, void *(*entry) (void *), void *data,
764                int priority)
765 {
766     pthread_attr_t attr;
767
768     pthread_attr_init (&attr);
769     return vlc_clone_attr (th, &attr, entry, data, priority);
770 }
771
772 /**
773  * Waits for a thread to complete (if needed), then destroys it.
774  * This is a cancellation point; in case of cancellation, the join does _not_
775  * occur.
776  * @warning
777  * A thread cannot join itself (normally VLC will abort if this is attempted).
778  * Also, a detached thread <b>cannot</b> be joined.
779  *
780  * @param handle thread handle
781  * @param p_result [OUT] pointer to write the thread return value or NULL
782  */
783 void vlc_join (vlc_thread_t handle, void **result)
784 {
785     int val = pthread_join (handle, result);
786     VLC_THREAD_ASSERT ("joining thread");
787 }
788
789 /**
790  * Creates and starts new detached thread.
791  * A detached thread cannot be joined. Its resources will be automatically
792  * released whenever the thread exits (in particular, its call stack will be
793  * reclaimed).
794  *
795  * Detached thread are particularly useful when some work needs to be done
796  * asynchronously, that is likely to be completed much earlier than the thread
797  * can practically be joined. In this case, thread detach can spare memory.
798  *
799  * A detached thread may be cancelled, so as to expedite its termination.
800  * Be extremely careful if you do this: while a normal joinable thread can
801  * safely be cancelled after it has already exited, cancelling an already
802  * exited detached thread is undefined: The thread handle would is destroyed
803  * immediately when the detached thread exits. So you need to ensure that the
804  * detached thread is still running before cancellation is attempted.
805  *
806  * @warning Care must be taken that any resources used by the detached thread
807  * remains valid until the thread completes.
808  *
809  * @note A detached thread must eventually exit just like another other
810  * thread. In practice, LibVLC will wait for detached threads to exit before
811  * it unloads the plugins.
812  *
813  * @param th [OUT] pointer to hold the thread handle, or NULL
814  * @param entry entry point for the thread
815  * @param data data parameter given to the entry point
816  * @param priority thread priority value
817  * @return 0 on success, a standard error code on error.
818  */
819 int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data,
820                       int priority)
821 {
822     vlc_thread_t dummy;
823     pthread_attr_t attr;
824
825     if (th == NULL)
826         th = &dummy;
827
828     pthread_attr_init (&attr);
829     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
830     return vlc_clone_attr (th, &attr, entry, data, priority);
831 }
832
833 int vlc_set_priority (vlc_thread_t th, int priority)
834 {
835 #if defined (_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING >= 0) \
836  && defined (_POSIX_THREAD_PRIORITY_SCHEDULING) \
837  && (_POSIX_THREAD_PRIORITY_SCHEDULING >= 0)
838     if (rt_priorities)
839     {
840         struct sched_param sp = { .sched_priority = priority + rt_offset, };
841         int policy;
842
843         if (sp.sched_priority <= 0)
844             sp.sched_priority += sched_get_priority_max (policy = SCHED_OTHER);
845         else
846             sp.sched_priority += sched_get_priority_min (policy = SCHED_RR);
847
848         if (pthread_setschedparam (th, policy, &sp))
849             return VLC_EGENERIC;
850     }
851 #else
852     (void) priority;
853 #endif
854     return VLC_SUCCESS;
855 }
856
857 /**
858  * Marks a thread as cancelled. Next time the target thread reaches a
859  * cancellation point (while not having disabled cancellation), it will
860  * run its cancellation cleanup handler, the thread variable destructors, and
861  * terminate. vlc_join() must be used afterward regardless of a thread being
862  * cancelled or not.
863  */
864 void vlc_cancel (vlc_thread_t thread_id)
865 {
866     pthread_cancel (thread_id);
867 #ifdef HAVE_MAEMO
868     pthread_kill (thread_id, SIGRTMIN);
869 #endif
870 }
871
872 /**
873  * Save the current cancellation state (enabled or disabled), then disable
874  * cancellation for the calling thread.
875  * This function must be called before entering a piece of code that is not
876  * cancellation-safe, unless it can be proven that the calling thread will not
877  * be cancelled.
878  * @return Previous cancellation state (opaque value for vlc_restorecancel()).
879  */
880 int vlc_savecancel (void)
881 {
882     int state;
883     int val = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
884
885     VLC_THREAD_ASSERT ("saving cancellation");
886     return state;
887 }
888
889 /**
890  * Restore the cancellation state for the calling thread.
891  * @param state previous state as returned by vlc_savecancel().
892  * @return Nothing, always succeeds.
893  */
894 void vlc_restorecancel (int state)
895 {
896 #ifndef NDEBUG
897     int oldstate, val;
898
899     val = pthread_setcancelstate (state, &oldstate);
900     /* This should fail if an invalid value for given for state */
901     VLC_THREAD_ASSERT ("restoring cancellation");
902
903     if (unlikely(oldstate != PTHREAD_CANCEL_DISABLE))
904          vlc_thread_fatal ("restoring cancellation while not disabled", EINVAL,
905                            __func__, __FILE__, __LINE__);
906 #else
907     pthread_setcancelstate (state, NULL);
908 #endif
909 }
910
911 /**
912  * Issues an explicit deferred cancellation point.
913  * This has no effect if thread cancellation is disabled.
914  * This can be called when there is a rather slow non-sleeping operation.
915  * This is also used to force a cancellation point in a function that would
916  * otherwise "not always" be a one (block_FifoGet() is an example).
917  */
918 void vlc_testcancel (void)
919 {
920     pthread_testcancel ();
921 }
922
923 void vlc_control_cancel (int cmd, ...)
924 {
925     (void) cmd;
926     assert (0);
927 }
928
929 /**
930  * Precision monotonic clock.
931  *
932  * In principles, the clock has a precision of 1 MHz. But the actual resolution
933  * may be much lower, especially when it comes to sleeping with mwait() or
934  * msleep(). Most general-purpose operating systems provide a resolution of
935  * only 100 to 1000 Hz.
936  *
937  * @warning The origin date (time value "zero") is not specified. It is
938  * typically the time the kernel started, but this is platform-dependent.
939  * If you need wall clock time, use gettimeofday() instead.
940  *
941  * @return a timestamp in microseconds.
942  */
943 mtime_t mdate (void)
944 {
945 #if (_POSIX_TIMERS > 0)
946     struct timespec ts;
947
948     vlc_clock_setup ();
949     if (unlikely(clock_gettime (vlc_clock_id, &ts) != 0))
950         abort ();
951
952     return (INT64_C(1000000) * ts.tv_sec) + (ts.tv_nsec / 1000);
953
954 #else
955     struct timeval tv;
956
957     if (unlikely(gettimeofday (&tv, NULL) != 0))
958         abort ();
959     return (INT64_C(1000000) * tv.tv_sec) + tv.tv_nsec;
960
961 #endif
962 }
963
964 #undef mwait
965 /**
966  * Waits until a deadline (possibly later due to OS scheduling).
967  * @param deadline timestamp to wait for (see mdate())
968  */
969 void mwait (mtime_t deadline)
970 {
971 #if (_POSIX_TIMERS > 0)
972     vlc_clock_setup ();
973     /* If the deadline is already elapsed, or within the clock precision,
974      * do not even bother the system timer. */
975     deadline -= vlc_clock_prec;
976
977     lldiv_t d = lldiv (deadline, 1000000);
978     struct timespec ts = { d.quot, d.rem * 1000 };
979
980     while (clock_nanosleep (vlc_clock_id, TIMER_ABSTIME, &ts, NULL) == EINTR);
981
982 #else
983     deadline -= mdate ();
984     if (deadline > 0)
985         msleep (deadline);
986
987 #endif
988 }
989
990 #undef msleep
991 /**
992  * Waits for an interval of time.
993  * @param delay how long to wait (in microseconds)
994  */
995 void msleep (mtime_t delay)
996 {
997     vlc_clock_setup ();
998
999     lldiv_t d = lldiv (delay, 1000000);
1000     struct timespec ts = { d.quot, d.rem * 1000 };
1001
1002 #if (_POSIX_TIMERS > 0)
1003     while (clock_nanosleep (vlc_clock_id, 0, &ts, &ts) == EINTR);
1004
1005 #else
1006     while (nanosleep (&ts, &ts) == -1)
1007         assert (errno == EINTR);
1008
1009 #endif
1010 }
1011
1012
1013 struct vlc_timer
1014 {
1015     vlc_thread_t thread;
1016     vlc_cond_t   reschedule;
1017     vlc_mutex_t  lock;
1018     void       (*func) (void *);
1019     void        *data;
1020     mtime_t      value, interval;
1021     vlc_atomic_t overruns;
1022 };
1023
1024 static void *vlc_timer_thread (void *data)
1025 {
1026     struct vlc_timer *timer = data;
1027
1028     vlc_mutex_lock (&timer->lock);
1029     mutex_cleanup_push (&timer->lock);
1030
1031     for (;;)
1032     {
1033         while (timer->value == 0)
1034             vlc_cond_wait (&timer->reschedule, &timer->lock);
1035
1036         if (vlc_cond_timedwait (&timer->reschedule, &timer->lock,
1037                                 timer->value) == 0)
1038             continue;
1039         if (timer->interval == 0)
1040             timer->value = 0; /* disarm */
1041         vlc_mutex_unlock (&timer->lock);
1042
1043         int canc = vlc_savecancel ();
1044         timer->func (timer->data);
1045         vlc_restorecancel (canc);
1046
1047         mtime_t now = mdate ();
1048         unsigned misses;
1049
1050         vlc_mutex_lock (&timer->lock);
1051         if (timer->interval == 0)
1052             continue;
1053
1054         misses = (now - timer->value) / timer->interval;
1055         timer->value += timer->interval;
1056         /* Try to compensate for one miss (mwait() will return immediately)
1057          * but no more. Otherwise, we might busy loop, after extended periods
1058          * without scheduling (suspend, SIGSTOP, RT preemption, ...). */
1059         if (misses > 1)
1060         {
1061             misses--;
1062             timer->value += misses * timer->interval;
1063             vlc_atomic_add (&timer->overruns, misses);
1064         }
1065     }
1066
1067     vlc_cleanup_pop ();
1068     assert (0);
1069 }
1070
1071 /**
1072  * Initializes an asynchronous timer.
1073  * @warning Asynchronous timers are processed from an unspecified thread.
1074  * Multiple occurences of a single interval timer are serialized; they cannot
1075  * run concurrently.
1076  *
1077  * @param id pointer to timer to be initialized
1078  * @param func function that the timer will call
1079  * @param data parameter for the timer function
1080  * @return 0 on success, a system error code otherwise.
1081  */
1082 int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
1083 {
1084     struct vlc_timer *timer = malloc (sizeof (*timer));
1085
1086     if (unlikely(timer == NULL))
1087         return ENOMEM;
1088     vlc_mutex_init (&timer->lock);
1089     vlc_cond_init (&timer->reschedule);
1090     assert (func);
1091     timer->func = func;
1092     timer->data = data;
1093     timer->value = 0;
1094     timer->interval = 0;
1095     vlc_atomic_set(&timer->overruns, 0);
1096
1097     if (vlc_clone (&timer->thread, vlc_timer_thread, timer,
1098                    VLC_THREAD_PRIORITY_INPUT))
1099     {
1100         vlc_cond_destroy (&timer->reschedule);
1101         vlc_mutex_destroy (&timer->lock);
1102         free (timer);
1103         return ENOMEM;
1104     }
1105
1106     *id = timer;
1107     return 0;
1108 }
1109
1110 /**
1111  * Destroys an initialized timer. If needed, the timer is first disarmed.
1112  * This function is undefined if the specified timer is not initialized.
1113  *
1114  * @warning This function <b>must</b> be called before the timer data can be
1115  * freed and before the timer callback function can be unloaded.
1116  *
1117  * @param timer timer to destroy
1118  */
1119 void vlc_timer_destroy (vlc_timer_t timer)
1120 {
1121     vlc_cancel (timer->thread);
1122     vlc_join (timer->thread, NULL);
1123     vlc_cond_destroy (&timer->reschedule);
1124     vlc_mutex_destroy (&timer->lock);
1125     free (timer);
1126 }
1127
1128 /**
1129  * Arm or disarm an initialized timer.
1130  * This functions overrides any previous call to itself.
1131  *
1132  * @note A timer can fire later than requested due to system scheduling
1133  * limitations. An interval timer can fail to trigger sometimes, either because
1134  * the system is busy or suspended, or because a previous iteration of the
1135  * timer is still running. See also vlc_timer_getoverrun().
1136  *
1137  * @param timer initialized timer
1138  * @param absolute the timer value origin is the same as mdate() if true,
1139  *                 the timer value is relative to now if false.
1140  * @param value zero to disarm the timer, otherwise the initial time to wait
1141  *              before firing the timer.
1142  * @param interval zero to fire the timer just once, otherwise the timer
1143  *                 repetition interval.
1144  */
1145 void vlc_timer_schedule (vlc_timer_t timer, bool absolute,
1146                          mtime_t value, mtime_t interval)
1147 {
1148     if (!absolute && value != 0)
1149         value += mdate();
1150
1151     vlc_mutex_lock (&timer->lock);
1152     timer->value = value;
1153     timer->interval = interval;
1154     vlc_cond_signal (&timer->reschedule);
1155     vlc_mutex_unlock (&timer->lock);
1156 }
1157
1158 /**
1159  * Fetch and reset the overrun counter for a timer.
1160  * @param timer initialized timer
1161  * @return the timer overrun counter, i.e. the number of times that the timer
1162  * should have run but did not since the last actual run. If all is well, this
1163  * is zero.
1164  */
1165 unsigned vlc_timer_getoverrun (vlc_timer_t timer)
1166 {
1167     return vlc_atomic_swap (&timer->overruns, 0);
1168 }
1169
1170
1171 /**
1172  * Count CPUs.
1173  * @return number of available (logical) CPUs.
1174  */
1175 unsigned vlc_GetCPUCount(void)
1176 {
1177 #if defined(HAVE_SCHED_GETAFFINITY)
1178     cpu_set_t cpu;
1179
1180     CPU_ZERO(&cpu);
1181     if (sched_getaffinity (getpid(), sizeof (cpu), &cpu) < 0)
1182         return 1;
1183
1184     return CPU_COUNT (&cpu);
1185
1186 #elif defined(__APPLE__)
1187     int count;
1188     size_t size = sizeof(count) ;
1189
1190     if (sysctlbyname ("hw.ncpu", &count, &size, NULL, 0))
1191         return 1; /* Failure */
1192     return count;
1193
1194 #elif defined(__OpenBSD__)
1195     int selectors[2] = { CTL_HW, HW_NCPU };
1196     int count;
1197     size_t size = sizeof(count);
1198
1199     if (sysctl (selectors, 2, &count, &size, NULL, 0))
1200         return 1; /* Failure */
1201     return count;
1202
1203 #elif defined(__SunOS)
1204     unsigned count = 0;
1205     int type;
1206     u_int numcpus;
1207     processor_info_t cpuinfo;
1208
1209     processorid_t *cpulist = malloc (sizeof (*cpulist) * sysconf(_SC_NPROCESSORS_MAX));
1210     if (unlikely(cpulist == NULL))
1211         return 1;
1212
1213     if (pset_info(PS_MYID, &type, &numcpus, cpulist) == 0)
1214     {
1215         for (u_int i = 0; i < numcpus; i++)
1216             if (processor_info (cpulist[i], &cpuinfo) == 0)
1217                 count += (cpuinfo.pi_state == P_ONLINE);
1218     }
1219     else
1220         count = sysconf (_SC_NPROCESSORS_ONLN);
1221     free (cpulist);
1222     return count ? count : 1;
1223
1224 #else
1225 #   warning "vlc_GetCPUCount is not implemented for your platform"
1226     return 1;
1227 #endif
1228 }