threads.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:23k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * threads.c : threads implementation for the VideoLAN client
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2004 VideoLAN
  5.  * $Id: threads.c 9056 2004-10-24 21:07:58Z gbazin $
  6.  *
  7.  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *          Gildas Bazin <gbazin@netcourrier.com>
  10.  *
  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.
  15.  *
  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.
  20.  *
  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.  *****************************************************************************/
  25. #include <vlc/vlc.h>
  26. #include <stdlib.h>
  27. #define VLC_THREADS_UNINITIALIZED  0
  28. #define VLC_THREADS_PENDING        1
  29. #define VLC_THREADS_ERROR          2
  30. #define VLC_THREADS_READY          3
  31. /*****************************************************************************
  32.  * Global mutex for lazy initialization of the threads system
  33.  *****************************************************************************/
  34. static volatile int i_initializations = 0;
  35. #if defined( PTH_INIT_IN_PTH_H )
  36. #elif defined( ST_INIT_IN_ST_H )
  37. #elif defined( UNDER_CE )
  38. #elif defined( WIN32 )
  39. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  40. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  41.     static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;
  42. #elif defined( HAVE_CTHREADS_H )
  43. #endif
  44. /*****************************************************************************
  45.  * Global variable for named mutexes
  46.  *****************************************************************************/
  47. typedef struct vlc_namedmutex_t vlc_namedmutex_t;
  48. struct vlc_namedmutex_t
  49. {
  50.     vlc_mutex_t lock;
  51.     char *psz_name;
  52.     int i_usage;
  53.     vlc_namedmutex_t *p_next;
  54. };
  55. /*****************************************************************************
  56.  * vlc_threads_init: initialize threads system
  57.  *****************************************************************************
  58.  * This function requires lazy initialization of a global lock in order to
  59.  * keep the library really thread-safe. Some architectures don't support this
  60.  * and thus do not guarantee the complete reentrancy.
  61.  *****************************************************************************/
  62. int __vlc_threads_init( vlc_object_t *p_this )
  63. {
  64.     static volatile int i_status = VLC_THREADS_UNINITIALIZED;
  65.     libvlc_t *p_libvlc = (libvlc_t *)p_this;
  66.     int i_ret = VLC_SUCCESS;
  67.     /* If we have lazy mutex initialization, use it. Otherwise, we just
  68.      * hope nothing wrong happens. */
  69. #if defined( PTH_INIT_IN_PTH_H )
  70. #elif defined( ST_INIT_IN_ST_H )
  71. #elif defined( UNDER_CE )
  72. #elif defined( WIN32 )
  73.     HINSTANCE hInstLib;
  74. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  75. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  76.     pthread_mutex_lock( &once_mutex );
  77. #elif defined( HAVE_CTHREADS_H )
  78. #endif
  79.     if( i_status == VLC_THREADS_UNINITIALIZED )
  80.     {
  81.         i_status = VLC_THREADS_PENDING;
  82.         /* We should be safe now. Do all the initialization stuff we want. */
  83.         p_libvlc->b_ready = VLC_FALSE;
  84. #if defined( PTH_INIT_IN_PTH_H )
  85.         i_ret = ( pth_init() == FALSE );
  86. #elif defined( ST_INIT_IN_ST_H )
  87.         i_ret = st_init();
  88. #elif defined( UNDER_CE )
  89.         /* Nothing to initialize */
  90. #elif defined( WIN32 )
  91.         /* Dynamically get the address of SignalObjectAndWait */
  92.         if( GetVersion() < 0x80000000 )
  93.         {
  94.             /* We are running on NT/2K/XP, we can use SignalObjectAndWait */
  95.             hInstLib = LoadLibrary( "kernel32" );
  96.             if( hInstLib )
  97.             {
  98.                 p_libvlc->SignalObjectAndWait =
  99.                     (SIGNALOBJECTANDWAIT)GetProcAddress( hInstLib,
  100.                                                      "SignalObjectAndWait" );
  101.             }
  102.         }
  103.         else
  104.         {
  105.             p_libvlc->SignalObjectAndWait = NULL;
  106.         }
  107.         p_libvlc->b_fast_mutex = 0;
  108.         p_libvlc->i_win9x_cv = 0;
  109. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  110. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  111. #elif defined( HAVE_CTHREADS_H )
  112. #endif
  113.         vlc_object_create( p_libvlc, VLC_OBJECT_ROOT );
  114.         if( i_ret )
  115.         {
  116.             i_status = VLC_THREADS_ERROR;
  117.         }
  118.         else
  119.         {
  120.             i_initializations++;
  121.             i_status = VLC_THREADS_READY;
  122.         }
  123.     }
  124.     else
  125.     {
  126.         /* Just increment the initialization count */
  127.         i_initializations++;
  128.     }
  129.     /* If we have lazy mutex initialization support, unlock the mutex;
  130.      * otherwize, do a naive wait loop. */
  131. #if defined( PTH_INIT_IN_PTH_H )
  132.     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
  133. #elif defined( ST_INIT_IN_ST_H )
  134.     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
  135. #elif defined( UNDER_CE )
  136.     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
  137. #elif defined( WIN32 )
  138.     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
  139. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  140.     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
  141. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  142.     pthread_mutex_unlock( &once_mutex );
  143. #elif defined( HAVE_CTHREADS_H )
  144.     while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
  145. #endif
  146.     if( i_status != VLC_THREADS_READY )
  147.     {
  148.         return VLC_ETHREAD;
  149.     }
  150.     return i_ret;
  151. }
  152. /*****************************************************************************
  153.  * vlc_threads_end: stop threads system
  154.  *****************************************************************************
  155.  * FIXME: This function is far from being threadsafe. We should undo exactly
  156.  * what we did above in vlc_threads_init.
  157.  *****************************************************************************/
  158. int __vlc_threads_end( vlc_object_t *p_this )
  159. {
  160. #if defined( PTH_INIT_IN_PTH_H )
  161.     i_initializations--;
  162.     if( i_initializations == 0 )
  163.     {
  164.         return ( pth_kill() == FALSE );
  165.     }
  166. #elif defined( ST_INIT_IN_ST_H )
  167.     i_initializations--;
  168. #elif defined( UNDER_CE )
  169.     i_initializations--;
  170. #elif defined( WIN32 )
  171.     i_initializations--;
  172. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  173.     i_initializations--;
  174. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  175.     pthread_mutex_lock( &once_mutex );
  176.     i_initializations--;
  177.     pthread_mutex_unlock( &once_mutex );
  178. #elif defined( HAVE_CTHREADS_H )
  179.     i_initializations--;
  180. #endif
  181.     return VLC_SUCCESS;
  182. }
  183. /*****************************************************************************
  184.  * vlc_mutex_init: initialize a mutex
  185.  *****************************************************************************/
  186. int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
  187. {
  188.     p_mutex->p_this = p_this;
  189. #if defined( PTH_INIT_IN_PTH_H )
  190.     return ( pth_mutex_init( &p_mutex->mutex ) == FALSE );
  191. #elif defined( ST_INIT_IN_ST_H )
  192.     p_mutex->mutex = st_mutex_new();
  193.     return ( p_mutex->mutex == NULL ) ? errno : 0;
  194. #elif defined( UNDER_CE )
  195.     InitializeCriticalSection( &p_mutex->csection );
  196.     return 0;
  197. #elif defined( WIN32 )
  198.     /* We use mutexes on WinNT/2K/XP because we can use the SignalObjectAndWait
  199.      * function and have a 100% correct vlc_cond_wait() implementation.
  200.      * As this function is not available on Win9x, we can use the faster
  201.      * CriticalSections */
  202.     if( p_this->p_libvlc->SignalObjectAndWait &&
  203.         !p_this->p_libvlc->b_fast_mutex )
  204.     {
  205.         /* We are running on NT/2K/XP, we can use SignalObjectAndWait */
  206.         p_mutex->mutex = CreateMutex( 0, FALSE, 0 );
  207.         return ( p_mutex->mutex != NULL ? 0 : 1 );
  208.     }
  209.     else
  210.     {
  211.         p_mutex->mutex = NULL;
  212.         InitializeCriticalSection( &p_mutex->csection );
  213.         return 0;
  214.     }
  215. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  216.     /* check the arguments and whether it's already been initialized */
  217.     if( p_mutex == NULL )
  218.     {
  219.         return B_BAD_VALUE;
  220.     }
  221.     if( p_mutex->init == 9999 )
  222.     {
  223.         return EALREADY;
  224.     }
  225.     p_mutex->lock = create_sem( 1, "BeMutex" );
  226.     if( p_mutex->lock < B_NO_ERROR )
  227.     {
  228.         return( -1 );
  229.     }
  230.     p_mutex->init = 9999;
  231.     return B_OK;
  232. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  233. #   if defined(DEBUG) && defined(SYS_LINUX)
  234.     {
  235.         /* Create error-checking mutex to detect problems more easily. */
  236.         pthread_mutexattr_t attr;
  237.         int                 i_result;
  238.         pthread_mutexattr_init( &attr );
  239.         pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
  240.         i_result = pthread_mutex_init( &p_mutex->mutex, &attr );
  241.         pthread_mutexattr_destroy( &attr );
  242.         return( i_result );
  243.     }
  244. #   endif
  245.     return pthread_mutex_init( &p_mutex->mutex, NULL );
  246. #elif defined( HAVE_CTHREADS_H )
  247.     mutex_init( p_mutex );
  248.     return 0;
  249. #endif
  250. }
  251. /*****************************************************************************
  252.  * vlc_mutex_destroy: destroy a mutex, inner version
  253.  *****************************************************************************/
  254. int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
  255. {
  256.     int i_result;
  257.     /* In case of error : */
  258.     int i_thread = -1;
  259.     const char * psz_error = "";
  260. #if defined( PTH_INIT_IN_PTH_H )
  261.     return 0;
  262. #elif defined( ST_INIT_IN_ST_H )
  263.     i_result = st_mutex_destroy( p_mutex->mutex );
  264. #elif defined( UNDER_CE )
  265.     DeleteCriticalSection( &p_mutex->csection );
  266.     return 0;
  267. #elif defined( WIN32 )
  268.     if( p_mutex->mutex )
  269.     {
  270.         CloseHandle( p_mutex->mutex );
  271.     }
  272.     else
  273.     {
  274.         DeleteCriticalSection( &p_mutex->csection );
  275.     }
  276.     return 0;
  277. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  278.     if( p_mutex->init == 9999 )
  279.     {
  280.         delete_sem( p_mutex->lock );
  281.     }
  282.     p_mutex->init = 0;
  283.     return B_OK;
  284. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  285.     i_result = pthread_mutex_destroy( &p_mutex->mutex );
  286.     if ( i_result )
  287.     {
  288.         i_thread = (int)pthread_self();
  289.         psz_error = strerror(i_result);
  290.     }
  291. #elif defined( HAVE_CTHREADS_H )
  292.     return 0;
  293. #endif
  294.     if( i_result )
  295.     {
  296.         msg_Err( p_mutex->p_this,
  297.                  "thread %d: mutex_destroy failed at %s:%d (%d:%s)",
  298.                  i_thread, psz_file, i_line, i_result, psz_error );
  299.     }
  300.     return i_result;
  301. }
  302. /*****************************************************************************
  303.  * vlc_cond_init: initialize a condition
  304.  *****************************************************************************/
  305. int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
  306. {
  307.     p_condvar->p_this = p_this;
  308. #if defined( PTH_INIT_IN_PTH_H )
  309.     return ( pth_cond_init( &p_condvar->cond ) == FALSE );
  310. #elif defined( ST_INIT_IN_ST_H )
  311.     p_condvar->cond = st_cond_new();
  312.     return ( p_condvar->cond == NULL ) ? errno : 0;
  313. #elif defined( UNDER_CE )
  314.     /* Initialize counter */
  315.     p_condvar->i_waiting_threads = 0;
  316.     /* Create an auto-reset event. */
  317.     p_condvar->event = CreateEvent( NULL,   /* no security */
  318.                                     FALSE,  /* auto-reset event */
  319.                                     FALSE,  /* start non-signaled */
  320.                                     NULL ); /* unnamed */
  321.     return !p_condvar->event;
  322. #elif defined( WIN32 )
  323.     /* Initialize counter */
  324.     p_condvar->i_waiting_threads = 0;
  325.     /* Misc init */
  326.     p_condvar->i_win9x_cv = p_this->p_libvlc->i_win9x_cv;
  327.     p_condvar->SignalObjectAndWait = p_this->p_libvlc->SignalObjectAndWait;
  328.     if( (p_condvar->SignalObjectAndWait && !p_this->p_libvlc->b_fast_mutex)
  329.         || p_condvar->i_win9x_cv == 0 )
  330.     {
  331.         /* Create an auto-reset event. */
  332.         p_condvar->event = CreateEvent( NULL,   /* no security */
  333.                                         FALSE,  /* auto-reset event */
  334.                                         FALSE,  /* start non-signaled */
  335.                                         NULL ); /* unnamed */
  336.         p_condvar->semaphore = NULL;
  337.         return !p_condvar->event;
  338.     }
  339.     else
  340.     {
  341.         p_condvar->semaphore = CreateSemaphore( NULL,       /* no security */
  342.                                                 0,          /* initial count */
  343.                                                 0x7fffffff, /* max count */
  344.                                                 NULL );     /* unnamed */
  345.         if( p_condvar->i_win9x_cv == 1 )
  346.             /* Create a manual-reset event initially signaled. */
  347.             p_condvar->event = CreateEvent( NULL, TRUE, TRUE, NULL );
  348.         else
  349.             /* Create a auto-reset event. */
  350.             p_condvar->event = CreateEvent( NULL, FALSE, FALSE, NULL );
  351.         InitializeCriticalSection( &p_condvar->csection );
  352.         return !p_condvar->semaphore || !p_condvar->event;
  353.     }
  354. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  355.     if( !p_condvar )
  356.     {
  357.         return B_BAD_VALUE;
  358.     }
  359.     if( p_condvar->init == 9999 )
  360.     {
  361.         return EALREADY;
  362.     }
  363.     p_condvar->thread = -1;
  364.     p_condvar->init = 9999;
  365.     return 0;
  366. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  367.     return pthread_cond_init( &p_condvar->cond, NULL );
  368. #elif defined( HAVE_CTHREADS_H )
  369.     /* condition_init() */
  370.     spin_lock_init( &p_condvar->lock );
  371.     cthread_queue_init( &p_condvar->queue );
  372.     p_condvar->name = 0;
  373.     p_condvar->implications = 0;
  374.     return 0;
  375. #endif
  376. }
  377. /*****************************************************************************
  378.  * vlc_cond_destroy: destroy a condition, inner version
  379.  *****************************************************************************/
  380. int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
  381. {
  382.     int i_result;
  383.     /* In case of error : */
  384.     int i_thread = -1;
  385.     const char * psz_error = "";
  386. #if defined( PTH_INIT_IN_PTH_H )
  387.     return 0;
  388. #elif defined( ST_INIT_IN_ST_H )
  389.     i_result = st_cond_destroy( p_condvar->cond );
  390. #elif defined( UNDER_CE )
  391.     i_result = !CloseHandle( p_condvar->event );
  392. #elif defined( WIN32 )
  393.     if( !p_condvar->semaphore )
  394.         i_result = !CloseHandle( p_condvar->event );
  395.     else
  396.         i_result = !CloseHandle( p_condvar->event )
  397.           || !CloseHandle( p_condvar->semaphore );
  398. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  399.     p_condvar->init = 0;
  400.     return 0;
  401. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  402.     i_result = pthread_cond_destroy( &p_condvar->cond );
  403.     if ( i_result )
  404.     {
  405.         i_thread = (int)pthread_self();
  406.         psz_error = strerror(i_result);
  407.     }
  408. #elif defined( HAVE_CTHREADS_H )
  409.     return 0;
  410. #endif
  411.     if( i_result )
  412.     {
  413.         msg_Err( p_condvar->p_this,
  414.                  "thread %d: cond_destroy failed at %s:%d (%d:%s)",
  415.                  i_thread, psz_file, i_line, i_result, psz_error );
  416.     }
  417.     return i_result;
  418. }
  419. /*****************************************************************************
  420.  * vlc_thread_create: create a thread, inner version
  421.  *****************************************************************************
  422.  * Note that i_priority is only taken into account on platforms supporting
  423.  * userland real-time priority threads.
  424.  *****************************************************************************/
  425. int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
  426.                          char *psz_name, void * ( *func ) ( void * ),
  427.                          int i_priority, vlc_bool_t b_wait )
  428. {
  429.     int i_ret;
  430.     void *p_data = (void *)p_this;
  431.     vlc_mutex_lock( &p_this->object_lock );
  432. #if defined( PTH_INIT_IN_PTH_H )
  433.     p_this->thread_id = pth_spawn( PTH_ATTR_DEFAULT, func, p_data );
  434.     i_ret = p_this->thread_id == NULL;
  435. #elif defined( ST_INIT_IN_ST_H )
  436.     p_this->thread_id = st_thread_create( func, p_data, 1, 0 );
  437.     i_ret = 0;
  438. #elif defined( WIN32 ) || defined( UNDER_CE )
  439.     {
  440.         unsigned threadID;
  441.         /* When using the MSVCRT C library you have to use the _beginthreadex
  442.          * function instead of CreateThread, otherwise you'll end up with
  443.          * memory leaks and the signal functions not working (see Microsoft
  444.          * Knowledge Base, article 104641) */
  445.         p_this->thread_id =
  446. #if defined( UNDER_CE )
  447.                 (HANDLE)CreateThread( NULL, 0, (PTHREAD_START) func,
  448.                                       p_data, 0, &threadID );
  449. #else
  450.                 (HANDLE)_beginthreadex( NULL, 0, (PTHREAD_START) func,
  451.                                         p_data, 0, &threadID );
  452. #endif
  453.     }
  454.     if ( p_this->thread_id && i_priority )
  455.     {
  456.         if ( !SetThreadPriority(p_this->thread_id, i_priority) )
  457.         {
  458.             msg_Warn( p_this, "couldn't set a faster priority" );
  459.             i_priority = 0;
  460.         }
  461.     }
  462.     i_ret = ( p_this->thread_id ? 0 : 1 );
  463. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  464.     p_this->thread_id = spawn_thread( (thread_func)func, psz_name,
  465.                                       i_priority, p_data );
  466.     i_ret = resume_thread( p_this->thread_id );
  467. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  468.     i_ret = pthread_create( &p_this->thread_id, NULL, func, p_data );
  469. #ifndef SYS_DARWIN
  470.     if ( config_GetInt( p_this, "rt-priority" ) )
  471. #endif
  472.     {
  473.         int i_error, i_policy;
  474.         struct sched_param param;
  475.         memset( &param, 0, sizeof(struct sched_param) );
  476.         i_priority += config_GetInt( p_this, "rt-offset" );
  477.         if ( i_priority <= 0 )
  478.         {
  479.             param.sched_priority = (-1) * i_priority;
  480.             i_policy = SCHED_OTHER;
  481.         }
  482.         else
  483.         {
  484.             param.sched_priority = i_priority;
  485.             i_policy = SCHED_RR;
  486.         }
  487.         if ( (i_error = pthread_setschedparam( p_this->thread_id,
  488.                                                i_policy, &param )) )
  489.         {
  490.             msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
  491.                       psz_file, i_line, strerror(i_error) );
  492.             i_priority = 0;
  493.         }
  494.     }
  495. #ifndef SYS_DARWIN
  496.     else
  497.     {
  498.         i_priority = 0;
  499.     }
  500. #endif
  501. #elif defined( HAVE_CTHREADS_H )
  502.     p_this->thread_id = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
  503.     i_ret = 0;
  504. #endif
  505.     if( i_ret == 0 )
  506.     {
  507.         if( b_wait )
  508.         {
  509.             msg_Dbg( p_this, "waiting for thread completion" );
  510.             vlc_cond_wait( &p_this->object_wait, &p_this->object_lock );
  511.         }
  512.         p_this->b_thread = 1;
  513.         msg_Dbg( p_this, "thread %d (%s) created at priority %d (%s:%d)",
  514.                  (int)p_this->thread_id, psz_name, i_priority,
  515.                  psz_file, i_line );
  516.         vlc_mutex_unlock( &p_this->object_lock );
  517.     }
  518.     else
  519.     {
  520. #ifdef HAVE_STRERROR
  521.         msg_Err( p_this, "%s thread could not be created at %s:%d (%s)",
  522.                          psz_name, psz_file, i_line, strerror(i_ret) );
  523. #else
  524.         msg_Err( p_this, "%s thread could not be created at %s:%d",
  525.                          psz_name, psz_file, i_line );
  526. #endif
  527.         vlc_mutex_unlock( &p_this->object_lock );
  528.     }
  529.     return i_ret;
  530. }
  531. /*****************************************************************************
  532.  * vlc_thread_set_priority: set the priority of the current thread when we
  533.  * couldn't set it in vlc_thread_create (for instance for the main thread)
  534.  *****************************************************************************/
  535. int __vlc_thread_set_priority( vlc_object_t *p_this, char * psz_file,
  536.                                int i_line, int i_priority )
  537. {
  538. #if defined( PTH_INIT_IN_PTH_H ) || defined( ST_INIT_IN_ST_H )
  539. #elif defined( WIN32 ) || defined( UNDER_CE )
  540.     if ( !SetThreadPriority(GetCurrentThread(), i_priority) )
  541.     {
  542.         msg_Warn( p_this, "couldn't set a faster priority" );
  543.         return 1;
  544.     }
  545. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  546. #ifndef SYS_DARWIN
  547.     if ( config_GetInt( p_this, "rt-priority" ) )
  548. #endif
  549.     {
  550.         int i_error, i_policy;
  551.         struct sched_param param;
  552.         memset( &param, 0, sizeof(struct sched_param) );
  553.         i_priority += config_GetInt( p_this, "rt-offset" );
  554.         if ( i_priority <= 0 )
  555.         {
  556.             param.sched_priority = (-1) * i_priority;
  557.             i_policy = SCHED_OTHER;
  558.         }
  559.         else
  560.         {
  561.             param.sched_priority = i_priority;
  562.             i_policy = SCHED_RR;
  563.         }
  564.         if ( !p_this->thread_id )
  565.             p_this->thread_id = pthread_self();
  566.         if ( (i_error = pthread_setschedparam( p_this->thread_id,
  567.                                                i_policy, &param )) )
  568.         {
  569.             msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
  570.                       psz_file, i_line, strerror(i_error) );
  571.             i_priority = 0;
  572.         }
  573.     }
  574. #endif
  575.     return 0;
  576. }
  577. /*****************************************************************************
  578.  * vlc_thread_ready: tell the parent thread we were successfully spawned
  579.  *****************************************************************************/
  580. void __vlc_thread_ready( vlc_object_t *p_this )
  581. {
  582.     vlc_mutex_lock( &p_this->object_lock );
  583.     vlc_cond_signal( &p_this->object_wait );
  584.     vlc_mutex_unlock( &p_this->object_lock );
  585. }
  586. /*****************************************************************************
  587.  * vlc_thread_join: wait until a thread exits, inner version
  588.  *****************************************************************************/
  589. void __vlc_thread_join( vlc_object_t *p_this, char * psz_file, int i_line )
  590. {
  591.     int i_ret = 0;
  592. #if defined( PTH_INIT_IN_PTH_H )
  593.     i_ret = ( pth_join( p_this->thread_id, NULL ) == FALSE );
  594. #elif defined( ST_INIT_IN_ST_H )
  595.     i_ret = st_thread_join( p_this->thread_id, NULL );
  596. #elif defined( UNDER_CE ) || defined( WIN32 )
  597.     WaitForSingleObject( p_this->thread_id, INFINITE );
  598.     CloseHandle( p_this->thread_id );
  599. #elif defined( HAVE_KERNEL_SCHEDULER_H )
  600.     int32_t exit_value;
  601.     wait_for_thread( p_this->thread_id, &exit_value );
  602. #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
  603.     i_ret = pthread_join( p_this->thread_id, NULL );
  604. #elif defined( HAVE_CTHREADS_H )
  605.     cthread_join( p_this->thread_id );
  606.     i_ret = 1;
  607. #endif
  608.     if( i_ret )
  609.     {
  610. #ifdef HAVE_STRERROR
  611.         msg_Err( p_this, "thread_join(%d) failed at %s:%d (%s)",
  612.                          (int)p_this->thread_id, psz_file, i_line,
  613.                          strerror(i_ret) );
  614. #else
  615.         msg_Err( p_this, "thread_join(%d) failed at %s:%d",
  616.                          (int)p_this->thread_id, psz_file, i_line );
  617. #endif
  618.     }
  619.     else
  620.     {
  621.         msg_Dbg( p_this, "thread %d joined (%s:%d)",
  622.                          (int)p_this->thread_id, psz_file, i_line );
  623.     }
  624.     p_this->b_thread = 0;
  625. }