1 /*****************************************************************************
2 * vlc_threads_funcs.h : threads implementation for the VideoLAN client
3 * This header provides a portable threads implementation.
4 *****************************************************************************
5 * Copyright (C) 1999-2007 the VideoLAN team
8 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
9 * Samuel Hocevar <sam@via.ecp.fr>
10 * Gildas Bazin <gbazin@netcourrier.com>
11 * Christophe Massiot <massiot@via.ecp.fr>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 #if !defined( __LIBVLC__ )
29 #error You are not libvlc or one of its plugins. You cannot include this file
32 #ifndef _VLC_THREADFUNCS_H_
33 #define _VLC_THREADFUNCS_H_
35 /*****************************************************************************
36 * Function definitions
37 *****************************************************************************/
38 VLC_EXPORT( void, __vlc_threads_error, ( vlc_object_t *) );
39 VLC_EXPORT( int, __vlc_mutex_init, ( vlc_object_t *, vlc_mutex_t * ) );
40 VLC_EXPORT( int, __vlc_mutex_init_recursive, ( vlc_object_t *, vlc_mutex_t * ) );
41 VLC_EXPORT( int, __vlc_mutex_destroy, ( const char *, int, vlc_mutex_t * ) );
42 VLC_EXPORT( int, __vlc_cond_init, ( vlc_object_t *, vlc_cond_t * ) );
43 VLC_EXPORT( int, __vlc_cond_destroy, ( const char *, int, vlc_cond_t * ) );
44 VLC_EXPORT( int, __vlc_threadvar_create, (vlc_object_t *, vlc_threadvar_t * ) );
45 VLC_EXPORT( int, __vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( void * ), int, vlc_bool_t ) );
46 VLC_EXPORT( int, __vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) );
47 VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) );
48 VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, const char *, int ) );
50 /*****************************************************************************
51 * vlc_threads_error: Signalize an error in the threading system
52 *****************************************************************************/
53 #define vlc_threads_error( P_THIS ) \
54 __vlc_threads_error( VLC_OBJECT(P_THIS) )
56 /*****************************************************************************
57 * vlc_threads_init: initialize threads system
58 *****************************************************************************/
59 #define vlc_threads_init( P_THIS ) \
60 __vlc_threads_init( VLC_OBJECT(P_THIS) )
62 /*****************************************************************************
63 * vlc_threads_end: deinitialize threads system
64 *****************************************************************************/
65 #define vlc_threads_end( P_THIS ) \
66 __vlc_threads_end( VLC_OBJECT(P_THIS) )
68 /*****************************************************************************
69 * vlc_mutex_init: initialize a mutex
70 *****************************************************************************/
71 #define vlc_mutex_init( P_THIS, P_MUTEX ) \
72 __vlc_mutex_init( VLC_OBJECT(P_THIS), P_MUTEX )
74 /*****************************************************************************
75 * vlc_mutex_init: initialize a recursive mutex (Don't use it)
76 *****************************************************************************/
77 #define vlc_mutex_init_recursive( P_THIS, P_MUTEX ) \
78 __vlc_mutex_init_recursive( VLC_OBJECT(P_THIS), P_MUTEX )
80 /*****************************************************************************
81 * vlc_mutex_lock: lock a mutex
82 *****************************************************************************/
83 #define vlc_mutex_lock( P_MUTEX ) \
84 __vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )
86 #if defined( PTHREAD_COND_T_IN_PTHREAD_H )
87 static inline unsigned long int CAST_PTHREAD_TO_INT (pthread_t th)
89 union { pthread_t th; unsigned long int i; } v = { };
95 static inline int __vlc_mutex_lock( const char * psz_file, int i_line,
96 vlc_mutex_t * p_mutex )
99 /* In case of error : */
100 unsigned long int i_thread = 0;
102 #if defined( PTH_INIT_IN_PTH_H )
103 i_result = ( pth_mutex_acquire( &p_mutex->mutex, FALSE, NULL ) == FALSE );
105 #elif defined( ST_INIT_IN_ST_H )
106 i_result = st_mutex_lock( p_mutex->mutex );
108 #elif defined( UNDER_CE )
109 EnterCriticalSection( &p_mutex->csection );
112 #elif defined( WIN32 )
115 WaitForSingleObject( p_mutex->mutex, INFINITE );
119 EnterCriticalSection( &p_mutex->csection );
123 #elif defined( HAVE_KERNEL_SCHEDULER_H )
124 if( p_mutex == NULL )
126 i_result = B_BAD_VALUE;
128 else if( p_mutex->init < 2000 )
130 i_result = B_NO_INIT;
134 i_result = acquire_sem( p_mutex->lock );
137 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
138 # define vlc_assert_locked( m ) \
139 assert (pthread_mutex_lock (&((m)->mutex)) == EDEADLK)
141 i_result = pthread_mutex_lock( &p_mutex->mutex );
144 i_thread = CAST_PTHREAD_TO_INT(pthread_self());
148 #elif defined( HAVE_CTHREADS_H )
149 mutex_lock( p_mutex->mutex );
156 msg_Err( p_mutex->p_this,
157 "thread %li: mutex_lock failed at %s:%d (%d:%m)",
158 i_thread, psz_file, i_line, i_result );
159 vlc_threads_error( p_mutex->p_this );
164 #ifndef vlc_assert_locked
165 # define vlc_assert_locked( m ) (void)0
168 /*****************************************************************************
169 * vlc_mutex_unlock: unlock a mutex
170 *****************************************************************************/
171 #define vlc_mutex_unlock( P_MUTEX ) \
172 __vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )
174 static inline int __vlc_mutex_unlock( const char * psz_file, int i_line,
175 vlc_mutex_t *p_mutex )
178 /* In case of error : */
179 unsigned long int i_thread = 0;
181 #if defined( PTH_INIT_IN_PTH_H )
182 i_result = ( pth_mutex_release( &p_mutex->mutex ) == FALSE );
184 #elif defined( ST_INIT_IN_ST_H )
185 i_result = st_mutex_unlock( p_mutex->mutex );
187 #elif defined( UNDER_CE )
188 LeaveCriticalSection( &p_mutex->csection );
191 #elif defined( WIN32 )
194 ReleaseMutex( p_mutex->mutex );
198 LeaveCriticalSection( &p_mutex->csection );
202 #elif defined( HAVE_KERNEL_SCHEDULER_H )
203 if( p_mutex == NULL )
205 i_result = B_BAD_VALUE;
207 else if( p_mutex->init < 2000 )
209 i_result = B_NO_INIT;
213 release_sem( p_mutex->lock );
217 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
218 i_result = pthread_mutex_unlock( &p_mutex->mutex );
221 i_thread = CAST_PTHREAD_TO_INT(pthread_self());
225 #elif defined( HAVE_CTHREADS_H )
226 mutex_unlock( p_mutex );
233 msg_Err( p_mutex->p_this,
234 "thread %li: mutex_unlock failed at %s:%d (%d:%m)",
235 i_thread, psz_file, i_line, i_result );
236 vlc_threads_error( p_mutex->p_this );
242 /*****************************************************************************
243 * vlc_mutex_destroy: destroy a mutex
244 *****************************************************************************/
245 #define vlc_mutex_destroy( P_MUTEX ) \
246 __vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )
248 /*****************************************************************************
249 * vlc_cond_init: initialize a condition
250 *****************************************************************************/
251 #define vlc_cond_init( P_THIS, P_COND ) \
252 __vlc_cond_init( VLC_OBJECT(P_THIS), P_COND )
254 /*****************************************************************************
255 * vlc_cond_signal: start a thread on condition completion
256 *****************************************************************************/
257 #define vlc_cond_signal( P_COND ) \
258 __vlc_cond_signal( __FILE__, __LINE__, P_COND )
260 static inline int __vlc_cond_signal( const char * psz_file, int i_line,
261 vlc_cond_t *p_condvar )
264 /* In case of error : */
265 unsigned long int i_thread = 0;
267 #if defined( PTH_INIT_IN_PTH_H )
268 i_result = ( pth_cond_notify( &p_condvar->cond, FALSE ) == FALSE );
270 #elif defined( ST_INIT_IN_ST_H )
271 i_result = st_cond_signal( p_condvar->cond );
273 #elif defined( UNDER_CE )
274 PulseEvent( p_condvar->event );
277 #elif defined( WIN32 )
278 /* Release one waiting thread if one is available. */
279 /* For this trick to work properly, the vlc_cond_signal must be surrounded
280 * by a mutex. This will prevent another thread from stealing the signal */
281 if( !p_condvar->semaphore )
284 ** PulseEvent() only works if none of the waiting threads is suspended.
285 ** this is particularily problematic under a debug session.
286 ** as documented in http://support.microsoft.com/kb/q173260/
288 PulseEvent( p_condvar->event );
290 else if( p_condvar->i_win9x_cv == 1 )
292 /* Wait for the gate to be open */
293 WaitForSingleObject( p_condvar->event, INFINITE );
295 if( p_condvar->i_waiting_threads )
297 /* Using a semaphore exposes us to a race condition. It is
298 * possible for another thread to start waiting on the semaphore
299 * just after we signaled it and thus steal the signal.
300 * We have to prevent new threads from entering the cond_wait(). */
301 ResetEvent( p_condvar->event );
303 /* A semaphore is used here because Win9x doesn't have
304 * SignalObjectAndWait() and thus a race condition exists
305 * during the time we release the mutex and the time we start
306 * waiting on the event (more precisely, the signal can sometimes
307 * be missed by the waiting thread if we use PulseEvent()). */
308 ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
313 if( p_condvar->i_waiting_threads )
315 ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
317 /* Wait for the last thread to be awakened */
318 WaitForSingleObject( p_condvar->event, INFINITE );
323 #elif defined( HAVE_KERNEL_SCHEDULER_H )
324 if( p_condvar == NULL )
326 i_result = B_BAD_VALUE;
328 else if( p_condvar->init < 2000 )
330 i_result = B_NO_INIT;
334 while( p_condvar->thread != -1 )
337 if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
342 if( info.state != B_THREAD_SUSPENDED )
344 /* The waiting thread is not suspended so it could
345 * have been interrupted beetwen the unlock and the
346 * suspend_thread line. That is why we sleep a little
347 * before retesting p_condver->thread. */
352 /* Ok, we have to wake up that thread */
353 resume_thread( p_condvar->thread );
360 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
361 i_result = pthread_cond_signal( &p_condvar->cond );
364 i_thread = CAST_PTHREAD_TO_INT(pthread_self());
368 #elif defined( HAVE_CTHREADS_H )
369 /* condition_signal() */
370 if ( p_condvar->queue.head || p_condvar->implications )
372 cond_signal( (condition_t)p_condvar );
380 msg_Err( p_condvar->p_this,
381 "thread %li: cond_signal failed at %s:%d (%d:%m)",
382 i_thread, psz_file, i_line, i_result );
383 vlc_threads_error( p_condvar->p_this );
389 /*****************************************************************************
390 * vlc_cond_wait: wait until condition completion
391 *****************************************************************************/
392 #define vlc_cond_wait( P_COND, P_MUTEX ) \
393 __vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX )
395 static inline int __vlc_cond_wait( const char * psz_file, int i_line,
396 vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
399 /* In case of error : */
400 unsigned long int i_thread = 0;
402 #if defined( PTH_INIT_IN_PTH_H )
403 i_result = ( pth_cond_await( &p_condvar->cond, &p_mutex->mutex, NULL )
406 #elif defined( ST_INIT_IN_ST_H )
407 st_mutex_unlock( p_mutex->mutex );
408 i_result = st_cond_wait( p_condvar->cond );
409 st_mutex_lock( p_mutex->mutex );
411 #elif defined( UNDER_CE )
412 p_condvar->i_waiting_threads++;
413 LeaveCriticalSection( &p_mutex->csection );
414 WaitForSingleObject( p_condvar->event, INFINITE );
415 p_condvar->i_waiting_threads--;
417 /* Reacquire the mutex before returning. */
418 vlc_mutex_lock( p_mutex );
422 #elif defined( WIN32 )
423 if( !p_condvar->semaphore )
425 /* Increase our wait count */
426 p_condvar->i_waiting_threads++;
430 /* It is only possible to atomically release the mutex and
431 * initiate the waiting on WinNT/2K/XP. Win9x doesn't have
432 * SignalObjectAndWait(). */
433 p_condvar->SignalObjectAndWait( p_mutex->mutex,
439 LeaveCriticalSection( &p_mutex->csection );
440 WaitForSingleObject( p_condvar->event, INFINITE );
443 p_condvar->i_waiting_threads--;
445 else if( p_condvar->i_win9x_cv == 1 )
447 int i_waiting_threads;
449 /* Wait for the gate to be open */
450 WaitForSingleObject( p_condvar->event, INFINITE );
452 /* Increase our wait count */
453 p_condvar->i_waiting_threads++;
455 LeaveCriticalSection( &p_mutex->csection );
456 WaitForSingleObject( p_condvar->semaphore, INFINITE );
458 /* Decrement and test must be atomic */
459 EnterCriticalSection( &p_condvar->csection );
461 /* Decrease our wait count */
462 i_waiting_threads = --p_condvar->i_waiting_threads;
464 LeaveCriticalSection( &p_condvar->csection );
466 /* Reopen the gate if we were the last waiting thread */
467 if( !i_waiting_threads )
468 SetEvent( p_condvar->event );
472 int i_waiting_threads;
474 /* Increase our wait count */
475 p_condvar->i_waiting_threads++;
477 LeaveCriticalSection( &p_mutex->csection );
478 WaitForSingleObject( p_condvar->semaphore, INFINITE );
480 /* Decrement and test must be atomic */
481 EnterCriticalSection( &p_condvar->csection );
483 /* Decrease our wait count */
484 i_waiting_threads = --p_condvar->i_waiting_threads;
486 LeaveCriticalSection( &p_condvar->csection );
488 /* Signal that the last waiting thread just went through */
489 if( !i_waiting_threads )
490 SetEvent( p_condvar->event );
493 /* Reacquire the mutex before returning. */
494 vlc_mutex_lock( p_mutex );
498 #elif defined( HAVE_KERNEL_SCHEDULER_H )
499 if( p_condvar == NULL )
501 i_result = B_BAD_VALUE;
503 else if( p_mutex == NULL )
505 i_result = B_BAD_VALUE;
507 else if( p_condvar->init < 2000 )
509 i_result = B_NO_INIT;
512 /* The p_condvar->thread var is initialized before the unlock because
513 * it enables to identify when the thread is interrupted beetwen the
514 * unlock line and the suspend_thread line */
515 p_condvar->thread = find_thread( NULL );
516 vlc_mutex_unlock( p_mutex );
517 suspend_thread( p_condvar->thread );
518 p_condvar->thread = -1;
520 vlc_mutex_lock( p_mutex );
523 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
526 /* In debug mode, timeout */
527 struct timespec timeout = {
528 (mdate() / 1000000) + THREAD_COND_TIMEOUT,
529 0 /* 1Hz precision is sufficient here :-) */
532 i_result = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex,
535 if( i_result == ETIMEDOUT )
538 msg_Dbg( p_condvar->p_this,
539 "thread %li: possible condition deadlock "
540 "at %s:%d (%m)", CAST_PTHREAD_TO_INT(pthread_self()),
543 i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
547 i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
552 i_thread = CAST_PTHREAD_TO_INT(pthread_self());
556 #elif defined( HAVE_CTHREADS_H )
557 condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
564 msg_Err( p_condvar->p_this,
565 "thread %li: cond_wait failed at %s:%d (%d:%m)",
566 i_thread, psz_file, i_line, i_result );
567 vlc_threads_error( p_condvar->p_this );
574 /*****************************************************************************
575 * vlc_cond_timedwait: wait until condition completion or expiration
576 *****************************************************************************
577 * Returns 0 if object signaled, an error code in case of timeout or error.
578 *****************************************************************************/
579 #define vlc_cond_timedwait( P_COND, P_MUTEX, DEADLINE ) \
580 __vlc_cond_timedwait( __FILE__, __LINE__, P_COND, P_MUTEX, DEADLINE )
582 static inline int __vlc_cond_timedwait( const char * psz_file, int i_line,
583 vlc_cond_t *p_condvar,
584 vlc_mutex_t *p_mutex,
588 unsigned long int i_thread = 0;
590 #if defined( PTH_INIT_IN_PTH_H )
591 # error Unimplemented
592 #elif defined( ST_INIT_IN_ST_H )
593 # error Unimplemented
594 #elif defined( UNDER_CE )
595 mtime_t delay_ms = (deadline - mdate())/1000;
601 p_condvar->i_waiting_threads++;
602 LeaveCriticalSection( &p_mutex->csection );
603 result = WaitForSingleObject( p_condvar->event, delay_ms );
604 p_condvar->i_waiting_threads--;
606 /* Reacquire the mutex before returning. */
607 vlc_mutex_lock( p_mutex );
611 #elif defined( WIN32 )
614 mtime_t delay_ms = (deadline - mdate())/1000;
618 if( !p_condvar->semaphore )
620 /* Increase our wait count */
621 p_condvar->i_waiting_threads++;
625 /* It is only possible to atomically release the mutex and
626 * initiate the waiting on WinNT/2K/XP. Win9x doesn't have
627 * SignalObjectAndWait(). */
628 result = p_condvar->SignalObjectAndWait( p_mutex->mutex,
634 LeaveCriticalSection( &p_mutex->csection );
635 result = WaitForSingleObject( p_condvar->event, delay_ms );
638 p_condvar->i_waiting_threads--;
640 else if( p_condvar->i_win9x_cv == 1 )
642 int i_waiting_threads;
644 /* Wait for the gate to be open */
645 result = WaitForSingleObject( p_condvar->event, delay_ms );
647 /* Increase our wait count */
648 p_condvar->i_waiting_threads++;
650 LeaveCriticalSection( &p_mutex->csection );
653 /* recaculate remaining delay */
654 delay_ms = (deadline - mdate())/1000;
658 result = WaitForSingleObject( p_condvar->semaphore, delay_ms );
661 /* Decrement and test must be atomic */
662 EnterCriticalSection( &p_condvar->csection );
664 /* Decrease our wait count */
665 i_waiting_threads = --p_condvar->i_waiting_threads;
667 LeaveCriticalSection( &p_condvar->csection );
669 /* Reopen the gate if we were the last waiting thread */
670 if( !i_waiting_threads )
671 SetEvent( p_condvar->event );
675 int i_waiting_threads;
677 /* Increase our wait count */
678 p_condvar->i_waiting_threads++;
680 LeaveCriticalSection( &p_mutex->csection );
681 result = WaitForSingleObject( p_condvar->semaphore, delay_ms );
683 /* Decrement and test must be atomic */
684 EnterCriticalSection( &p_condvar->csection );
686 /* Decrease our wait count */
687 i_waiting_threads = --p_condvar->i_waiting_threads;
689 LeaveCriticalSection( &p_condvar->csection );
691 /* Signal that the last waiting thread just went through */
692 if( !i_waiting_threads )
693 SetEvent( p_condvar->event );
696 /* Reacquire the mutex before returning. */
697 vlc_mutex_lock( p_mutex );
701 #elif defined( HAVE_KERNEL_SCHEDULER_H )
702 # error Unimplemented
703 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
704 lldiv_t d = lldiv( deadline, 1000000 );
705 struct timespec ts = { d.quot, d.rem * 1000 };
707 i_res = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex, &ts );
708 if( i_res == ETIMEDOUT )
709 return ETIMEDOUT; /* this error is perfectly normal */
711 if ( i_res ) /* other errors = bug */
713 i_thread = CAST_PTHREAD_TO_INT(pthread_self());
717 #elif defined( HAVE_CTHREADS_H )
718 # error Unimplemented
723 msg_Err( p_condvar->p_this,
724 "thread %li: cond_wait failed at %s:%d (%d:%m)",
725 i_thread, psz_file, i_line, i_res );
726 vlc_threads_error( p_condvar->p_this );
732 /*****************************************************************************
733 * vlc_cond_destroy: destroy a condition
734 *****************************************************************************/
735 #define vlc_cond_destroy( P_COND ) \
736 __vlc_cond_destroy( __FILE__, __LINE__, P_COND )
738 /*****************************************************************************
739 * vlc_threadvar_create: create a thread-local variable
740 *****************************************************************************/
741 #define vlc_threadvar_create( PTHIS, P_TLS ) \
742 __vlc_threadvar_create( PTHIS, P_TLS )
744 /*****************************************************************************
745 * vlc_threadvar_set: create: set the value of a thread-local variable
746 *****************************************************************************/
747 static inline int vlc_threadvar_set( vlc_threadvar_t * p_tls, void *p_value )
751 #if defined( PTH_INIT_IN_PTH_H )
752 return pth_key_setdata( p_tls->handle, p_value );
753 #elif defined( ST_INIT_IN_ST_H )
754 return st_thread_setspecific( p_tls->handle, p_value );
755 #elif defined( HAVE_KERNEL_SCHEDULER_H )
758 #elif defined( UNDER_CE ) || defined( WIN32 )
759 i_ret = ( TlsSetValue( p_tls->handle, p_value ) != 0 );
761 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
762 i_ret = pthread_setspecific( p_tls->handle, p_value );
764 #elif defined( HAVE_CTHREADS_H )
765 i_ret = cthread_setspecific( p_tls->handle, p_value );
771 /*****************************************************************************
772 * vlc_threadvar_get: create: get the value of a thread-local variable
773 *****************************************************************************/
774 static inline void* vlc_threadvar_get( vlc_threadvar_t * p_tls )
778 #if defined( PTH_INIT_IN_PTH_H )
779 p_ret = pth_key_getdata( p_handle->key );
780 #elif defined( ST_INIT_IN_ST_H )
781 p_ret = st_thread_getspecific( p_handle->key );
782 #elif defined( HAVE_KERNEL_SCHEDULER_H )
784 #elif defined( UNDER_CE ) || defined( WIN32 )
785 p_ret = TlsGetValue( p_tls->handle );
787 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
788 p_ret = pthread_getspecific( p_tls->handle );
790 #elif defined( HAVE_CTHREADS_H )
791 if ( !cthread_getspecific( p_tls->handle, &p_ret ) )
800 /*****************************************************************************
801 * vlc_thread_create: create a thread
802 *****************************************************************************/
803 #define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY, WAIT ) \
804 __vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, (void * ( * ) ( void * ))FUNC, PRIORITY, WAIT )
806 /*****************************************************************************
807 * vlc_thread_set_priority: set the priority of the calling thread
808 *****************************************************************************/
809 #define vlc_thread_set_priority( P_THIS, PRIORITY ) \
810 __vlc_thread_set_priority( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PRIORITY )
812 /*****************************************************************************
813 * vlc_thread_ready: tell the parent thread we were successfully spawned
814 *****************************************************************************/
815 #define vlc_thread_ready( P_THIS ) \
816 __vlc_thread_ready( VLC_OBJECT(P_THIS) )
818 /*****************************************************************************
819 * vlc_thread_join: wait until a thread exits
820 *****************************************************************************/
821 #define vlc_thread_join( P_THIS ) \
822 __vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ )