From 72218fb9b9ba6c9f5a36bd3d3cfb1557a5491452 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 25 Jan 2009 20:30:48 +0200 Subject: [PATCH] De-inline vlc_(test|save|restore)cancel, add some assertions --- include/vlc_threads.h | 50 +--------------- src/libvlccore.sym | 3 + src/misc/threads.c | 133 ++++++++++++++++++++++++++++++------------ 3 files changed, 102 insertions(+), 84 deletions(-) diff --git a/include/vlc_threads.h b/include/vlc_threads.h index 66f0f67069..c9908321cf 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -163,59 +163,15 @@ VLC_EXPORT (void, vlc_control_cancel, (int cmd, ...)); #ifndef LIBVLC_USE_PTHREAD_CANCEL enum { - VLC_SAVE_CANCEL, - VLC_RESTORE_CANCEL, - VLC_TEST_CANCEL, VLC_DO_CANCEL, VLC_CLEANUP_PUSH, VLC_CLEANUP_POP, }; #endif -/** - * Save the cancellation state and disable cancellation for the calling thread. - * This function must be called before entering a piece of code that is not - * cancellation-safe. - * @return Previous cancellation state (opaque value). - */ -static inline int vlc_savecancel (void) -{ - int state; -#if defined (LIBVLC_USE_PTHREAD_CANCEL) - (void) pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state); -#else - vlc_control_cancel (VLC_SAVE_CANCEL, &state); -#endif - return state; -} - -/** - * Restore the cancellation state for the calling thread. - * @param state previous state as returned by vlc_savecancel(). - * @return Nothing, always succeeds. - */ -static inline void vlc_restorecancel (int state) -{ -#if defined (LIBVLC_USE_PTHREAD_CANCEL) - (void) pthread_setcancelstate (state, NULL); -#else - vlc_control_cancel (VLC_RESTORE_CANCEL, state); -#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. - */ -static inline void vlc_testcancel (void) -{ -#if defined (LIBVLC_USE_PTHREAD_CANCEL) - pthread_testcancel (); -#else - vlc_control_cancel (VLC_TEST_CANCEL); -#endif -} +VLC_EXPORT( int, vlc_savecancel, (void) ); +VLC_EXPORT( void, vlc_restorecancel, (int state) ); +VLC_EXPORT( void, vlc_testcancel, (void) ); #if defined (LIBVLC_USE_PTHREAD_CANCEL) /** diff --git a/src/libvlccore.sym b/src/libvlccore.sym index f5896628f0..4933f76b93 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -496,6 +496,8 @@ vlc_poll vlc_rand_bytes vlc_recvmsg vlc_release +vlc_restorecancel +vlc_savecancel vlc_sd_Create vlc_sd_GetNames vlc_sdp_Start @@ -506,6 +508,7 @@ vlc_strcasestr vlc_strlcpy vlc_strtoll vlc_submodule_create +vlc_testcancel vlc_thread_create __vlc_thread_join __vlc_thread_set_priority diff --git a/src/misc/threads.c b/src/misc/threads.c index e35d6b5fab..f9fb8c54c2 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -805,8 +805,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 @@ -825,6 +824,101 @@ void vlc_join (vlc_thread_t handle, void **result) #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; /* 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 */ + 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 { @@ -1058,41 +1152,6 @@ void vlc_control_cancel (int cmd, ...) 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 (UNDER_CE) - ExitThread(0); -#elif defined (WIN32) - _endthread (); -#else -# error Not implemented! -#endif - } - break; - case VLC_DO_CANCEL: nfo->killed = true; break; -- 2.39.2