Commit 651078ec authored by Clément Stenac's avatar Clément Stenac

Added initial support for TLS (Thread Local Storage) variables

parent 965e95ec
...@@ -139,6 +139,9 @@ typedef struct ...@@ -139,6 +139,9 @@ typedef struct
pth_cond_t cond; pth_cond_t cond;
vlc_object_t * p_this; vlc_object_t * p_this;
} vlc_cond_t; } vlc_cond_t;
typedef struct
{
} vlc_threadvar_t;
#elif defined( ST_INIT_IN_ST_H ) #elif defined( ST_INIT_IN_ST_H )
typedef st_thread_t vlc_thread_t; typedef st_thread_t vlc_thread_t;
...@@ -152,6 +155,9 @@ typedef struct ...@@ -152,6 +155,9 @@ typedef struct
st_cond_t cond; st_cond_t cond;
vlc_object_t * p_this; vlc_object_t * p_this;
} vlc_cond_t; } vlc_cond_t;
typedef struct
{
} vlc_threadvar_t;
#elif defined( WIN32 ) || defined( UNDER_CE ) #elif defined( WIN32 ) || defined( UNDER_CE )
typedef HANDLE vlc_thread_t; typedef HANDLE vlc_thread_t;
...@@ -182,6 +188,11 @@ typedef struct ...@@ -182,6 +188,11 @@ typedef struct
vlc_object_t * p_this; vlc_object_t * p_this;
} vlc_cond_t; } vlc_cond_t;
typedef struct
{
DWORD handle;
} vlc_threadvar_t;
#elif defined( HAVE_KERNEL_SCHEDULER_H ) #elif defined( HAVE_KERNEL_SCHEDULER_H )
/* This is the BeOS implementation of the vlc threads, note that the mutex is /* This is the BeOS implementation of the vlc threads, note that the mutex is
* not a real mutex and the cond_var is not like a pthread cond_var but it is * not a real mutex and the cond_var is not like a pthread cond_var but it is
...@@ -205,6 +216,11 @@ typedef struct ...@@ -205,6 +216,11 @@ typedef struct
vlc_object_t * p_this; vlc_object_t * p_this;
} vlc_cond_t; } vlc_cond_t;
typedef struct
{
} vlc_threadvar_t;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) #elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
typedef pthread_t vlc_thread_t; typedef pthread_t vlc_thread_t;
typedef struct typedef struct
...@@ -218,6 +234,11 @@ typedef struct ...@@ -218,6 +234,11 @@ typedef struct
vlc_object_t * p_this; vlc_object_t * p_this;
} vlc_cond_t; } vlc_cond_t;
typedef struct
{
pthread_key_t handle;
} vlc_threadvar_t;
#elif defined( HAVE_CTHREADS_H ) #elif defined( HAVE_CTHREADS_H )
typedef cthread_t vlc_thread_t; typedef cthread_t vlc_thread_t;
...@@ -244,5 +265,10 @@ typedef struct ...@@ -244,5 +265,10 @@ typedef struct
vlc_object_t * p_this; vlc_object_t * p_this;
} vlc_cond_t; } vlc_cond_t;
typedef struct
{
cthread_key_t handle;
} vlc_threadvar_t;
#endif #endif
...@@ -38,6 +38,7 @@ VLC_EXPORT( int, __vlc_mutex_init, ( vlc_object_t *, vlc_mutex_t * ) ); ...@@ -38,6 +38,7 @@ VLC_EXPORT( int, __vlc_mutex_init, ( vlc_object_t *, vlc_mutex_t * ) );
VLC_EXPORT( int, __vlc_mutex_destroy, ( const char *, int, vlc_mutex_t * ) ); VLC_EXPORT( int, __vlc_mutex_destroy, ( const char *, int, vlc_mutex_t * ) );
VLC_EXPORT( int, __vlc_cond_init, ( vlc_object_t *, vlc_cond_t * ) ); VLC_EXPORT( int, __vlc_cond_init, ( vlc_object_t *, vlc_cond_t * ) );
VLC_EXPORT( int, __vlc_cond_destroy, ( const char *, int, vlc_cond_t * ) ); VLC_EXPORT( int, __vlc_cond_destroy, ( const char *, int, vlc_cond_t * ) );
VLC_EXPORT( int, __vlc_threadvar_create, (vlc_object_t *, vlc_threadvar_t * ) );
VLC_EXPORT( int, __vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( void * ), int, vlc_bool_t ) ); VLC_EXPORT( int, __vlc_thread_create, ( vlc_object_t *, const char *, int, const char *, void * ( * ) ( void * ), int, vlc_bool_t ) );
VLC_EXPORT( int, __vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) ); VLC_EXPORT( int, __vlc_thread_set_priority, ( vlc_object_t *, const char *, int, int ) );
VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) ); VLC_EXPORT( void, __vlc_thread_ready, ( vlc_object_t * ) );
...@@ -547,6 +548,71 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, ...@@ -547,6 +548,71 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line,
#define vlc_cond_destroy( P_COND ) \ #define vlc_cond_destroy( P_COND ) \
__vlc_cond_destroy( __FILE__, __LINE__, P_COND ) __vlc_cond_destroy( __FILE__, __LINE__, P_COND )
/*****************************************************************************
* vlc_threadvar_create: create a thread-local variable
*****************************************************************************/
#define vlc_threadvar_create( PTHIS, P_TLS ) \
__vlc_threadvar_create( PTHIS, P_TLS )
/*****************************************************************************
* vlc_threadvar_set: create: set the value of a thread-local variable
*****************************************************************************/
#define vlc_threadvar_set( P_TLS , P_VAL ) \
__vlc_threadvar_set( __FILE__, __LINE__, P_TLS, P_VAL )
static inline int __vlc_threadvar_set( char* psz_file, int line,
vlc_threadvar_t * p_tls, void *p_value )
{
int i_ret;
#if defined( PTH_INIT_IN_PTH_H ) || \
defined( ST_INIT_IN_ST_H ) || defined( HAVE_KERNEL_SCHEDULER_H )
return -1;
#elif defined( UNDER_CE ) || defined( WIN32 )
i_ret = ( TlsSetValue( &p_tls->handle, p_value ) != 0 );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
i_ret = pthread_setspecific( p_tls->handle, p_value );
#elif defined( HAVE_CTHREADS_H )
i_ret = cthread_setspecific( p_tls->handle, p_value );
#endif
return i_ret;
}
/*****************************************************************************
* vlc_threadvar_get: create: get the value of a thread-local variable
*****************************************************************************/
#define vlc_threadvar_get( P_TLS ) \
__vlc_threadvar_get( __FILE__, __LINE__, P_TLS )
static inline void* __vlc_threadvar_get( char* psz_file, int line,
vlc_threadvar_t * p_tls )
{
void* p_ret;
#if defined( PTH_INIT_IN_PTH_H ) || \
defined( ST_INIT_IN_ST_H ) || defined( HAVE_KERNEL_SCHEDULER_H )
return NULL;
#elif defined( UNDER_CE ) || defined( WIN32 )
p_ret = TlsGetValue( &p_tls->handle );
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
p_ret = pthread_getspecific( p_tls->handle );
#elif defined( HAVE_CTHREADS_H )
if ( !cthread_getspecific( p_tls->handle, &p_ret ) )
{
p_ret = NULL;
}
#endif
return p_ret;
}
/***************************************************************************** /*****************************************************************************
* vlc_thread_create: create a thread * vlc_thread_create: create a thread
*****************************************************************************/ *****************************************************************************/
......
...@@ -500,6 +500,36 @@ int __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar ...@@ -500,6 +500,36 @@ int __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar
return i_result; return i_result;
} }
/*****************************************************************************
* vlc_tls_create: create a thread-local variable
*****************************************************************************/
int __vlc_threadvar_create( vlc_object_t *p_this, vlc_threadvar_t *p_tls )
{
#if defined( PTH_INIT_IN_PTH_H )
#elif defined( HAVE_KERNEL_SCHEDULER_H )
#elif defined( ST_INIT_IN_ST_H )
msg_Err( p_this, "TLS not implemented" );
return VLC_EGENERIC;
#elif defined( UNDER_CE ) || defined( WIN32 )
#elif defined( WIN32 )
p_tls->handle = TlsAlloc();
if( p_tls->handle == 0xFFFFFFFF )
{
return VLC_EGENERIC;
}
msg_Err( p_this, "TLS not implemented" );
return VLC_EGENERIC;
#elif defined( PTHREAD_COND_T_IN_PTHREAD_H )
return pthread_key_create( &p_tls->handle, NULL );
#elif defined( HAVE_CTHREADS_H )
return cthread_keycreate( &p_tls-handle );
#endif
}
/***************************************************************************** /*****************************************************************************
* vlc_thread_create: create a thread, inner version * vlc_thread_create: create a thread, inner version
***************************************************************************** *****************************************************************************
......
...@@ -3,6 +3,9 @@ import unittest ...@@ -3,6 +3,9 @@ import unittest
import native_libvlc_test import native_libvlc_test
class NativeLibvlcTestCase( unittest.TestCase ): class NativeLibvlcTestCase( unittest.TestCase ):
def testTls( self ):
"""[Thread] Set TLS"""
native_libvlc_test.threadvar_test()
def test1Exception( self ): def test1Exception( self ):
"""[LibVLC] Checks libvlc_exception""" """[LibVLC] Checks libvlc_exception"""
# native_libvlc_test.exception_test() # native_libvlc_test.exception_test()
......
...@@ -24,6 +24,7 @@ static PyMethodDef native_libvlc_test_methods[] = { ...@@ -24,6 +24,7 @@ static PyMethodDef native_libvlc_test_methods[] = {
DEF_METHOD( bsearch_direct_test, "Test Bsearch without structure" ) DEF_METHOD( bsearch_direct_test, "Test Bsearch without structure" )
DEF_METHOD( bsearch_member_test, "Test Bsearch with structure" ) DEF_METHOD( bsearch_member_test, "Test Bsearch with structure" )
DEF_METHOD( dict_test, "Test dictionnaries" ) DEF_METHOD( dict_test, "Test dictionnaries" )
DEF_METHOD( threadvar_test, "Test TLS" )
{ NULL, NULL, 0, NULL } { NULL, NULL, 0, NULL }
}; };
......
...@@ -6,6 +6,8 @@ PyObject *create_destroy( PyObject *self, PyObject *args ); ...@@ -6,6 +6,8 @@ PyObject *create_destroy( PyObject *self, PyObject *args );
PyObject *playlist_test( PyObject *self, PyObject *args ); PyObject *playlist_test( PyObject *self, PyObject *args );
PyObject *vlm_test( PyObject *self, PyObject *args ); PyObject *vlm_test( PyObject *self, PyObject *args );
PyObject *threadvar_test( PyObject *self, PyObject *args );
/* Stats */ /* Stats */
PyObject *timers_test( PyObject *self, PyObject *args ); PyObject *timers_test( PyObject *self, PyObject *args );
......
#include "../pyunit.h"
#include <vlc/vlc.h>
PyObject *threadvar_test( PyObject *self, PyObject *args )
{
void *p_foo = malloc(1);
vlc_threadvar_t key, key2;
vlc_threadvar_create( NULL, &key );
vlc_threadvar_set( &key, p_foo );
ASSERT( vlc_threadvar_get( &key ) == p_foo, "key does not match" );
vlc_threadvar_create( NULL, &key2 );
vlc_threadvar_set( &key2, NULL );
ASSERT( vlc_threadvar_get( &key2 ) == NULL, "key2 does not match" );
Py_INCREF( Py_None );
return Py_None;
}
...@@ -42,7 +42,7 @@ def get_ldflags(): ...@@ -42,7 +42,7 @@ def get_ldflags():
native_libvlc_test = Extension( 'native_libvlc_test', native_libvlc_test = Extension( 'native_libvlc_test',
sources = ['native/init.c', 'native/url.c', 'native/i18n.c', sources = ['native/init.c', 'native/url.c', 'native/i18n.c',
'native/stats.c', 'native/libvlc.c', 'native/profiles.c', 'native/stats.c', 'native/libvlc.c', 'native/profiles.c',
'native/algo.c'], 'native/algo.c', 'native/threads.c'],
include_dirs = ['../include', '../', '/usr/win32/include' ], include_dirs = ['../include', '../', '/usr/win32/include' ],
extra_objects = [ '../src/.libs/libvlc.so', '../src/.libs/libvlc-control.so' ], extra_objects = [ '../src/.libs/libvlc.so', '../src/.libs/libvlc-control.so' ],
extra_compile_args = get_cflags(), extra_compile_args = get_cflags(),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment