📄 threads.c
字号:
p_condvar->init = 9999; return 0;#endif}/***************************************************************************** * vlc_cond_destroy: destroy a condition, inner version *****************************************************************************/void __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar ){#if defined( LIBVLC_USE_PTHREAD ) int val = pthread_cond_destroy( p_condvar ); VLC_THREAD_ASSERT ("destroying condition");#elif defined( UNDER_CE ) || defined( WIN32 ) VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); CloseHandle( *p_condvar );#elif defined( HAVE_KERNEL_SCHEDULER_H ) p_condvar->init = 0;#endif}/***************************************************************************** * vlc_tls_create: create a thread-local variable *****************************************************************************/int vlc_threadvar_create( vlc_threadvar_t *p_tls, void (*destr) (void *) ){ int i_ret;#if defined( LIBVLC_USE_PTHREAD ) i_ret = pthread_key_create( p_tls, destr );#elif defined( UNDER_CE ) i_ret = ENOSYS;#elif defined( WIN32 ) /* FIXME: remember/use the destr() callback and stop leaking whatever */ *p_tls = TlsAlloc(); i_ret = (*p_tls == TLS_OUT_OF_INDEXES) ? EAGAIN : 0;#else# error Unimplemented!#endif return i_ret;}void vlc_threadvar_delete (vlc_threadvar_t *p_tls){#if defined( LIBVLC_USE_PTHREAD ) pthread_key_delete (*p_tls);#elif defined( UNDER_CE )#elif defined( WIN32 ) TlsFree (*p_tls);#else# error Unimplemented!#endif}struct vlc_thread_boot{ void * (*entry) (vlc_object_t *); vlc_object_t *object;};#if defined (LIBVLC_USE_PTHREAD)# define THREAD_RTYPE void *# define THREAD_RVAL NULL#elif defined (WIN32)# define THREAD_RTYPE __stdcall unsigned# define THREAD_RVAL 0#endifstatic THREAD_RTYPE thread_entry (void *data){ vlc_object_t *obj = ((struct vlc_thread_boot *)data)->object; void *(*func) (vlc_object_t *) = ((struct vlc_thread_boot *)data)->entry; free (data);#ifndef NDEBUG vlc_threadvar_set (&thread_object_key, obj);#endif msg_Dbg (obj, "thread started"); func (obj); msg_Dbg (obj, "thread ended"); return THREAD_RVAL;}/***************************************************************************** * vlc_thread_create: create a thread, inner version ***************************************************************************** * Note that i_priority is only taken into account on platforms supporting * userland real-time priority threads. *****************************************************************************/int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line, const char *psz_name, void * ( *func ) ( vlc_object_t * ), int i_priority, bool b_wait ){ int i_ret; vlc_object_internals_t *p_priv = vlc_internals( p_this ); struct vlc_thread_boot *boot = malloc (sizeof (*boot)); if (boot == NULL) return errno; boot->entry = func; boot->object = p_this; vlc_object_lock( p_this ); /* Make sure we don't re-create a thread if the object has already one */ assert( !p_priv->b_thread );#if defined( LIBVLC_USE_PTHREAD ) pthread_attr_t attr; pthread_attr_init (&attr); /* Block the signals that signals interface plugin handles. * If the LibVLC caller wants to handle some signals by itself, it should * block these before whenever invoking LibVLC. And it must obviously not * start the VLC signals interface plugin. * * LibVLC will normally ignore any interruption caused by an asynchronous * signal during a system call. But there may well be some buggy cases * where it fails to handle EINTR (bug reports welcome). Some underlying * libraries might also not handle EINTR properly. */ sigset_t set, oldset; sigemptyset (&set); sigdelset (&set, SIGHUP); sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); sigaddset (&set, SIGPIPE); /* We don't want this one, really! */ pthread_sigmask (SIG_BLOCK, &set, &oldset);#ifndef __APPLE__ if( config_GetInt( p_this, "rt-priority" ) > 0 )#endif { struct sched_param p = { .sched_priority = i_priority, }; int policy; /* Hack to avoid error msg */ if( config_GetType( p_this, "rt-offset" ) ) p.sched_priority += config_GetInt( p_this, "rt-offset" ); if( p.sched_priority <= 0 ) p.sched_priority += sched_get_priority_max (policy = SCHED_OTHER); else p.sched_priority += sched_get_priority_min (policy = SCHED_RR); pthread_attr_setschedpolicy (&attr, policy); pthread_attr_setschedparam (&attr, &p); } i_ret = pthread_create( &p_priv->thread_id, &attr, thread_entry, boot ); pthread_sigmask (SIG_SETMASK, &oldset, NULL); pthread_attr_destroy (&attr);#elif defined( WIN32 ) || defined( UNDER_CE ) /* When using the MSVCRT C library you have to use the _beginthreadex * function instead of CreateThread, otherwise you'll end up with * memory leaks and the signal functions not working (see Microsoft * Knowledge Base, article 104641) */#if defined( UNDER_CE ) HANDLE hThread = CreateThread( NULL, 0, thread_entry, (LPVOID)boot, CREATE_SUSPENDED, NULL );#else HANDLE hThread = (HANDLE)(uintptr_t) _beginthreadex( NULL, 0, thread_entry, boot, CREATE_SUSPENDED, NULL );#endif if( hThread ) { p_priv->thread_id = hThread; ResumeThread (hThread); i_ret = 0; if( i_priority && !SetThreadPriority (hThread, i_priority) ) { msg_Warn( p_this, "couldn't set a faster priority" ); i_priority = 0; } } else i_ret = errno;#elif defined( HAVE_KERNEL_SCHEDULER_H ) p_priv->thread_id = spawn_thread( (thread_func)thread_entry, psz_name, i_priority, p_data ); i_ret = resume_thread( p_priv->thread_id );#endif if( i_ret == 0 ) { if( b_wait ) { msg_Dbg( p_this, "waiting for thread initialization" ); vlc_object_wait( p_this ); } p_priv->b_thread = true; msg_Dbg( p_this, "thread %lu (%s) created at priority %d (%s:%d)", (unsigned long)p_priv->thread_id, psz_name, i_priority, psz_file, i_line ); } else { errno = i_ret; msg_Err( p_this, "%s thread could not be created at %s:%d (%m)", psz_name, psz_file, i_line ); } vlc_object_unlock( p_this ); return i_ret;}/***************************************************************************** * vlc_thread_set_priority: set the priority of the current thread when we * couldn't set it in vlc_thread_create (for instance for the main thread) *****************************************************************************/int __vlc_thread_set_priority( vlc_object_t *p_this, const char * psz_file, int i_line, int i_priority ){ vlc_object_internals_t *p_priv = vlc_internals( p_this ); if( !p_priv->b_thread ) { msg_Err( p_this, "couldn't set priority of non-existent thread" ); return ESRCH; }#if defined( LIBVLC_USE_PTHREAD )# ifndef __APPLE__ if( config_GetInt( p_this, "rt-priority" ) > 0 )# endif { int i_error, i_policy; struct sched_param param; memset( ¶m, 0, sizeof(struct sched_param) ); if( config_GetType( p_this, "rt-offset" ) ) i_priority += config_GetInt( p_this, "rt-offset" ); if( i_priority <= 0 ) { param.sched_priority = (-1) * i_priority; i_policy = SCHED_OTHER; } else { param.sched_priority = i_priority; i_policy = SCHED_RR; } if( (i_error = pthread_setschedparam( p_priv->thread_id, i_policy, ¶m )) ) { errno = i_error; msg_Warn( p_this, "couldn't set thread priority (%s:%d): %m", psz_file, i_line ); i_priority = 0; } }#elif defined( WIN32 ) || defined( UNDER_CE ) VLC_UNUSED( psz_file); VLC_UNUSED( i_line ); if( !SetThreadPriority(p_priv->thread_id, i_priority) ) { msg_Warn( p_this, "couldn't set a faster priority" ); return 1; }#endif return 0;}/***************************************************************************** * vlc_thread_join: wait until a thread exits, inner version *****************************************************************************/void __vlc_thread_join( vlc_object_t *p_this, const char * psz_file, int i_line ){ vlc_object_internals_t *p_priv = vlc_internals( p_this ); int i_ret = 0;#if defined( LIBVLC_USE_PTHREAD ) /* Make sure we do return if we are calling vlc_thread_join() * from the joined thread */ if (pthread_equal (pthread_self (), p_priv->thread_id)) { msg_Warn (p_this, "joining the active thread (VLC might crash)"); i_ret = pthread_detach (p_priv->thread_id); } else i_ret = pthread_join (p_priv->thread_id, NULL);#elif defined( UNDER_CE ) || defined( WIN32 ) HMODULE hmodule; BOOL (WINAPI *OurGetThreadTimes)( HANDLE, FILETIME*, FILETIME*, FILETIME*, FILETIME* ); FILETIME create_ft, exit_ft, kernel_ft, user_ft; int64_t real_time, kernel_time, user_time; HANDLE hThread; /* ** object will close its thread handle when destroyed, duplicate it here ** to be on the safe side */ if( ! DuplicateHandle(GetCurrentProcess(), p_priv->thread_id, GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS) ) { p_priv->b_thread = false; i_ret = GetLastError(); goto error; } WaitForSingleObject( hThread, INFINITE );#if defined( UNDER_CE ) hmodule = GetModuleHandle( _T("COREDLL") );#else hmodule = GetModuleHandle( _T("KERNEL32") );#endif OurGetThreadTimes = (BOOL (WINAPI*)( HANDLE, FILETIME*, FILETIME*, FILETIME*, FILETIME* )) GetProcAddress( hmodule, _T("GetThreadTimes") ); if( OurGetThreadTimes && OurGetThreadTimes( hThread, &create_ft, &exit_ft, &kernel_ft, &user_ft ) ) { real_time = ((((int64_t)exit_ft.dwHighDateTime)<<32)| exit_ft.dwLowDateTime) - ((((int64_t)create_ft.dwHighDateTime)<<32)| create_ft.dwLowDateTime); real_time /= 10; kernel_time = ((((int64_t)kernel_ft.dwHighDateTime)<<32)| kernel_ft.dwLowDateTime) / 10; user_time = ((((int64_t)user_ft.dwHighDateTime)<<32)| user_ft.dwLowDateTime) / 10; msg_Dbg( p_this, "thread times: " "real %"PRId64"m%fs, kernel %"PRId64"m%fs, user %"PRId64"m%fs", real_time/60/1000000, (double)((real_time%(60*1000000))/1000000.0), kernel_time/60/1000000, (double)((kernel_time%(60*1000000))/1000000.0), user_time/60/1000000, (double)((user_time%(60*1000000))/1000000.0) ); } CloseHandle( hThread );error:#elif defined( HAVE_KERNEL_SCHEDULER_H ) int32_t exit_value; i_ret = (B_OK == wait_for_thread( p_priv->thread_id, &exit_value ));#endif if( i_ret ) { errno = i_ret; msg_Err( p_this, "thread_join(%lu) failed at %s:%d (%m)", (unsigned long)p_priv->thread_id, psz_file, i_line ); } else msg_Dbg( p_this, "thread %lu joined (%s:%d)", (unsigned long)p_priv->thread_id, psz_file, i_line ); p_priv->b_thread = false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -