Commit 72218fb9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont
Browse files

De-inline vlc_(test|save|restore)cancel, add some assertions

parent b7320893
......@@ -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)
/**
......
......@@ -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
......
......@@ -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;
......
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