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 #include <vlc/vlc.h>
00027
00028 #include <stdlib.h>
00029
00030 #define VLC_THREADS_UNINITIALIZED 0
00031 #define VLC_THREADS_PENDING 1
00032 #define VLC_THREADS_ERROR 2
00033 #define VLC_THREADS_READY 3
00034
00035
00036
00037
00038 static volatile unsigned i_initializations = 0;
00039 static volatile int i_status = VLC_THREADS_UNINITIALIZED;
00040 static vlc_object_t *p_root;
00041
00042 #if defined( PTH_INIT_IN_PTH_H )
00043 #elif defined( ST_INIT_IN_ST_H )
00044 #elif defined( UNDER_CE )
00045 #elif defined( WIN32 )
00046 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00047 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00048 static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;
00049 #elif defined( HAVE_CTHREADS_H )
00050 #endif
00051
00052
00053
00054
00055 typedef struct vlc_namedmutex_t vlc_namedmutex_t;
00056 struct vlc_namedmutex_t
00057 {
00058 vlc_mutex_t lock;
00059
00060 char *psz_name;
00061 int i_usage;
00062 vlc_namedmutex_t *p_next;
00063 };
00064
00065
00066
00067
00068
00069
00070
00071
00072 int __vlc_threads_init( vlc_object_t *p_this )
00073 {
00074 libvlc_t *p_libvlc = (libvlc_t *)p_this;
00075 int i_ret = VLC_SUCCESS;
00076
00077
00078
00079 #if defined( PTH_INIT_IN_PTH_H )
00080 #elif defined( ST_INIT_IN_ST_H )
00081 #elif defined( UNDER_CE )
00082 #elif defined( WIN32 )
00083 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00084 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00085 pthread_mutex_lock( &once_mutex );
00086 #elif defined( HAVE_CTHREADS_H )
00087 #endif
00088
00089 if( i_status == VLC_THREADS_UNINITIALIZED )
00090 {
00091 i_status = VLC_THREADS_PENDING;
00092
00093
00094 p_libvlc->b_ready = VLC_FALSE;
00095
00096 #if defined( PTH_INIT_IN_PTH_H )
00097 i_ret = ( pth_init() == FALSE );
00098
00099 #elif defined( ST_INIT_IN_ST_H )
00100 i_ret = st_init();
00101
00102 #elif defined( UNDER_CE )
00103
00104
00105 #elif defined( WIN32 )
00106
00107 if( GetVersion() < 0x80000000 )
00108 {
00109 HINSTANCE hInstLib;
00110
00111
00112 hInstLib = LoadLibrary( "kernel32" );
00113 if( hInstLib )
00114 {
00115 p_libvlc->SignalObjectAndWait =
00116 (SIGNALOBJECTANDWAIT)GetProcAddress( hInstLib,
00117 "SignalObjectAndWait" );
00118 }
00119 }
00120 else
00121 {
00122 p_libvlc->SignalObjectAndWait = NULL;
00123 }
00124
00125 p_libvlc->b_fast_mutex = 0;
00126 p_libvlc->i_win9x_cv = 0;
00127
00128 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00129 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00130 #elif defined( HAVE_CTHREADS_H )
00131 #endif
00132
00133 p_root = vlc_object_create( p_libvlc, VLC_OBJECT_ROOT );
00134 if( p_root == NULL )
00135 i_ret = VLC_ENOMEM;
00136
00137 if( i_ret )
00138 {
00139 i_status = VLC_THREADS_ERROR;
00140 }
00141 else
00142 {
00143 i_initializations++;
00144 i_status = VLC_THREADS_READY;
00145 }
00146 }
00147 else
00148 {
00149
00150 i_initializations++;
00151 }
00152
00153
00154
00155 #if defined( PTH_INIT_IN_PTH_H )
00156 while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00157 #elif defined( ST_INIT_IN_ST_H )
00158 while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00159 #elif defined( UNDER_CE )
00160 while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00161 #elif defined( WIN32 )
00162 while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00163 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00164 while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00165 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00166 pthread_mutex_unlock( &once_mutex );
00167 #elif defined( HAVE_CTHREADS_H )
00168 while( i_status == VLC_THREADS_PENDING ) msleep( THREAD_SLEEP );
00169 #endif
00170
00171 if( i_status != VLC_THREADS_READY )
00172 {
00173 return VLC_ETHREAD;
00174 }
00175
00176 return i_ret;
00177 }
00178
00179
00180
00181
00182
00183
00184 int __vlc_threads_end( vlc_object_t *p_this )
00185 {
00186 #if defined( PTH_INIT_IN_PTH_H )
00187 #elif defined( ST_INIT_IN_ST_H )
00188 #elif defined( UNDER_CE )
00189 #elif defined( WIN32 )
00190 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00191 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00192 pthread_mutex_lock( &once_mutex );
00193 #elif defined( HAVE_CTHREADS_H )
00194 #endif
00195
00196 if( i_initializations == 0 )
00197 return VLC_EGENERIC;
00198
00199 i_initializations--;
00200 if( i_initializations == 0 )
00201 {
00202 i_status = VLC_THREADS_UNINITIALIZED;
00203 vlc_object_destroy( p_root );
00204 }
00205
00206 #if defined( PTH_INIT_IN_PTH_H )
00207 if( i_initializations == 0 )
00208 {
00209 return ( pth_kill() == FALSE );
00210 }
00211
00212 #elif defined( ST_INIT_IN_ST_H )
00213 #elif defined( UNDER_CE )
00214 #elif defined( WIN32 )
00215 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00216 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00217 pthread_mutex_unlock( &once_mutex );
00218 #elif defined( HAVE_CTHREADS_H )
00219 #endif
00220 return VLC_SUCCESS;
00221 }
00222
00223
00224
00225
00226 int __vlc_mutex_init( vlc_object_t *p_this, vlc_mutex_t *p_mutex )
00227 {
00228 p_mutex->p_this = p_this;
00229
00230 #if defined( PTH_INIT_IN_PTH_H )
00231 return ( pth_mutex_init( &p_mutex->mutex ) == FALSE );
00232
00233 #elif defined( ST_INIT_IN_ST_H )
00234 p_mutex->mutex = st_mutex_new();
00235 return ( p_mutex->mutex == NULL ) ? errno : 0;
00236
00237 #elif defined( UNDER_CE )
00238 InitializeCriticalSection( &p_mutex->csection );
00239 return 0;
00240
00241 #elif defined( WIN32 )
00242
00243
00244
00245
00246 if( p_this->p_libvlc->SignalObjectAndWait &&
00247 !p_this->p_libvlc->b_fast_mutex )
00248 {
00249
00250 p_mutex->mutex = CreateMutex( 0, FALSE, 0 );
00251 return ( p_mutex->mutex != NULL ? 0 : 1 );
00252 }
00253 else
00254 {
00255 p_mutex->mutex = NULL;
00256 InitializeCriticalSection( &p_mutex->csection );
00257 return 0;
00258 }
00259
00260 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00261
00262 if( p_mutex == NULL )
00263 {
00264 return B_BAD_VALUE;
00265 }
00266
00267 if( p_mutex->init == 9999 )
00268 {
00269 return EALREADY;
00270 }
00271
00272 p_mutex->lock = create_sem( 1, "BeMutex" );
00273 if( p_mutex->lock < B_NO_ERROR )
00274 {
00275 return( -1 );
00276 }
00277
00278 p_mutex->init = 9999;
00279 return B_OK;
00280
00281 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00282 # if defined(DEBUG) && defined(SYS_LINUX)
00283 {
00284
00285 pthread_mutexattr_t attr;
00286 int i_result;
00287
00288 pthread_mutexattr_init( &attr );
00289 pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );
00290 i_result = pthread_mutex_init( &p_mutex->mutex, &attr );
00291 pthread_mutexattr_destroy( &attr );
00292 return( i_result );
00293 }
00294 # endif
00295 return pthread_mutex_init( &p_mutex->mutex, NULL );
00296
00297 #elif defined( HAVE_CTHREADS_H )
00298 mutex_init( p_mutex );
00299 return 0;
00300
00301 #endif
00302 }
00303
00304
00305
00306
00307 int __vlc_mutex_destroy( char * psz_file, int i_line, vlc_mutex_t *p_mutex )
00308 {
00309 int i_result;
00310
00311 int i_thread = -1;
00312 const char * psz_error = "";
00313
00314 #if defined( PTH_INIT_IN_PTH_H )
00315 return 0;
00316
00317 #elif defined( ST_INIT_IN_ST_H )
00318 i_result = st_mutex_destroy( p_mutex->mutex );
00319
00320 #elif defined( UNDER_CE )
00321 DeleteCriticalSection( &p_mutex->csection );
00322 return 0;
00323
00324 #elif defined( WIN32 )
00325 if( p_mutex->mutex )
00326 {
00327 CloseHandle( p_mutex->mutex );
00328 }
00329 else
00330 {
00331 DeleteCriticalSection( &p_mutex->csection );
00332 }
00333 return 0;
00334
00335 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00336 if( p_mutex->init == 9999 )
00337 {
00338 delete_sem( p_mutex->lock );
00339 }
00340
00341 p_mutex->init = 0;
00342 return B_OK;
00343
00344 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00345 i_result = pthread_mutex_destroy( &p_mutex->mutex );
00346 if( i_result )
00347 {
00348 i_thread = (int)pthread_self();
00349 psz_error = strerror(i_result);
00350 }
00351
00352 #elif defined( HAVE_CTHREADS_H )
00353 return 0;
00354
00355 #endif
00356
00357 if( i_result )
00358 {
00359 msg_Err( p_mutex->p_this,
00360 "thread %d: mutex_destroy failed at %s:%d (%d:%s)",
00361 i_thread, psz_file, i_line, i_result, psz_error );
00362 }
00363 return i_result;
00364 }
00365
00366
00367
00368
00369 int __vlc_cond_init( vlc_object_t *p_this, vlc_cond_t *p_condvar )
00370 {
00371 p_condvar->p_this = p_this;
00372
00373 #if defined( PTH_INIT_IN_PTH_H )
00374 return ( pth_cond_init( &p_condvar->cond ) == FALSE );
00375
00376 #elif defined( ST_INIT_IN_ST_H )
00377 p_condvar->cond = st_cond_new();
00378 return ( p_condvar->cond == NULL ) ? errno : 0;
00379
00380 #elif defined( UNDER_CE )
00381
00382 p_condvar->i_waiting_threads = 0;
00383
00384
00385 p_condvar->event = CreateEvent( NULL,
00386 FALSE,
00387 FALSE,
00388 NULL );
00389 return !p_condvar->event;
00390
00391 #elif defined( WIN32 )
00392
00393 p_condvar->i_waiting_threads = 0;
00394
00395
00396 p_condvar->i_win9x_cv = p_this->p_libvlc->i_win9x_cv;
00397 p_condvar->SignalObjectAndWait = p_this->p_libvlc->SignalObjectAndWait;
00398
00399 if( (p_condvar->SignalObjectAndWait && !p_this->p_libvlc->b_fast_mutex)
00400 || p_condvar->i_win9x_cv == 0 )
00401 {
00402
00403 p_condvar->event = CreateEvent( NULL,
00404 FALSE,
00405 FALSE,
00406 NULL );
00407
00408 p_condvar->semaphore = NULL;
00409 return !p_condvar->event;
00410 }
00411 else
00412 {
00413 p_condvar->semaphore = CreateSemaphore( NULL,
00414 0,
00415 0x7fffffff,
00416 NULL );
00417
00418 if( p_condvar->i_win9x_cv == 1 )
00419
00420 p_condvar->event = CreateEvent( NULL, TRUE, TRUE, NULL );
00421 else
00422
00423 p_condvar->event = CreateEvent( NULL, FALSE, FALSE, NULL );
00424
00425 InitializeCriticalSection( &p_condvar->csection );
00426
00427 return !p_condvar->semaphore || !p_condvar->event;
00428 }
00429
00430 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00431 if( !p_condvar )
00432 {
00433 return B_BAD_VALUE;
00434 }
00435
00436 if( p_condvar->init == 9999 )
00437 {
00438 return EALREADY;
00439 }
00440
00441 p_condvar->thread = -1;
00442 p_condvar->init = 9999;
00443 return 0;
00444
00445 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00446 return pthread_cond_init( &p_condvar->cond, NULL );
00447
00448 #elif defined( HAVE_CTHREADS_H )
00449
00450 spin_lock_init( &p_condvar->lock );
00451 cthread_queue_init( &p_condvar->queue );
00452 p_condvar->name = 0;
00453 p_condvar->implications = 0;
00454
00455 return 0;
00456
00457 #endif
00458 }
00459
00460
00461
00462
00463 int __vlc_cond_destroy( char * psz_file, int i_line, vlc_cond_t *p_condvar )
00464 {
00465 int i_result;
00466
00467 int i_thread = -1;
00468 const char * psz_error = "";
00469
00470 #if defined( PTH_INIT_IN_PTH_H )
00471 return 0;
00472
00473 #elif defined( ST_INIT_IN_ST_H )
00474 i_result = st_cond_destroy( p_condvar->cond );
00475
00476 #elif defined( UNDER_CE )
00477 i_result = !CloseHandle( p_condvar->event );
00478
00479 #elif defined( WIN32 )
00480 if( !p_condvar->semaphore )
00481 i_result = !CloseHandle( p_condvar->event );
00482 else
00483 i_result = !CloseHandle( p_condvar->event )
00484 || !CloseHandle( p_condvar->semaphore );
00485
00486 if( p_condvar->semaphore != NULL )
00487 DeleteCriticalSection( &p_condvar->csection );
00488
00489 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00490 p_condvar->init = 0;
00491 return 0;
00492
00493 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00494 i_result = pthread_cond_destroy( &p_condvar->cond );
00495 if( i_result )
00496 {
00497 i_thread = (int)pthread_self();
00498 psz_error = strerror(i_result);
00499 }
00500
00501 #elif defined( HAVE_CTHREADS_H )
00502 return 0;
00503
00504 #endif
00505
00506 if( i_result )
00507 {
00508 msg_Err( p_condvar->p_this,
00509 "thread %d: cond_destroy failed at %s:%d (%d:%s)",
00510 i_thread, psz_file, i_line, i_result, psz_error );
00511 }
00512 return i_result;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521 int __vlc_thread_create( vlc_object_t *p_this, char * psz_file, int i_line,
00522 char *psz_name, void * ( *func ) ( void * ),
00523 int i_priority, vlc_bool_t b_wait )
00524 {
00525 int i_ret;
00526 void *p_data = (void *)p_this;
00527
00528 vlc_mutex_lock( &p_this->object_lock );
00529
00530 #if defined( PTH_INIT_IN_PTH_H )
00531 p_this->thread_id = pth_spawn( PTH_ATTR_DEFAULT, func, p_data );
00532 i_ret = p_this->thread_id == NULL;
00533
00534 #elif defined( ST_INIT_IN_ST_H )
00535 p_this->thread_id = st_thread_create( func, p_data, 1, 0 );
00536 i_ret = 0;
00537
00538 #elif defined( WIN32 ) || defined( UNDER_CE )
00539 {
00540 unsigned threadID;
00541
00542
00543
00544
00545 p_this->thread_id =
00546 #if defined( UNDER_CE )
00547 (HANDLE)CreateThread( NULL, 0, (PTHREAD_START) func,
00548 p_data, 0, &threadID );
00549 #else
00550 (HANDLE)_beginthreadex( NULL, 0, (PTHREAD_START) func,
00551 p_data, 0, &threadID );
00552 #endif
00553 }
00554
00555 if( p_this->thread_id && i_priority )
00556 {
00557 if( !SetThreadPriority(p_this->thread_id, i_priority) )
00558 {
00559 msg_Warn( p_this, "couldn't set a faster priority" );
00560 i_priority = 0;
00561 }
00562 }
00563
00564 i_ret = ( p_this->thread_id ? 0 : 1 );
00565
00566 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00567 p_this->thread_id = spawn_thread( (thread_func)func, psz_name,
00568 i_priority, p_data );
00569 i_ret = resume_thread( p_this->thread_id );
00570
00571 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00572 i_ret = pthread_create( &p_this->thread_id, NULL, func, p_data );
00573
00574 #ifndef SYS_DARWIN
00575 if( config_GetInt( p_this, "rt-priority" ) )
00576 #endif
00577 {
00578 int i_error, i_policy;
00579 struct sched_param param;
00580
00581 memset( ¶m, 0, sizeof(struct sched_param) );
00582 if( config_GetType( p_this, "rt-offset" ) )
00583 {
00584 i_priority += config_GetInt( p_this, "rt-offset" );
00585 }
00586 if( i_priority <= 0 )
00587 {
00588 param.sched_priority = (-1) * i_priority;
00589 i_policy = SCHED_OTHER;
00590 }
00591 else
00592 {
00593 param.sched_priority = i_priority;
00594 i_policy = SCHED_RR;
00595 }
00596 if( (i_error = pthread_setschedparam( p_this->thread_id,
00597 i_policy, ¶m )) )
00598 {
00599 msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
00600 psz_file, i_line, strerror(i_error) );
00601 i_priority = 0;
00602 }
00603 }
00604 #ifndef SYS_DARWIN
00605 else
00606 {
00607 i_priority = 0;
00608 }
00609 #endif
00610
00611 #elif defined( HAVE_CTHREADS_H )
00612 p_this->thread_id = cthread_fork( (cthread_fn_t)func, (any_t)p_data );
00613 i_ret = 0;
00614
00615 #endif
00616
00617 if( i_ret == 0 )
00618 {
00619 if( b_wait )
00620 {
00621 msg_Dbg( p_this, "waiting for thread completion" );
00622 vlc_cond_wait( &p_this->object_wait, &p_this->object_lock );
00623 }
00624
00625 p_this->b_thread = 1;
00626
00627 msg_Dbg( p_this, "thread %u (%s) created at priority %d (%s:%d)",
00628 (unsigned int)p_this->thread_id, psz_name, i_priority,
00629 psz_file, i_line );
00630
00631 vlc_mutex_unlock( &p_this->object_lock );
00632 }
00633 else
00634 {
00635 #ifdef HAVE_STRERROR
00636 msg_Err( p_this, "%s thread could not be created at %s:%d (%s)",
00637 psz_name, psz_file, i_line, strerror(i_ret) );
00638 #else
00639 msg_Err( p_this, "%s thread could not be created at %s:%d",
00640 psz_name, psz_file, i_line );
00641 #endif
00642 vlc_mutex_unlock( &p_this->object_lock );
00643 }
00644
00645 return i_ret;
00646 }
00647
00648
00649
00650
00651
00652 int __vlc_thread_set_priority( vlc_object_t *p_this, char * psz_file,
00653 int i_line, int i_priority )
00654 {
00655 #if defined( PTH_INIT_IN_PTH_H ) || defined( ST_INIT_IN_ST_H )
00656 #elif defined( WIN32 ) || defined( UNDER_CE )
00657 if( !SetThreadPriority(GetCurrentThread(), i_priority) )
00658 {
00659 msg_Warn( p_this, "couldn't set a faster priority" );
00660 return 1;
00661 }
00662
00663 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00664 #ifndef SYS_DARWIN
00665 if( config_GetInt( p_this, "rt-priority" ) )
00666 #endif
00667 {
00668 int i_error, i_policy;
00669 struct sched_param param;
00670
00671 memset( ¶m, 0, sizeof(struct sched_param) );
00672 if( config_GetType( p_this, "rt-offset" ) )
00673 {
00674 i_priority += config_GetInt( p_this, "rt-offset" );
00675 }
00676 if( i_priority <= 0 )
00677 {
00678 param.sched_priority = (-1) * i_priority;
00679 i_policy = SCHED_OTHER;
00680 }
00681 else
00682 {
00683 param.sched_priority = i_priority;
00684 i_policy = SCHED_RR;
00685 }
00686 if( !p_this->thread_id )
00687 p_this->thread_id = pthread_self();
00688 if( (i_error = pthread_setschedparam( p_this->thread_id,
00689 i_policy, ¶m )) )
00690 {
00691 msg_Warn( p_this, "couldn't set thread priority (%s:%d): %s",
00692 psz_file, i_line, strerror(i_error) );
00693 i_priority = 0;
00694 }
00695 }
00696 #endif
00697
00698 return 0;
00699 }
00700
00701
00702
00703
00704 void __vlc_thread_ready( vlc_object_t *p_this )
00705 {
00706 vlc_mutex_lock( &p_this->object_lock );
00707 vlc_cond_signal( &p_this->object_wait );
00708 vlc_mutex_unlock( &p_this->object_lock );
00709 }
00710
00711
00712
00713
00714 void __vlc_thread_join( vlc_object_t *p_this, char * psz_file, int i_line )
00715 {
00716 int i_ret = 0;
00717
00718 #if defined( PTH_INIT_IN_PTH_H )
00719 i_ret = ( pth_join( p_this->thread_id, NULL ) == FALSE );
00720
00721 #elif defined( ST_INIT_IN_ST_H )
00722 i_ret = st_thread_join( p_this->thread_id, NULL );
00723
00724 #elif defined( UNDER_CE ) || defined( WIN32 )
00725 HMODULE hmodule;
00726 BOOL (WINAPI *OurGetThreadTimes)( HANDLE, FILETIME*, FILETIME*,
00727 FILETIME*, FILETIME* );
00728 FILETIME create_ft, exit_ft, kernel_ft, user_ft;
00729 int64_t real_time, kernel_time, user_time;
00730
00731 WaitForSingleObject( p_this->thread_id, INFINITE );
00732
00733 #if defined( UNDER_CE )
00734 hmodule = GetModuleHandle( _T("COREDLL") );
00735 #else
00736 hmodule = GetModuleHandle( _T("KERNEL32") );
00737 #endif
00738 OurGetThreadTimes = (BOOL (WINAPI*)( HANDLE, FILETIME*, FILETIME*,
00739 FILETIME*, FILETIME* ))
00740 GetProcAddress( hmodule, _T("GetThreadTimes") );
00741
00742 if( OurGetThreadTimes &&
00743 OurGetThreadTimes( p_this->thread_id,
00744 &create_ft, &exit_ft, &kernel_ft, &user_ft ) )
00745 {
00746 real_time =
00747 ((((int64_t)exit_ft.dwHighDateTime)<<32)| exit_ft.dwLowDateTime) -
00748 ((((int64_t)create_ft.dwHighDateTime)<<32)| create_ft.dwLowDateTime);
00749 real_time /= 10;
00750
00751 kernel_time =
00752 ((((int64_t)kernel_ft.dwHighDateTime)<<32)|
00753 kernel_ft.dwLowDateTime) / 10;
00754
00755 user_time =
00756 ((((int64_t)user_ft.dwHighDateTime)<<32)|
00757 user_ft.dwLowDateTime) / 10;
00758
00759 msg_Dbg( p_this, "thread times: "
00760 "real "I64Fd"m%fs, kernel "I64Fd"m%fs, user "I64Fd"m%fs",
00761 real_time/60/1000000,
00762 (double)((real_time%(60*1000000))/1000000.0),
00763 kernel_time/60/1000000,
00764 (double)((kernel_time%(60*1000000))/1000000.0),
00765 user_time/60/1000000,
00766 (double)((user_time%(60*1000000))/1000000.0) );
00767 }
00768 CloseHandle( p_this->thread_id );
00769
00770 #elif defined( HAVE_KERNEL_SCHEDULER_H )
00771 int32_t exit_value;
00772 wait_for_thread( p_this->thread_id, &exit_value );
00773
00774 #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
00775 i_ret = pthread_join( p_this->thread_id, NULL );
00776
00777 #elif defined( HAVE_CTHREADS_H )
00778 cthread_join( p_this->thread_id );
00779 i_ret = 1;
00780
00781 #endif
00782
00783 if( i_ret )
00784 {
00785 #ifdef HAVE_STRERROR
00786 msg_Err( p_this, "thread_join(%u) failed at %s:%d (%s)",
00787 (unsigned int)p_this->thread_id, psz_file, i_line,
00788 strerror(i_ret) );
00789 #else
00790 msg_Err( p_this, "thread_join(%u) failed at %s:%d",
00791 (unsigned int)p_this->thread_id, psz_file, i_line );
00792 #endif
00793 }
00794 else
00795 {
00796 msg_Dbg( p_this, "thread %u joined (%s:%d)",
00797 (unsigned int)p_this->thread_id, psz_file, i_line );
00798 }
00799
00800 p_this->b_thread = 0;
00801 }
00802