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