⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threads.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
    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( &param, 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, &param )) )        {            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 + -