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