00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 VLC_EXPORT( int, __vlc_threads_init, ( vlc_object_t * ) );
00032 VLC_EXPORT( int, __vlc_threads_end, ( vlc_object_t * ) );
00033 VLC_EXPORT( int, __vlc_mutex_init, ( vlc_object_t *, vlc_mutex_t * ) );
00034 VLC_EXPORT( int, __vlc_mutex_destroy, ( char *, int, vlc_mutex_t * ) );
00035 VLC_EXPORT( int, __vlc_cond_init, ( vlc_object_t *, vlc_cond_t * ) );
00036 VLC_EXPORT( int, __vlc_cond_destroy, ( char *, int, vlc_cond_t * ) );
00037 VLC_EXPORT( int, __vlc_thread_create, ( vlc_object_t *, char *, int, char *, void * ( * ) ( void * ), int, vlc_bool_t ) );
00038 VLC_EXPORT( int, __vlc_thread_set_priority, ( vlc_object_t *, char *, int, int ) );
00039 VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) );
00040 VLC_EXPORT( void, __vlc_thread_join, ( vlc_object_t *, char *, int ) );
00041
00042
00043
00044
00045
00046 #define vlc_threads_init( P_THIS ) \
00047 __vlc_threads_init( VLC_OBJECT(P_THIS) )
00048
00049
00050
00051
00052 #define vlc_threads_end( P_THIS ) \
00053 __vlc_threads_end( VLC_OBJECT(P_THIS) )
00054
00055
00056
00057
00058 #define vlc_mutex_init( P_THIS, P_MUTEX ) \
00059 __vlc_mutex_init( VLC_OBJECT(P_THIS), P_MUTEX )
00060
00061
00062
00063
00064 #define vlc_mutex_lock( P_MUTEX ) \
00065 __vlc_mutex_lock( __FILE__, __LINE__, P_MUTEX )
00066
00067 static inline int __vlc_mutex_lock( char * psz_file, int i_line,
00068 vlc_mutex_t * p_mutex )
00069 {
00070 int i_result;
00071
00072 int i_thread = -1;
00073 const char * psz_error = "";
00074
00075 #if defined( PTH_INIT_IN_PTH_H )
00076 i_result = ( pth_mutex_acquire( &p_mutex->mutex, FALSE, NULL ) == FALSE );
00077
00078 #elif defined( ST_INIT_IN_ST_H )
00079 i_result = st_mutex_lock( p_mutex->mutex );
00080
00081 #elif defined( UNDER_CE )
00082 EnterCriticalSection( &p_mutex->csection );
00083 i_result = 0;
00084
00085 #elif defined( WIN32 )
00086 if( p_mutex->mutex )
00087 {
00088 WaitForSingleObject( p_mutex->mutex, INFINITE );
00089 }
00090 else
00091 {
00092 EnterCriticalSection( &p_mutex->csection );
00093 }
00094 i_result = 0;
00095
00096 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00097 if( p_mutex == NULL )
00098 {
00099 i_result = B_BAD_VALUE;
00100 }
00101 else if( p_mutex->init < 2000 )
00102 {
00103 i_result = B_NO_INIT;
00104 }
00105 else
00106 {
00107 i_result = acquire_sem( p_mutex->lock );
00108 }
00109
00110 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00111 i_result = pthread_mutex_lock( &p_mutex->mutex );
00112 if ( i_result )
00113 {
00114 i_thread = (int)pthread_self();
00115 psz_error = strerror(i_result);
00116 }
00117
00118 #elif defined( HAVE_CTHREADS_H )
00119 mutex_lock( p_mutex->mutex );
00120 i_result = 0;
00121
00122 #endif
00123
00124 if( i_result )
00125 {
00126 msg_Err( p_mutex->p_this,
00127 "thread %u: mutex_lock failed at %s:%d (%d:%s)",
00128 i_thread, psz_file, i_line, i_result, psz_error );
00129 }
00130 return i_result;
00131 }
00132
00133
00134
00135
00136 #define vlc_mutex_unlock( P_MUTEX ) \
00137 __vlc_mutex_unlock( __FILE__, __LINE__, P_MUTEX )
00138
00139 static inline int __vlc_mutex_unlock( char * psz_file, int i_line,
00140 vlc_mutex_t *p_mutex )
00141 {
00142 int i_result;
00143
00144 int i_thread = -1;
00145 const char * psz_error = "";
00146
00147 #if defined( PTH_INIT_IN_PTH_H )
00148 i_result = ( pth_mutex_release( &p_mutex->mutex ) == FALSE );
00149
00150 #elif defined( ST_INIT_IN_ST_H )
00151 i_result = st_mutex_unlock( p_mutex->mutex );
00152
00153 #elif defined( UNDER_CE )
00154 LeaveCriticalSection( &p_mutex->csection );
00155 i_result = 0;
00156
00157 #elif defined( WIN32 )
00158 if( p_mutex->mutex )
00159 {
00160 ReleaseMutex( p_mutex->mutex );
00161 }
00162 else
00163 {
00164 LeaveCriticalSection( &p_mutex->csection );
00165 }
00166 i_result = 0;
00167
00168 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00169 if( p_mutex == NULL )
00170 {
00171 i_result = B_BAD_VALUE;
00172 }
00173 else if( p_mutex->init < 2000 )
00174 {
00175 i_result = B_NO_INIT;
00176 }
00177 else
00178 {
00179 release_sem( p_mutex->lock );
00180 return B_OK;
00181 }
00182
00183 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00184 i_result = pthread_mutex_unlock( &p_mutex->mutex );
00185 if ( i_result )
00186 {
00187 i_thread = (int)pthread_self();
00188 psz_error = strerror(i_result);
00189 }
00190
00191 #elif defined( HAVE_CTHREADS_H )
00192 mutex_unlock( p_mutex );
00193 i_result = 0;
00194
00195 #endif
00196
00197 if( i_result )
00198 {
00199 msg_Err( p_mutex->p_this,
00200 "thread %u: mutex_unlock failed at %s:%d (%d:%s)",
00201 i_thread, psz_file, i_line, i_result, psz_error );
00202 }
00203
00204 return i_result;
00205 }
00206
00207
00208
00209
00210 #define vlc_mutex_destroy( P_MUTEX ) \
00211 __vlc_mutex_destroy( __FILE__, __LINE__, P_MUTEX )
00212
00213
00214
00215
00216 #define vlc_cond_init( P_THIS, P_COND ) \
00217 __vlc_cond_init( VLC_OBJECT(P_THIS), P_COND )
00218
00219
00220
00221
00222 #define vlc_cond_signal( P_COND ) \
00223 __vlc_cond_signal( __FILE__, __LINE__, P_COND )
00224
00225 static inline int __vlc_cond_signal( char * psz_file, int i_line,
00226 vlc_cond_t *p_condvar )
00227 {
00228 int i_result;
00229
00230 int i_thread = -1;
00231 const char * psz_error = "";
00232
00233 #if defined( PTH_INIT_IN_PTH_H )
00234 i_result = ( pth_cond_notify( &p_condvar->cond, FALSE ) == FALSE );
00235
00236 #elif defined( ST_INIT_IN_ST_H )
00237 i_result = st_cond_signal( p_condvar->cond );
00238
00239 #elif defined( UNDER_CE )
00240 PulseEvent( p_condvar->event );
00241 i_result = 0;
00242
00243 #elif defined( WIN32 )
00244
00245
00246
00247 if( !p_condvar->semaphore )
00248 {
00249 PulseEvent( p_condvar->event );
00250 }
00251 else if( p_condvar->i_win9x_cv == 1 )
00252 {
00253
00254 WaitForSingleObject( p_condvar->event, INFINITE );
00255
00256 if( p_condvar->i_waiting_threads )
00257 {
00258
00259
00260
00261
00262 ResetEvent( p_condvar->event );
00263
00264
00265
00266
00267
00268
00269 ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
00270 }
00271 }
00272 else
00273 {
00274 if( p_condvar->i_waiting_threads )
00275 {
00276 ReleaseSemaphore( p_condvar->semaphore, 1, 0 );
00277
00278
00279 WaitForSingleObject( p_condvar->event, INFINITE );
00280 }
00281 }
00282 i_result = 0;
00283
00284 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00285 if( p_condvar == NULL )
00286 {
00287 i_result = B_BAD_VALUE;
00288 }
00289 else if( p_condvar->init < 2000 )
00290 {
00291 i_result = B_NO_INIT;
00292 }
00293 else
00294 {
00295 while( p_condvar->thread != -1 )
00296 {
00297 thread_info info;
00298 if( get_thread_info(p_condvar->thread, &info) == B_BAD_VALUE )
00299 {
00300 return 0;
00301 }
00302
00303 if( info.state != B_THREAD_SUSPENDED )
00304 {
00305
00306
00307
00308
00309 snooze( 10000 );
00310 }
00311 else
00312 {
00313
00314 resume_thread( p_condvar->thread );
00315 return 0;
00316 }
00317 }
00318 i_result = 0;
00319 }
00320
00321 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00322 i_result = pthread_cond_signal( &p_condvar->cond );
00323 if ( i_result )
00324 {
00325 i_thread = (int)pthread_self();
00326 psz_error = strerror(i_result);
00327 }
00328
00329 #elif defined( HAVE_CTHREADS_H )
00330
00331 if ( p_condvar->queue.head || p_condvar->implications )
00332 {
00333 cond_signal( (condition_t)p_condvar );
00334 }
00335 i_result = 0;
00336
00337 #endif
00338
00339 if( i_result )
00340 {
00341 msg_Err( p_condvar->p_this,
00342 "thread %u: cond_signal failed at %s:%d (%d:%s)",
00343 i_thread, psz_file, i_line, i_result, psz_error );
00344 }
00345
00346 return i_result;
00347 }
00348
00349
00350
00351
00352 #define vlc_cond_wait( P_COND, P_MUTEX ) \
00353 __vlc_cond_wait( __FILE__, __LINE__, P_COND, P_MUTEX )
00354
00355 static inline int __vlc_cond_wait( char * psz_file, int i_line,
00356 vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex )
00357 {
00358 int i_result;
00359
00360 int i_thread = -1;
00361 const char * psz_error = "";
00362
00363 #if defined( PTH_INIT_IN_PTH_H )
00364 i_result = ( pth_cond_await( &p_condvar->cond, &p_mutex->mutex, NULL )
00365 == FALSE );
00366
00367 #elif defined( ST_INIT_IN_ST_H )
00368 st_mutex_unlock( p_mutex->mutex );
00369 i_result = st_cond_wait( p_condvar->cond );
00370 st_mutex_lock( p_mutex->mutex );
00371
00372 #elif defined( UNDER_CE )
00373 p_condvar->i_waiting_threads++;
00374 LeaveCriticalSection( &p_mutex->csection );
00375 WaitForSingleObject( p_condvar->event, INFINITE );
00376 p_condvar->i_waiting_threads--;
00377
00378
00379 vlc_mutex_lock( p_mutex );
00380
00381 i_result = 0;
00382
00383 #elif defined( WIN32 )
00384 if( !p_condvar->semaphore )
00385 {
00386
00387 p_condvar->i_waiting_threads++;
00388
00389 if( p_mutex->mutex )
00390 {
00391
00392
00393
00394 p_condvar->SignalObjectAndWait( p_mutex->mutex,
00395 p_condvar->event,
00396 INFINITE, FALSE );
00397 }
00398 else
00399 {
00400 LeaveCriticalSection( &p_mutex->csection );
00401 WaitForSingleObject( p_condvar->event, INFINITE );
00402 }
00403
00404 p_condvar->i_waiting_threads--;
00405 }
00406 else if( p_condvar->i_win9x_cv == 1 )
00407 {
00408 int i_waiting_threads;
00409
00410
00411 WaitForSingleObject( p_condvar->event, INFINITE );
00412
00413
00414 p_condvar->i_waiting_threads++;
00415
00416 LeaveCriticalSection( &p_mutex->csection );
00417 WaitForSingleObject( p_condvar->semaphore, INFINITE );
00418
00419
00420 EnterCriticalSection( &p_condvar->csection );
00421
00422
00423 i_waiting_threads = --p_condvar->i_waiting_threads;
00424
00425 LeaveCriticalSection( &p_condvar->csection );
00426
00427
00428 if( !i_waiting_threads )
00429 SetEvent( p_condvar->event );
00430 }
00431 else
00432 {
00433 int i_waiting_threads;
00434
00435
00436 p_condvar->i_waiting_threads++;
00437
00438 LeaveCriticalSection( &p_mutex->csection );
00439 WaitForSingleObject( p_condvar->semaphore, INFINITE );
00440
00441
00442 EnterCriticalSection( &p_condvar->csection );
00443
00444
00445 i_waiting_threads = --p_condvar->i_waiting_threads;
00446
00447 LeaveCriticalSection( &p_condvar->csection );
00448
00449
00450 if( !i_waiting_threads )
00451 SetEvent( p_condvar->event );
00452 }
00453
00454
00455 vlc_mutex_lock( p_mutex );
00456
00457 i_result = 0;
00458
00459 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00460 if( p_condvar == NULL )
00461 {
00462 i_result = B_BAD_VALUE;
00463 }
00464 else if( p_mutex == NULL )
00465 {
00466 i_result = B_BAD_VALUE;
00467 }
00468 else if( p_condvar->init < 2000 )
00469 {
00470 i_result = B_NO_INIT;
00471 }
00472
00473
00474
00475
00476 p_condvar->thread = find_thread( NULL );
00477 vlc_mutex_unlock( p_mutex );
00478 suspend_thread( p_condvar->thread );
00479 p_condvar->thread = -1;
00480
00481 vlc_mutex_lock( p_mutex );
00482 i_result = 0;
00483
00484 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00485
00486 # ifdef DEBUG
00487
00488 struct timeval now;
00489 struct timespec timeout;
00490
00491 gettimeofday( &now, NULL );
00492 timeout.tv_sec = now.tv_sec + THREAD_COND_TIMEOUT;
00493 timeout.tv_nsec = now.tv_usec * 1000;
00494
00495 i_result = pthread_cond_timedwait( &p_condvar->cond, &p_mutex->mutex,
00496 &timeout );
00497
00498 if( i_result == ETIMEDOUT )
00499 {
00500
00501 msg_Dbg( p_condvar->p_this,
00502 "thread %u: secret message triggered "
00503 "at %s:%d (%s)", (int)pthread_self(),
00504 psz_file, i_line, strerror(i_result) );
00505
00506 i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
00507 }
00508
00509 # else
00510 i_result = pthread_cond_wait( &p_condvar->cond, &p_mutex->mutex );
00511 # endif
00512
00513 if ( i_result )
00514 {
00515 i_thread = (int)pthread_self();
00516 psz_error = strerror(i_result);
00517 }
00518
00519 #elif defined( HAVE_CTHREADS_H )
00520 condition_wait( (condition_t)p_condvar, (mutex_t)p_mutex );
00521 i_result = 0;
00522
00523 #endif
00524
00525 if( i_result )
00526 {
00527 msg_Err( p_condvar->p_this,
00528 "thread %u: cond_wait failed at %s:%d (%d:%s)",
00529 i_thread, psz_file, i_line, i_result, psz_error );
00530 }
00531
00532 return i_result;
00533 }
00534
00535
00536
00537
00538 #define vlc_cond_destroy( P_COND ) \
00539 __vlc_cond_destroy( __FILE__, __LINE__, P_COND )
00540
00541
00542
00543
00544 #define vlc_thread_create( P_THIS, PSZ_NAME, FUNC, PRIORITY, WAIT ) \
00545 __vlc_thread_create( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PSZ_NAME, (void * ( * ) ( void * ))FUNC, PRIORITY, WAIT )
00546
00547
00548
00549
00550 #define vlc_thread_set_priority( P_THIS, PRIORITY ) \
00551 __vlc_thread_set_priority( VLC_OBJECT(P_THIS), __FILE__, __LINE__, PRIORITY )
00552
00553
00554
00555
00556 #define vlc_thread_ready( P_THIS ) \
00557 __vlc_thread_ready( VLC_OBJECT(P_THIS) )
00558
00559
00560
00561
00562 #define vlc_thread_join( P_THIS ) \
00563 __vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ )