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

📄 threads.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * threads.c : threads implementation for the VideoLAN client ***************************************************************************** * Copyright (C) 1999-2007 the VideoLAN team * $Id: 3218f5eb6efb1cf86c00a1c08f8f4d2a100d17f0 $ * * Authors: Jean-Marc Dressler <polux@via.ecp.fr> *          Samuel Hocevar <sam@zoy.org> *          Gildas Bazin <gbazin@netcourrier.com> *          Clément Sténac * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include "libvlc.h"#include <assert.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <signal.h>#define VLC_THREADS_UNINITIALIZED  0#define VLC_THREADS_PENDING        1#define VLC_THREADS_ERROR          2#define VLC_THREADS_READY          3/***************************************************************************** * Global mutex for lazy initialization of the threads system *****************************************************************************/static volatile unsigned i_initializations = 0;#if defined( LIBVLC_USE_PTHREAD )# include <sched.h>static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;#endif/** * Global process-wide VLC object. * Contains inter-instance data, such as the module cache and global mutexes. */static libvlc_global_data_t *p_root;libvlc_global_data_t *vlc_global( void ){    assert( i_initializations > 0 );    return p_root;}#ifndef NDEBUG/** * Object running the current thread */static vlc_threadvar_t thread_object_key;vlc_object_t *vlc_threadobj (void){    return vlc_threadvar_get (&thread_object_key);}#endifvlc_threadvar_t msg_context_global_key;#if defined(LIBVLC_USE_PTHREAD)static inline unsigned long vlc_threadid (void){     union { pthread_t th; unsigned long int i; } v = { };     v.th = pthread_self ();     return v.i;}#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE)# include <execinfo.h>#endif/***************************************************************************** * vlc_thread_fatal: Report an error from the threading layer ***************************************************************************** * This is mostly meant for debugging. *****************************************************************************/void vlc_pthread_fatal (const char *action, int error,                        const char *file, unsigned line){    fprintf (stderr, "LibVLC fatal error %s in thread %lu at %s:%u: %d\n",             action, vlc_threadid (), file, line, error);    /* Sometimes strerror_r() crashes too, so make sure we print an error     * message before we invoke it */#ifdef __GLIBC__    /* Avoid the strerror_r() prototype brain damage in glibc */    errno = error;    fprintf (stderr, " Error message: %m at:\n");#else    char buf[1000];    const char *msg;    switch (strerror_r (error, buf, sizeof (buf)))    {        case 0:            msg = buf;            break;        case ERANGE: /* should never happen */            msg = "unknwon (too big to display)";            break;        default:            msg = "unknown (invalid error number)";            break;    }    fprintf (stderr, " Error message: %s\n", msg);#endif    fflush (stderr);#ifdef HAVE_BACKTRACE    void *stack[20];    int len = backtrace (stack, sizeof (stack) / sizeof (stack[0]));    backtrace_symbols_fd (stack, len, 2);#endif    abort ();}#elsevoid vlc_pthread_fatal (const char *action, int error,                        const char *file, unsigned line){    (void)action; (void)error; (void)file; (void)line;    abort();}#endif/***************************************************************************** * vlc_threads_init: initialize threads system ***************************************************************************** * This function requires lazy initialization of a global lock in order to * keep the library really thread-safe. Some architectures don't support this * and thus do not guarantee the complete reentrancy. *****************************************************************************/int vlc_threads_init( void ){    int i_ret = VLC_SUCCESS;    /* If we have lazy mutex initialization, use it. Otherwise, we just     * hope nothing wrong happens. */#if defined( LIBVLC_USE_PTHREAD )    pthread_mutex_lock( &once_mutex );#endif    if( i_initializations == 0 )    {        p_root = vlc_custom_create( (vlc_object_t *)NULL, sizeof( *p_root ),                                    VLC_OBJECT_GENERIC, "root" );        if( p_root == NULL )        {            i_ret = VLC_ENOMEM;            goto out;        }        /* We should be safe now. Do all the initialization stuff we want. */#ifndef NDEBUG        vlc_threadvar_create( &thread_object_key, NULL );#endif        vlc_threadvar_create( &msg_context_global_key, msg_StackDestroy );    }    i_initializations++;out:    /* If we have lazy mutex initialization support, unlock the mutex.     * Otherwize, we are screwed. */#if defined( LIBVLC_USE_PTHREAD )    pthread_mutex_unlock( &once_mutex );#endif    return i_ret;}/***************************************************************************** * vlc_threads_end: stop threads system ***************************************************************************** * FIXME: This function is far from being threadsafe. *****************************************************************************/void vlc_threads_end( void ){#if defined( LIBVLC_USE_PTHREAD )    pthread_mutex_lock( &once_mutex );#endif    assert( i_initializations > 0 );    if( i_initializations == 1 )    {        vlc_object_release( p_root );        vlc_threadvar_delete( &msg_context_global_key );#ifndef NDEBUG        vlc_threadvar_delete( &thread_object_key );#endif    }    i_initializations--;#if defined( LIBVLC_USE_PTHREAD )    pthread_mutex_unlock( &once_mutex );#endif}#if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6)/* This is not prototyped under glibc, though it exists. */int pthread_mutexattr_setkind_np( pthread_mutexattr_t *attr, int kind );#endif/***************************************************************************** * vlc_mutex_init: initialize a mutex *****************************************************************************/int vlc_mutex_init( vlc_mutex_t *p_mutex ){#if defined( LIBVLC_USE_PTHREAD )    pthread_mutexattr_t attr;    int                 i_result;    pthread_mutexattr_init( &attr );# ifndef NDEBUG    /* Create error-checking mutex to detect problems more easily. */#  if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6)    pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_ERRORCHECK_NP );#  else    pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK );#  endif# endif    i_result = pthread_mutex_init( p_mutex, &attr );    pthread_mutexattr_destroy( &attr );    return i_result;#elif defined( UNDER_CE )    InitializeCriticalSection( &p_mutex->csection );    return 0;#elif defined( WIN32 )    *p_mutex = CreateMutex( NULL, FALSE, NULL );    return (*p_mutex != NULL) ? 0 : ENOMEM;#elif defined( HAVE_KERNEL_SCHEDULER_H )    /* check the arguments and whether it's already been initialized */    if( p_mutex == NULL )    {        return B_BAD_VALUE;    }    if( p_mutex->init == 9999 )    {        return EALREADY;    }    p_mutex->lock = create_sem( 1, "BeMutex" );    if( p_mutex->lock < B_NO_ERROR )    {        return( -1 );    }    p_mutex->init = 9999;    return B_OK;#endif}/***************************************************************************** * vlc_mutex_init: initialize a recursive mutex (Do not use) *****************************************************************************/int vlc_mutex_init_recursive( vlc_mutex_t *p_mutex ){#if defined( LIBVLC_USE_PTHREAD )    pthread_mutexattr_t attr;    int                 i_result;    pthread_mutexattr_init( &attr );#  if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6)    pthread_mutexattr_setkind_np( &attr, PTHREAD_MUTEX_RECURSIVE_NP );#  else    pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );#  endif    i_result = pthread_mutex_init( p_mutex, &attr );    pthread_mutexattr_destroy( &attr );    return( i_result );#elif defined( WIN32 )    /* Create mutex returns a recursive mutex */    *p_mutex = CreateMutex( 0, FALSE, 0 );    return (*p_mutex != NULL) ? 0 : ENOMEM;#else# error Unimplemented!#endif}/***************************************************************************** * vlc_mutex_destroy: destroy a mutex, inner version *****************************************************************************/void __vlc_mutex_destroy( const char * psz_file, int i_line, vlc_mutex_t *p_mutex ){#if defined( LIBVLC_USE_PTHREAD )    int val = pthread_mutex_destroy( p_mutex );    VLC_THREAD_ASSERT ("destroying mutex");#elif defined( UNDER_CE )    VLC_UNUSED( psz_file); VLC_UNUSED( i_line );    DeleteCriticalSection( &p_mutex->csection );#elif defined( WIN32 )    VLC_UNUSED( psz_file); VLC_UNUSED( i_line );    CloseHandle( *p_mutex );#elif defined( HAVE_KERNEL_SCHEDULER_H )    if( p_mutex->init == 9999 )        delete_sem( p_mutex->lock );    p_mutex->init = 0;#endif}/***************************************************************************** * vlc_cond_init: initialize a condition *****************************************************************************/int __vlc_cond_init( vlc_cond_t *p_condvar ){#if defined( LIBVLC_USE_PTHREAD )    pthread_condattr_t attr;    int ret;    ret = pthread_condattr_init (&attr);    if (ret)        return ret;# if !defined (_POSIX_CLOCK_SELECTION)   /* Fairly outdated POSIX support (that was defined in 2001) */#  define _POSIX_CLOCK_SELECTION (-1)# endif# if (_POSIX_CLOCK_SELECTION >= 0)    /* NOTE: This must be the same clock as the one in mtime.c */    pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);# endif    ret = pthread_cond_init (p_condvar, &attr);    pthread_condattr_destroy (&attr);    return ret;#elif defined( UNDER_CE ) || defined( WIN32 )    /* Create an auto-reset event. */    *p_condvar = CreateEvent( NULL,   /* no security */                              FALSE,  /* auto-reset event */                              FALSE,  /* start non-signaled */                              NULL ); /* unnamed */    return *p_condvar ? 0 : ENOMEM;#elif defined( HAVE_KERNEL_SCHEDULER_H )    if( !p_condvar )    {        return B_BAD_VALUE;    }    if( p_condvar->init == 9999 )    {        return EALREADY;    }    p_condvar->thread = -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -