1 /*****************************************************************************
2 * threads.h : threads implementation for the VideoLAN client
3 * This header provides a portable threads implementation.
4 *****************************************************************************
5 * Copyright (C) 1999, 2000 VideoLAN
6 * $Id: threads.h,v 1.35 2002/02/25 23:59:07 sam Exp $
8 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
9 * Samuel Hocevar <sam@via.ecp.fr>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
28 #if defined(GPROF) || defined(DEBUG)
29 # include <sys/time.h>
32 #if defined( PTH_INIT_IN_PTH_H ) /* GNU Pth */
35 #elif defined( ST_INIT_IN_ST_H ) /* State threads */
38 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) /* pthreads (like Linux & BSD) */
40 /* This is not prototyped under Linux, though it exists. */
41 int pthread_mutexattr_setkind_np( pthread_mutexattr_t *attr, int kind );
43 #elif defined( HAVE_CTHREADS_H ) /* GNUMach */
44 # include <cthreads.h>
46 #elif defined( HAVE_KERNEL_SCHEDULER_H ) /* BeOS */
49 # include <kernel/OS.h>
50 # include <kernel/scheduler.h>
51 # include <byteorder.h>
53 #elif defined( WIN32 )
54 #define WIN32_LEAN_AND_MEAN
59 # error no threads available on your system !
63 /*****************************************************************************
65 *****************************************************************************
66 * These constants are used by all threads in *_CreateThread() and
67 * *_DestroyThreads() functions. Since those calls are non-blocking, an integer
68 * value is used as a shared flag to represent the status of the thread.
69 *****************************************************************************/
71 /* Void status - this value can be used to make sure no operation is currently
72 * in progress on the concerned thread in an array of recorded threads */
73 #define THREAD_NOP 0 /* nothing happened */
76 #define THREAD_CREATE 10 /* thread is initializing */
77 #define THREAD_START 11 /* thread has forked */
78 #define THREAD_READY 19 /* thread is ready */
80 /* Destructions status */
81 #define THREAD_DESTROY 20 /* destruction order has been sent */
82 #define THREAD_END 21 /* destruction order has been received */
83 #define THREAD_OVER 29 /* thread does not exist any more */
86 #define THREAD_ERROR 30 /* an error occured */
87 #define THREAD_FATAL 31 /* an fatal error occured - program must end */
89 /*****************************************************************************
91 *****************************************************************************/
93 #if defined( PTH_INIT_IN_PTH_H )
94 typedef pth_t vlc_thread_t;
95 typedef pth_mutex_t vlc_mutex_t;
96 typedef pth_cond_t vlc_cond_t;
98 #elif defined( ST_INIT_IN_ST_H )
99 typedef st_thread_t * vlc_thread_t;
100 typedef st_mutex_t * vlc_mutex_t;
101 typedef st_cond_t * vlc_cond_t;
103 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
104 typedef pthread_t vlc_thread_t;
105 typedef pthread_mutex_t vlc_mutex_t;
106 typedef pthread_cond_t vlc_cond_t;
108 #elif defined( HAVE_CTHREADS_H )
109 typedef cthread_t vlc_thread_t;
111 /* Those structs are the ones defined in /include/cthreads.h but we need
112 * to handle (*foo) where foo is a (mutex_t) while they handle (foo) where
113 * foo is a (mutex_t*) */
114 typedef struct s_mutex {
118 struct cthread_queue queue;
121 typedef struct s_condition {
123 struct cthread_queue queue;
125 struct cond_imp *implications;
128 #elif defined( HAVE_KERNEL_SCHEDULER_H )
129 /* This is the BeOS implementation of the vlc threads, note that the mutex is
130 * not a real mutex and the cond_var is not like a pthread cond_var but it is
131 * enough for what wee need */
133 typedef thread_id vlc_thread_t;
147 #elif defined( WIN32 )
148 typedef HANDLE vlc_thread_t;
149 typedef CRITICAL_SECTION vlc_mutex_t;
153 int i_waiting_threads;
157 typedef unsigned (__stdcall *PTHREAD_START) (void *);
161 typedef void *(*vlc_thread_func_t)(void *p_data);
163 /*****************************************************************************
165 *****************************************************************************/
168 /* Wrapper function for profiling */
169 static void * vlc_thread_wrapper ( void *p_wrapper );
173 # define ITIMER_REAL 1
174 # define ITIMER_PROF 2
178 struct timeval it_value;
179 struct timeval it_interval;
182 int setitimer(int kind, const struct itimerval* itnew, struct itimerval* itold);
186 typedef struct wrapper_s
188 /* Data lock access */
192 /* Data used to spawn the real thread */
193 vlc_thread_func_t func;
196 /* Profiling timer passed to the thread */
197 struct itimerval itimer;
203 /*****************************************************************************
204 * vlc_threads_init: initialize threads system
205 *****************************************************************************/
206 static __inline__ int vlc_threads_init( void )
208 #if defined( PTH_INIT_IN_PTH_H )
211 #elif defined( ST_INIT_IN_ST_H )
214 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
217 #elif defined( HAVE_CTHREADS_H )
220 #elif defined( HAVE_KERNEL_SCHEDULER_H )
223 #elif defined( WIN32 )
229 /*****************************************************************************
230 * vlc_threads_end: stop threads system
231 *****************************************************************************/
232 static __inline__ int vlc_threads_end( void )
234 #if defined( PTH_INIT_IN_PTH_H )
237 #elif defined( ST_INIT_IN_ST_H )
240 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
243 #elif defined( HAVE_CTHREADS_H )
246 #elif defined( HAVE_KERNEL_SCHEDULER_H )
249 #elif defined( WIN32 )
255 /*****************************************************************************
256 * vlc_mutex_init: initialize a mutex
257 *****************************************************************************/
258 static __inline__ int vlc_mutex_init( vlc_mutex_t *p_mutex )
260 #if defined( PTH_INIT_IN_PTH_H )
261 return pth_mutex_init( p_mutex );
263 #elif defined( ST_INIT_IN_ST_H )
264 *p_mutex = st_mutex_new();
265 return ( *p_mutex == NULL ) ? errno : 0;
267 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
268 # if defined(DEBUG) && defined(SYS_LINUX)
269 /* Create error-checking mutex to detect threads problems more easily. */
270 pthread_mutexattr_t attr;
273 pthread_mutexattr_init( &attr );
274 pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
275 i_result = pthread_mutex_init( p_mutex, &attr );
276 pthread_mutexattr_destroy( &attr );
280 return pthread_mutex_init( p_mutex, NULL );
282 #elif defined( HAVE_CTHREADS_H )
283 mutex_init( p_mutex );
286 #elif defined( HAVE_KERNEL_SCHEDULER_H )
288 /* check the arguments and whether it's already been initialized */
289 if( p_mutex == NULL )
294 if( p_mutex->init == 9999 )
299 p_mutex->lock = create_sem( 1, "BeMutex" );
300 if( p_mutex->lock < B_NO_ERROR )
305 p_mutex->init = 9999;
308 #elif defined( WIN32 )
309 InitializeCriticalSection( p_mutex );
315 /*****************************************************************************
316 * vlc_mutex_lock: lock a mutex
317 *****************************************************************************/
319 # define vlc_mutex_lock( P_MUTEX ) \
320 _vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )
322 # define vlc_mutex_lock( P_MUTEX ) \
323 _vlc_mutex_lock( NULL, 0, P_MUTEX )
326 static __inline__ int _vlc_mutex_lock( char * psz_file, int i_line,
327 vlc_mutex_t *p_mutex )
329 #if defined( PTH_INIT_IN_PTH_H )
330 return pth_mutex_acquire( p_mutex, TRUE, NULL );
332 #elif defined( ST_INIT_IN_ST_H )
333 return st_mutex_lock( *p_mutex );
335 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
336 int i_return = pthread_mutex_lock( p_mutex );
339 intf_ErrMsg( "thread %d error: mutex_lock failed at %s:%d (%s)",
340 pthread_self(), psz_file, i_line, strerror(i_return) );
344 #elif defined( HAVE_CTHREADS_H )
345 mutex_lock( p_mutex );
348 #elif defined( HAVE_KERNEL_SCHEDULER_H )
356 if( p_mutex->init < 2000 )
361 err = acquire_sem( p_mutex->lock );
364 #elif defined( WIN32 )
365 EnterCriticalSection( p_mutex );
371 /*****************************************************************************
372 * vlc_mutex_unlock: unlock a mutex
373 *****************************************************************************/
375 # define vlc_mutex_unlock( P_MUTEX ) \
376 _vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )
378 # define vlc_mutex_unlock( P_MUTEX ) \
379 _vlc_mutex_unlock( NULL, 0, P_MUTEX )
382 static __inline__ int _vlc_mutex_unlock( char * psz_file, int i_line,
383 vlc_mutex_t *p_mutex )
385 #if defined( PTH_INIT_IN_PTH_H )
386 return pth_mutex_release( p_mutex );
388 #elif defined( ST_INIT_IN_ST_H )
389 return st_mutex_unlock( *p_mutex );
391 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
392 int i_return = pthread_mutex_unlock( p_mutex );
395 intf_ErrMsg( "thread %d error: mutex_unlock failed at %s:%d (%s)",
396 pthread_self(), psz_file, i_line, strerror(i_return) );
400 #elif defined( HAVE_CTHREADS_H )
401 mutex_unlock( p_mutex );
404 #elif defined( HAVE_KERNEL_SCHEDULER_H )
410 if( p_mutex->init < 2000 )
415 release_sem( p_mutex->lock );
418 #elif defined( WIN32 )
419 LeaveCriticalSection( p_mutex );
425 /*****************************************************************************
426 * vlc_mutex_destroy: destroy a mutex
427 *****************************************************************************/
429 # define vlc_mutex_destroy( P_MUTEX ) \
430 _vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )
432 # define vlc_mutex_destroy( P_MUTEX ) \
433 _vlc_mutex_destroy( NULL, 0, P_MUTEX )
436 static __inline__ int _vlc_mutex_destroy( char * psz_file, int i_line,
437 vlc_mutex_t *p_mutex )
439 #if defined( PTH_INIT_IN_PTH_H )
442 #elif defined( ST_INIT_IN_ST_H )
443 return st_mutex_destroy( *p_mutex );
445 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
446 int i_return = pthread_mutex_destroy( p_mutex );
449 intf_ErrMsg( "thread %d error: mutex_destroy failed at %s:%d (%s)",
450 pthread_self(), psz_file, i_line, strerror(i_return) );
454 #elif defined( HAVE_CTHREADS_H )
457 #elif defined( HAVE_KERNEL_SCHEDULER_H )
458 if( p_mutex->init == 9999 )
460 delete_sem( p_mutex->lock );
466 #elif defined( WIN32 )
467 DeleteCriticalSection( p_mutex );
473 /*****************************************************************************
474 * vlc_cond_init: initialize a condition
475 *****************************************************************************/
476 static __inline__ int vlc_cond_init( vlc_cond_t *p_condvar )
478 #if defined( PTH_INIT_IN_PTH_H )
479 return pth_cond_init( p_condvar );
481 #elif defined( ST_INIT_IN_ST_H )
482 *p_condvar = st_cond_new();
483 return ( *p_condvar == NULL ) ? errno : 0;
485 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
486 return pthread_cond_init( p_condvar, NULL );
488 #elif defined( HAVE_CTHREADS_H )
489 /* condition_init() */
490 spin_lock_init( &p_condvar->lock );
491 cthread_queue_init( &p_condvar->queue );
493 p_condvar->implications = 0;
497 #elif defined( HAVE_KERNEL_SCHEDULER_H )
503 if( p_condvar->init == 9999 )
508 p_condvar->thread = -1;
509 p_condvar->init = 9999;
512 #elif defined( WIN32 )
513 /* initialise counter */
514 p_condvar->i_waiting_threads = 0;
516 /* Create an auto-reset event. */
517 p_condvar->signal = CreateEvent( NULL, /* no security */
518 FALSE, /* auto-reset event */
519 FALSE, /* non-signaled initially */
520 NULL ); /* unnamed */
522 return( !p_condvar->signal );
527 /*****************************************************************************
528 * vlc_cond_signal: start a thread on condition completion
529 *****************************************************************************/
530 static __inline__ int vlc_cond_signal( vlc_cond_t *p_condvar )
532 #if defined( PTH_INIT_IN_PTH_H )
533 return pth_cond_notify( p_condvar, FALSE );
535 #elif defined( ST_INIT_IN_ST_H )
536 return st_cond_signal( *p_condvar );
538 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
539 return pthread_cond_signal( p_condvar );
541 #elif defined( HAVE_CTHREADS_H )
542 /* condition_signal() */
543 if ( p_condvar->queue.head || p_condvar->implications )
545 cond_signal( (condition_t)p_condvar );
549 #elif defined( HAVE_KERNEL_SCHEDULER_H )
555 if( p_condvar->init < 2000 )
560 while( p_condvar->thread != -1 )
563 if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
568 if( info.state != B_THREAD_SUSPENDED )
570 /* The waiting thread is not suspended so it could
571 * have been interrupted beetwen the unlock and the
572 * suspend_thread line. That is why we sleep a little
573 * before retesting p_condver->thread. */
578 /* Ok, we have to wake up that thread */
579 resume_thread( p_condvar->thread );
585 #elif defined( WIN32 )
586 /* Release one waiting thread if one is available. */
587 /* For this trick to work properly, the vlc_cond_signal must be surrounded
588 * by a mutex. This will prevent another thread from stealing the signal */
589 int i_waiting_threads = p_condvar->i_waiting_threads;
590 while( p_condvar->i_waiting_threads
591 && p_condvar->i_waiting_threads == i_waiting_threads )
593 PulseEvent( p_condvar->signal );
594 Sleep( 0 ); /* deschedule the current thread */
601 /*****************************************************************************
602 * vlc_cond_broadcast: start all threads waiting on condition completion
603 *****************************************************************************/
605 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
606 * Only works with pthreads, you need to adapt it for others
607 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
609 static __inline__ int vlc_cond_broadcast( vlc_cond_t *p_condvar )
611 #if defined( PTH_INIT_IN_PTH_H )
612 return pth_cond_notify( p_condvar, FALSE );
614 #elif defined( ST_INIT_IN_ST_H )
615 return st_cond_broadcast( p_condvar );
617 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
618 return pthread_cond_broadcast( p_condvar );
620 #elif defined( HAVE_CTHREADS_H )
621 /* condition_signal() */
622 if ( p_condvar->queue.head || p_condvar->implications )
624 cond_signal( (condition_t)p_condvar );
628 #elif defined( HAVE_KERNEL_SCHEDULER_H )
634 if( p_condvar->init < 2000 )
639 while( p_condvar->thread != -1 )
642 if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
647 if( info.state != B_THREAD_SUSPENDED )
649 /* The waiting thread is not suspended so it could
650 * have been interrupted beetwen the unlock and the
651 * suspend_thread line. That is why we sleep a little
652 * before retesting p_condver->thread. */
657 /* Ok, we have to wake up that thread */
658 resume_thread( p_condvar->thread );
664 #elif defined( WIN32 )
665 /* Release all waiting threads. */
666 /* For this trick to work properly, the vlc_cond_signal must be surrounded
667 * by a mutex. This will prevent another thread from stealing the signal */
668 while( p_condvar->i_waiting_threads )
670 PulseEvent( p_condvar->signal );
671 Sleep( 0 ); /* deschedule the current thread */
678 /*****************************************************************************
679 * vlc_cond_wait: wait until condition completion
680 *****************************************************************************/
682 # define vlc_cond_wait( P_COND, P_MUTEX ) \
683 _vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX )
685 # define vlc_cond_wait( P_COND, P_MUTEX ) \
686 _vlc_cond_wait( NULL, 0, P_COND, P_MUTEX )
689 static __inline__ int _vlc_cond_wait( char * psz_file, int i_line,
690 vlc_cond_t *p_condvar,
691 vlc_mutex_t *p_mutex )
693 #if defined( PTH_INIT_IN_PTH_H )
694 return pth_cond_await( p_condvar, p_mutex, NULL );
696 #elif defined( ST_INIT_IN_ST_H )
699 st_mutex_unlock( *p_mutex );
700 i_ret = st_cond_wait( *p_condvar );
701 st_mutex_lock( *p_mutex );
705 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
708 return pthread_cond_wait( p_condvar, p_mutex );
710 /* In debug mode, timeout */
712 struct timespec timeout;
717 gettimeofday( &now, NULL );
718 timeout.tv_sec = now.tv_sec + THREAD_COND_TIMEOUT;
719 timeout.tv_nsec = now.tv_usec * 1000;
721 if( (i_result = pthread_cond_timedwait( p_condvar, p_mutex, &timeout )) )
723 intf_WarnMsg( 1, "thread %d warning: Possible deadlock detected in cond_wait at %s:%d (%s)",
724 pthread_self(), psz_file, i_line, strerror(i_result) );
733 #elif defined( HAVE_CTHREADS_H )
734 condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
737 #elif defined( HAVE_KERNEL_SCHEDULER_H )
748 if( p_condvar->init < 2000 )
753 /* The p_condvar->thread var is initialized before the unlock because
754 * it enables to identify when the thread is interrupted beetwen the
755 * unlock line and the suspend_thread line */
756 p_condvar->thread = find_thread( NULL );
757 vlc_mutex_unlock( p_mutex );
758 suspend_thread( p_condvar->thread );
759 p_condvar->thread = -1;
761 vlc_mutex_lock( p_mutex );
764 #elif defined( WIN32 )
765 /* The ideal would be to use a function which atomically releases the
766 * mutex and initiate the waiting.
767 * Unfortunately only the SignalObjectAndWait function does this and it's
768 * only supported on WinNT/2K, furthermore it cannot take multiple
769 * events as parameters.
771 * The solution we use should however fulfill all our needs (even though
772 * it is not a correct pthreads implementation)
776 p_condvar->i_waiting_threads ++;
778 /* Release the mutex */
779 vlc_mutex_unlock( p_mutex );
781 i_result = WaitForSingleObject( p_condvar->signal, INFINITE);
783 /* maybe we should protect this with a mutex ? */
784 p_condvar->i_waiting_threads --;
786 /* Reacquire the mutex before returning. */
787 vlc_mutex_lock( p_mutex );
789 return( i_result == WAIT_FAILED );
794 /*****************************************************************************
795 * vlc_cond_destroy: destroy a condition
796 *****************************************************************************/
798 # define vlc_cond_destroy( P_COND ) \
799 _vlc_cond_destroy( __FILE__, __LINE__, P_COND )
801 # define vlc_cond_destroy( P_COND ) \
802 _vlc_cond_destroy( NULL, 0, P_COND )
805 static __inline__ int _vlc_cond_destroy( char * psz_file, int i_line,
806 vlc_cond_t *p_condvar )
808 #if defined( PTH_INIT_IN_PTH_H )
811 #elif defined( ST_INIT_IN_ST_H )
812 return st_cond_destroy( *p_condvar );
814 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
815 int i_result = pthread_cond_destroy( p_condvar );
818 intf_ErrMsg( "thread %d error: cond_destroy failed at %s:%d (%s)",
819 pthread_self(), psz_file, i_line, strerror(i_result) );
823 #elif defined( HAVE_CTHREADS_H )
826 #elif defined( HAVE_KERNEL_SCHEDULER_H )
830 #elif defined( WIN32 )
831 return( !CloseHandle( p_condvar->signal ) );
836 /*****************************************************************************
837 * vlc_thread_create: create a thread
838 *****************************************************************************/
840 # define vlc_thread_create( P_THREAD, PSZ_NAME, FUNC, P_DATA ) \
841 _vlc_thread_create( __FILE__, __LINE__, P_THREAD, PSZ_NAME, FUNC, P_DATA )
843 # define vlc_thread_create( P_THREAD, PSZ_NAME, FUNC, P_DATA ) \
844 _vlc_thread_create( NULL, 0, P_THREAD, PSZ_NAME, FUNC, P_DATA )
847 static __inline__ int _vlc_thread_create( char * psz_file, int i_line,
848 vlc_thread_t *p_thread,
850 vlc_thread_func_t func,
858 /* Initialize the wrapper structure */
860 wrapper.p_data = p_data;
861 getitimer( ITIMER_PROF, &wrapper.itimer );
862 vlc_mutex_init( &wrapper.lock );
863 vlc_cond_init( &wrapper.wait );
864 vlc_mutex_lock( &wrapper.lock );
866 /* Alter user-passed data so that we call the wrapper instead
867 * of the real function */
869 func = vlc_thread_wrapper;
872 #if defined( PTH_INIT_IN_PTH_H )
873 *p_thread = pth_spawn( PTH_ATTR_DEFAULT, func, p_data );
874 i_ret = ( p_thread == NULL );
876 #elif defined( ST_INIT_IN_ST_H )
877 *p_thread = st_thread_create( func, p_data, 1, 0 );
878 i_ret = ( p_thread == NULL );
880 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
881 i_ret = pthread_create( p_thread, NULL, func, p_data );
883 #elif defined( HAVE_CTHREADS_H )
884 *p_thread = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
887 #elif defined( HAVE_KERNEL_SCHEDULER_H )
888 *p_thread = spawn_thread( (thread_func)func, psz_name,
889 B_NORMAL_PRIORITY, p_data );
890 i_ret = resume_thread( *p_thread );
892 #elif defined( WIN32 )
895 /* This method is not recommended when using the MSVCRT C library,
896 * so we'll have to use _beginthreadex instead */
897 *p_thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) func,
898 p_data, 0, &threadID);
901 /* When using the MSVCRT C library you have to use the _beginthreadex
902 * function instead of CreateThread, otherwise you'll end up with memory
903 * leaks and the signal function not working */
904 *p_thread = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START) func,
905 p_data, 0, &threadID);
907 i_ret = ( *p_thread ? 0 : 1 );
914 vlc_cond_wait( &wrapper.wait, &wrapper.lock );
917 vlc_mutex_unlock( &wrapper.lock );
918 vlc_mutex_destroy( &wrapper.lock );
919 vlc_cond_destroy( &wrapper.wait );
924 intf_WarnMsg( 2, "thread info: %d (%s) has been created (%s:%d)",
925 *p_thread, psz_name, psz_file, i_line );
929 intf_ErrMsg( "thread error: %s couldn't be created at %s:%d (%s)",
930 psz_name, psz_file, i_line, strerror(i_ret) );
936 /*****************************************************************************
937 * vlc_thread_exit: terminate a thread
938 *****************************************************************************/
939 static __inline__ void vlc_thread_exit( void )
941 #if defined( PTH_INIT_IN_PTH_H )
944 #elif defined( ST_INIT_IN_ST_H )
946 st_thread_exit( &result );
948 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
951 #elif defined( HAVE_CTHREADS_H )
953 cthread_exit( &result );
955 #elif defined( HAVE_KERNEL_SCHEDULER_H )
958 #elif defined( WIN32 )
962 /* For now we don't close the thread handles (because of race conditions).
963 * Need to be looked at. */
969 /*****************************************************************************
970 * vlc_thread_join: wait until a thread exits
971 *****************************************************************************/
973 # define vlc_thread_join( THREAD ) \
974 _vlc_thread_join( __FILE__, __LINE__, THREAD )
976 # define vlc_thread_join( THREAD ) \
977 _vlc_thread_join( NULL, 0, THREAD )
980 static __inline__ void _vlc_thread_join( char * psz_file, int i_line,
981 vlc_thread_t thread )
985 #if defined( PTH_INIT_IN_PTH_H )
986 i_ret = pth_join( thread, NULL );
988 #elif defined( ST_INIT_IN_ST_H )
989 i_ret = st_thread_join( thread, NULL );
991 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
992 i_ret = pthread_join( thread, NULL );
994 #elif defined( HAVE_CTHREADS_H )
995 cthread_join( thread );
998 #elif defined( HAVE_KERNEL_SCHEDULER_H )
1000 wait_for_thread( thread, &exit_value );
1002 #elif defined( WIN32 )
1003 WaitForSingleObject( thread, INFINITE );
1009 intf_ErrMsg( "thread error: thread_join(%d) failed at %s:%d (%s)",
1010 thread, psz_file, i_line, strerror(i_ret) );
1014 intf_WarnMsg( 2, "thread info: %d has been joined (%s:%d)",
1015 thread, psz_file, i_line );
1020 static void *vlc_thread_wrapper( void *p_wrapper )
1022 /* Put user data in thread-local variables */
1023 void * p_data = ((wrapper_t*)p_wrapper)->p_data;
1024 vlc_thread_func_t func = ((wrapper_t*)p_wrapper)->func;
1026 /* Set the profile timer value */
1027 setitimer( ITIMER_PROF, &((wrapper_t*)p_wrapper)->itimer, NULL );
1029 /* Tell the calling thread that we don't need its data anymore */
1030 vlc_mutex_lock( &((wrapper_t*)p_wrapper)->lock );
1031 vlc_cond_signal( &((wrapper_t*)p_wrapper)->wait );
1032 vlc_mutex_unlock( &((wrapper_t*)p_wrapper)->lock );
1034 /* Call the real function */
1035 return func( p_data );