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