X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fthreads.c;h=75aed7077c54218d39648cc27a1cc68b02e8028e;hb=31196681e079413f491febb8eabf996f4e2b445a;hp=68472bb2329c633e69ffab9869249118dae34959;hpb=75ba8eb991b640254a6106e00db86c4ed411e0da;p=vlc diff --git a/src/misc/threads.c b/src/misc/threads.c index 68472bb232..75aed7077c 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -39,36 +39,23 @@ #endif #include -/***************************************************************************** - * Global mutex for lazy initialization of the threads system - *****************************************************************************/ -static volatile unsigned i_initializations = 0; - #if defined( LIBVLC_USE_PTHREAD ) # include - -static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER; +# ifdef __linux__ +# include /* SYS_gettid */ +# endif #else static vlc_threadvar_t cancel_key; #endif -/** - * Global process-wide VLC object. - * Contains the global named mutexes. - * TODO: remove it. - */ -static vlc_object_t *p_root; - -vlc_object_t *vlc_global( void ) -{ - assert( i_initializations > 0 ); - return p_root; -} - #ifdef HAVE_EXECINFO_H # include #endif +#ifdef __APPLE__ +# include /* gettimeofday in vlc_cond_timedwait */ +#endif + /** * Print a backtrace to the standard error for debugging purpose. */ @@ -88,11 +75,16 @@ void vlc_trace (const char *fn, const char *file, unsigned line) static inline unsigned long vlc_threadid (void) { -#if defined(LIBVLC_USE_PTHREAD) +#if defined (LIBVLC_USE_PTHREAD) +# if defined (__linux__) + return syscall (SYS_gettid); + +# else union { pthread_t th; unsigned long int i; } v = { }; v.th = pthread_self (); return v.i; +#endif #elif defined (WIN32) return GetCurrentThreadId (); @@ -160,81 +152,120 @@ typedef struct vlc_cancel_t vlc_cleanup_t *cleaners; bool killable; bool killed; +# ifdef UNDER_CE + HANDLE cancel_event; +# endif } vlc_cancel_t; -# define VLC_CANCEL_INIT { NULL, true, false } +# ifndef UNDER_CE +# define VLC_CANCEL_INIT { NULL, true, false } +# else +# define VLC_CANCEL_INIT { NULL, true, false, NULL } +# endif #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 +#ifdef UNDER_CE +static void CALLBACK vlc_cancel_self (ULONG_PTR dummy); - if( i_initializations == 0 ) +static DWORD vlc_cancelable_wait (DWORD count, const HANDLE *handles, + DWORD delay) +{ + vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key); + if (nfo == NULL) { - 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; - } + /* Main thread - cannot be cancelled anyway */ + return WaitForMultipleObjects (count, handles, FALSE, delay); + } + HANDLE new_handles[count + 1]; + memcpy(new_handles, handles, count * sizeof(HANDLE)); + new_handles[count] = nfo->cancel_event; + DWORD result = WaitForMultipleObjects (count + 1, new_handles, FALSE, + delay); + if (result == WAIT_OBJECT_0 + count) + { + vlc_cancel_self (NULL); + return WAIT_IO_COMPLETION; + } + else + { + return result; + } +} - /* We should be safe now. Do all the initialization stuff we want. */ -#ifndef LIBVLC_USE_PTHREAD_CANCEL - vlc_threadvar_create( &cancel_key, free ); -#endif +DWORD SleepEx (DWORD dwMilliseconds, BOOL bAlertable) +{ + if (bAlertable) + { + DWORD result = vlc_cancelable_wait (0, NULL, dwMilliseconds); + return (result == WAIT_TIMEOUT) ? 0 : WAIT_IO_COMPLETION; + } + else + { + Sleep(dwMilliseconds); + return 0; } - 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 ); +DWORD WaitForSingleObjectEx (HANDLE hHandle, DWORD dwMilliseconds, + BOOL bAlertable) +{ + if (bAlertable) + { + /* The MSDN documentation specifies different return codes, + * but in practice they are the same. We just check that it + * remains so. */ +#if WAIT_ABANDONED != WAIT_ABANDONED_0 +# error Windows headers changed, code needs to be rewritten! #endif - - return i_ret; + return vlc_cancelable_wait (1, &hHandle, dwMilliseconds); + } + else + { + return WaitForSingleObject (hHandle, dwMilliseconds); + } } -/***************************************************************************** - * vlc_threads_end: stop threads system - ***************************************************************************** - * FIXME: This function is far from being threadsafe. - *****************************************************************************/ -void vlc_threads_end( void ) +DWORD WaitForMultipleObjectsEx (DWORD nCount, const HANDLE *lpHandles, + BOOL bWaitAll, DWORD dwMilliseconds, + BOOL bAlertable) { -#if defined( LIBVLC_USE_PTHREAD ) - pthread_mutex_lock( &once_mutex ); + if (bAlertable) + { + /* We do not support the bWaitAll case */ + assert (! bWaitAll); + return vlc_cancelable_wait (nCount, lpHandles, dwMilliseconds); + } + else + { + return WaitForMultipleObjects (nCount, lpHandles, bWaitAll, + dwMilliseconds); + } +} #endif - assert( i_initializations > 0 ); +#ifdef WIN32 +static vlc_mutex_t super_mutex; + +BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) +{ + (void) hinstDll; + (void) lpvReserved; - if( i_initializations == 1 ) + switch (fdwReason) { - vlc_object_release( p_root ); -#ifndef LIBVLC_USE_PTHREAD - vlc_threadvar_delete( &cancel_key ); -#endif - } - i_initializations--; + case DLL_PROCESS_ATTACH: + vlc_mutex_init (&super_mutex); + vlc_threadvar_create (&cancel_key, free); + break; -#if defined( LIBVLC_USE_PTHREAD ) - pthread_mutex_unlock( &once_mutex ); -#endif + case DLL_PROCESS_DETACH: + vlc_threadvar_delete( &cancel_key ); + vlc_mutex_destroy (&super_mutex); + break; + } + return TRUE; } +#endif #if defined (__GLIBC__) && (__GLIBC_MINOR__ < 6) /* This is not prototyped under glibc, though it exists. */ @@ -265,8 +296,10 @@ int vlc_mutex_init( vlc_mutex_t *p_mutex ) return i_result; #elif defined( WIN32 ) + /* This creates a recursive mutex. This is OK as fast mutexes have + * no defined behavior in case of recursive locking. */ InitializeCriticalSection (&p_mutex->mutex); - p_mutex->recursive = false; + p_mutex->initialized = 1; return 0; #endif @@ -293,9 +326,7 @@ int vlc_mutex_init_recursive( vlc_mutex_t *p_mutex ) #elif defined( WIN32 ) InitializeCriticalSection( &p_mutex->mutex ); - p_mutex->owner = 0; /* the error value for GetThreadId()! */ - p_mutex->recursion = 0; - p_mutex->recursive = true; + p_mutex->initialized = 1; return 0; #endif @@ -315,6 +346,7 @@ void vlc_mutex_destroy (vlc_mutex_t *p_mutex) VLC_THREAD_ASSERT ("destroying mutex"); #elif defined( WIN32 ) + assert (InterlockedExchange (&p_mutex->initialized, -1) == 1); DeleteCriticalSection (&p_mutex->mutex); #endif @@ -324,6 +356,7 @@ void vlc_mutex_destroy (vlc_mutex_t *p_mutex) * Acquires a mutex. If needed, waits for any other thread to release it. * Beware of deadlocks when locking multiple mutexes at the same time, * or when using mutexes from callbacks. + * This function is not a cancellation-point. * * @param p_mutex mutex initialized with vlc_mutex_init() or * vlc_mutex_init_recursive() @@ -335,29 +368,62 @@ void vlc_mutex_lock (vlc_mutex_t *p_mutex) VLC_THREAD_ASSERT ("locking mutex"); #elif defined( WIN32 ) - if (p_mutex->recursive) - { - DWORD self = GetCurrentThreadId (); - - if ((DWORD)InterlockedCompareExchange (&p_mutex->owner, self, - self) == self) - { /* We already locked this recursive mutex */ - p_mutex->recursion++; - return; - } - - /* We need to lock this recursive mutex */ - EnterCriticalSection (&p_mutex->mutex); - self = InterlockedExchange (&p_mutex->owner, self); - assert (self == 0); /* no previous owner */ - return; + if (InterlockedCompareExchange (&p_mutex->initialized, 0, 0) == 0) + { /* ^^ We could also lock super_mutex all the time... sluggish */ + assert (p_mutex != &super_mutex); /* this one cannot be static */ + + vlc_mutex_lock (&super_mutex); + if (InterlockedCompareExchange (&p_mutex->initialized, 0, 0) == 0) + vlc_mutex_init (p_mutex); + /* FIXME: destroy the mutex some time... */ + vlc_mutex_unlock (&super_mutex); } - /* Non-recursive mutex */ + assert (InterlockedExchange (&p_mutex->initialized, 1) == 1); EnterCriticalSection (&p_mutex->mutex); #endif } +/** + * Acquires a mutex if and only if it is not currently held by another thread. + * This function never sleeps and can be used in delay-critical code paths. + * This function is not a cancellation-point. + * + * Beware: If this function fails, then the mutex is held... by another + * thread. The calling thread must deal with the error appropriately. That + * typically implies postponing the operations that would have required the + * mutex. If the thread cannot defer those operations, then it must use + * vlc_mutex_lock(). If in doubt, use vlc_mutex_lock() instead. + * + * @param p_mutex mutex initialized with vlc_mutex_init() or + * vlc_mutex_init_recursive() + * @return 0 if the mutex could be acquired, an error code otherwise. + */ +int vlc_mutex_trylock (vlc_mutex_t *p_mutex) +{ +#if defined(LIBVLC_USE_PTHREAD) + int val = pthread_mutex_trylock( p_mutex ); + + if (val != EBUSY) + VLC_THREAD_ASSERT ("locking mutex"); + return val; + +#elif defined( WIN32 ) + if (InterlockedCompareExchange (&p_mutex->initialized, 0, 0) == 0) + { /* ^^ We could also lock super_mutex all the time... sluggish */ + assert (p_mutex != &super_mutex); /* this one cannot be static */ + + vlc_mutex_lock (&super_mutex); + if (InterlockedCompareExchange (&p_mutex->initialized, 0, 0) == 0) + vlc_mutex_init (p_mutex); + /* FIXME: destroy the mutex some time... */ + vlc_mutex_unlock (&super_mutex); + } + assert (InterlockedExchange (&p_mutex->initialized, 1) == 1); + return TryEnterCriticalSection (&p_mutex->mutex) ? 0 : EBUSY; + +#endif +} /** * Releases a mutex (or crashes if the mutex is not locked by the caller). @@ -370,18 +436,7 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex) VLC_THREAD_ASSERT ("unlocking mutex"); #elif defined( WIN32 ) - if (p_mutex->recursive) - { - if (p_mutex->recursion != 0) - { - p_mutex->recursion--; - return; /* We still own this mutex */ - } - - /* We release the mutex */ - InterlockedExchange (&p_mutex->owner, 0); - /* fall through */ - } + assert (InterlockedExchange (&p_mutex->initialized, 1) == 1); LeaveCriticalSection (&p_mutex->mutex); #endif @@ -474,11 +529,6 @@ void vlc_cond_broadcast (vlc_cond_t *p_condvar) #endif } -#ifdef UNDER_CE -# warning FIXME -# define WaitForMultipleObjectsEx(a,b,c) WaitForMultipleObjects(a,b) -#endif - /** * Waits for a condition variable. The calling thread will be suspended until * another thread calls vlc_cond_signal() or vlc_cond_broadcast() on the same @@ -522,7 +572,6 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) #elif defined( WIN32 ) DWORD result; - assert (!p_mutex->recursive); do { vlc_testcancel (); @@ -552,6 +601,16 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, mtime_t deadline) { #if defined(LIBVLC_USE_PTHREAD) +#ifdef __APPLE__ + /* mdate() is mac_absolute_time on osx, which we must convert to do + * the same base than gettimeofday() on which pthread_cond_timedwait + * counts on. */ + mtime_t oldbase = mdate(); + struct timeval tv; + gettimeofday(&tv, NULL); + mtime_t newbase = (mtime_t)tv.tv_sec * 1000000 + (mtime_t) tv.tv_usec; + deadline = deadline - oldbase + newbase; +#endif lldiv_t d = lldiv( deadline, CLOCK_FREQ ); struct timespec ts = { d.quot, d.rem * (1000000000 / CLOCK_FREQ) }; @@ -563,7 +622,6 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, #elif defined( WIN32 ) DWORD result; - assert (!p_mutex->recursive); do { vlc_testcancel (); @@ -595,8 +653,6 @@ int vlc_threadvar_create( vlc_threadvar_t *p_tls, void (*destr) (void *) ) #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(); @@ -611,7 +667,6 @@ 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 @@ -619,14 +674,51 @@ void vlc_threadvar_delete (vlc_threadvar_t *p_tls) #endif } +/** + * Sets a thread-local variable. + * @param key thread-local variable key (created with vlc_threadvar_create()) + * @param value new value for the variable for the calling thread + * @return 0 on success, a system error code otherwise. + */ +int vlc_threadvar_set (vlc_threadvar_t key, void *value) +{ +#if defined(LIBVLC_USE_PTHREAD) + return pthread_setspecific (key, value); +#elif defined( UNDER_CE ) || defined( WIN32 ) + return TlsSetValue (key, p_value) ? ENOMEM : 0; +#else +# error Unimplemented! +#endif +} + +/** + * Gets the value of a thread-local variable for the calling thread. + * This function cannot fail. + * @return the value associated with the given variable for the calling + * or NULL if there is no value. + */ +void *vlc_threadvar_get (vlc_threadvar_t key) +{ +#if defined(LIBVLC_USE_PTHREAD) + return pthread_getspecific (key); +#elif defined( UNDER_CE ) || defined( WIN32 ) + return TlsGetValue (key); +#else +# error Unimplemented! +#endif +} + #if defined (LIBVLC_USE_PTHREAD) #elif defined (WIN32) static unsigned __stdcall vlc_entry (void *data) { vlc_cancel_t cancel_data = VLC_CANCEL_INIT; vlc_thread_t self = data; +#ifdef UNDER_CE + cancel_data.cancel_event = self->cancel_event; +#endif - vlc_threadvar_set (&cancel_key, &cancel_data); + vlc_threadvar_set (cancel_key, &cancel_data); self->data = self->entry (self->data); return 0; } @@ -722,7 +814,13 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, th->data = data; th->entry = entry; #if defined( UNDER_CE ) - hThread = CreateThread (NULL, 0, vlc_entry, th, CREATE_SUSPENDED, NULL); + th->cancel_event = CreateEvent (NULL, FALSE, FALSE, NULL); + if (th->cancel_event == NULL) + { + free(th); + return errno; + } + hThread = CreateThread (NULL, 128*1024, vlc_entry, th, CREATE_SUSPENDED, NULL); #else hThread = (HANDLE)(uintptr_t) _beginthreadex (NULL, 0, vlc_entry, th, CREATE_SUSPENDED, NULL); @@ -730,6 +828,7 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, if (hThread) { +#ifndef UNDER_CE /* Thread closes the handle when exiting, duplicate it here * to be on the safe side when joining. */ if (!DuplicateHandle (GetCurrentProcess (), hThread, @@ -740,6 +839,9 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, free (th); return ENOMEM; } +#else + th->handle = hThread; +#endif ResumeThread (hThread); if (priority) @@ -778,6 +880,8 @@ void vlc_cancel (vlc_thread_t thread_id) { #if defined (LIBVLC_USE_PTHREAD_CANCEL) pthread_cancel (thread_id); +#elif defined (UNDER_CE) + SetEvent (thread_id->cancel_event); #elif defined (WIN32) QueueUserAPC (vlc_cancel_self, thread_id->handle, 0); #else @@ -798,8 +902,7 @@ void vlc_join (vlc_thread_t handle, void **result) { #if defined( LIBVLC_USE_PTHREAD ) int val = pthread_join (handle, result); - if (val) - vlc_thread_fatal ("joining thread", val, __func__, __FILE__, __LINE__); + VLC_THREAD_ASSERT ("joining thread"); #elif defined( UNDER_CE ) || defined( WIN32 ) do @@ -810,11 +913,111 @@ void vlc_join (vlc_thread_t handle, void **result) CloseHandle (handle->handle); if (result) *result = handle->data; +#if defined( UNDER_CE ) + CloseHandle (handle->cancel_event); +#endif free (handle); #endif } +/** + * Save the current cancellation state (enabled or disabled), then disable + * cancellation for the calling thread. + * This function must be called before entering a piece of code that is not + * cancellation-safe, unless it can be proven that the calling thread will not + * be cancelled. + * @return Previous cancellation state (opaque value for vlc_restorecancel()). + */ +int vlc_savecancel (void) +{ + int state; + +#if defined (LIBVLC_USE_PTHREAD_CANCEL) + int val = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state); + VLC_THREAD_ASSERT ("saving cancellation"); + +#else + vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key); + if (nfo == NULL) + return false; /* Main thread - cannot be cancelled anyway */ + + state = nfo->killable; + nfo->killable = false; + +#endif + return state; +} + +/** + * Restore the cancellation state for the calling thread. + * @param state previous state as returned by vlc_savecancel(). + * @return Nothing, always succeeds. + */ +void vlc_restorecancel (int state) +{ +#if defined (LIBVLC_USE_PTHREAD_CANCEL) +# ifndef NDEBUG + int oldstate, val; + + val = pthread_setcancelstate (state, &oldstate); + /* This should fail if an invalid value for given for state */ + VLC_THREAD_ASSERT ("restoring cancellation"); + + if (oldstate != PTHREAD_CANCEL_DISABLE) + vlc_thread_fatal ("restoring cancellation while not disabled", EINVAL, + __func__, __FILE__, __LINE__); +# else + pthread_setcancelstate (state, NULL); +# endif + +#else + vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key); + assert (state == false || state == true); + + if (nfo == NULL) + return; /* Main thread - cannot be cancelled anyway */ + + assert (!nfo->killable); + nfo->killable = state != 0; + +#endif +} + +/** + * Issues an explicit deferred cancellation point. + * This has no effect if thread cancellation is disabled. + * This can be called when there is a rather slow non-sleeping operation. + * This is also used to force a cancellation point in a function that would + * otherwise "not always" be a one (block_FifoGet() is an example). + */ +void vlc_testcancel (void) +{ +#if defined (LIBVLC_USE_PTHREAD_CANCEL) + pthread_testcancel (); + +#else + vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key); + if (nfo == NULL) + return; /* Main thread - cannot be cancelled anyway */ + + if (nfo->killable && nfo->killed) + { + for (vlc_cleanup_t *p = nfo->cleaners; p != NULL; p = p->next) + p->proc (p->data); +# if defined (LIBVLC_USE_PTHREAD) + pthread_exit (PTHREAD_CANCELLED); +# elif defined (UNDER_CE) + ExitThread(0); +# elif defined (WIN32) + _endthread (); +# else +# error Not implemented! +# endif + } +#endif +} + struct vlc_thread_boot { @@ -835,15 +1038,16 @@ static void *thread_entry (void *data) return NULL; } +#undef vlc_thread_create /***************************************************************************** - * vlc_thread_create: create a thread, inner version + * vlc_thread_create: create a thread ***************************************************************************** * 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 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 ) { int i_ret; vlc_object_internals_t *p_priv = vlc_internals( p_this ); @@ -854,8 +1058,6 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line 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 ); @@ -870,28 +1072,19 @@ int __vlc_thread_create( vlc_object_t *p_this, const char * psz_file, int i_line } #endif + p_priv->b_thread = true; i_ret = vlc_clone( &p_priv->thread_id, thread_entry, boot, i_priority ); 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 ); - } + msg_Dbg( p_this, "thread (%s) created at priority %d (%s:%d)", + psz_name, i_priority, psz_file, i_line ); else { + p_priv->b_thread = false; 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; } @@ -970,6 +1163,7 @@ void __vlc_thread_join( vlc_object_t *p_this ) FILETIME create_ft, exit_ft, kernel_ft, user_ft; int64_t real_time, kernel_time, user_time; +#ifndef UNDER_CE if( ! DuplicateHandle(GetCurrentProcess(), p_priv->thread_id->handle, GetCurrentProcess(), @@ -981,6 +1175,9 @@ void __vlc_thread_join( vlc_object_t *p_this ) p_priv->b_thread = false; return; /* We have a problem! */ } +#else + hThread = p_priv->thread_id->handle; +#endif vlc_join( p_priv->thread_id, NULL ); @@ -1036,7 +1233,7 @@ void vlc_control_cancel (int cmd, ...) #else va_list ap; - vlc_cancel_t *nfo = vlc_threadvar_get (&cancel_key); + vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key); if (nfo == NULL) { #ifdef WIN32 @@ -1047,46 +1244,13 @@ void vlc_control_cancel (int cmd, ...) if (nfo == NULL) return; /* Uho! Expect problems! */ *nfo = VLC_CANCEL_INIT; - vlc_threadvar_set (&cancel_key, nfo); + vlc_threadvar_set (cancel_key, nfo); #endif } va_start (ap, cmd); switch (cmd) { - case VLC_SAVE_CANCEL: - { - int *p_state = va_arg (ap, int *); - *p_state = nfo->killable; - nfo->killable = false; - break; - } - - case VLC_RESTORE_CANCEL: - { - int state = va_arg (ap, int); - nfo->killable = state != 0; - break; - } - - case VLC_TEST_CANCEL: - if (nfo->killable && nfo->killed) - { - for (vlc_cleanup_t *p = nfo->cleaners; p != NULL; p = p->next) - p->proc (p->data); -#ifndef WIN32 - free (nfo); -#endif -#if defined (LIBVLC_USE_PTHREAD) - pthread_exit (PTHREAD_CANCELLED); -#elif defined (WIN32) - _endthread (); -#else -# error Not implemented! -#endif - } - break; - case VLC_DO_CANCEL: nfo->killed = true; break;