Commit d9b51113 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Remove the requirement for vlc object to be locked when invoking waitpipe.

This is so that the net_* functions can use it without making pushing locking assumption on their caller.
parent 8f92249a
...@@ -109,7 +109,9 @@ struct vlc_object_internals_t ...@@ -109,7 +109,9 @@ struct vlc_object_internals_t
vlc_bool_t b_thread; vlc_bool_t b_thread;
/* Objects thread synchronization */ /* Objects thread synchronization */
vlc_bool_t b_signaled;
int pipes[2]; int pipes[2];
vlc_spinlock_t spin;
/* Objects management */ /* Objects management */
unsigned i_refcount; unsigned i_refcount;
......
...@@ -195,6 +195,7 @@ vlc_object_t *vlc_custom_create( vlc_object_t *p_this, size_t i_size, ...@@ -195,6 +195,7 @@ vlc_object_t *vlc_custom_create( vlc_object_t *p_this, size_t i_size,
vlc_mutex_init( p_new, &p_new->object_lock ); vlc_mutex_init( p_new, &p_new->object_lock );
vlc_cond_init( p_new, &p_new->object_wait ); vlc_cond_init( p_new, &p_new->object_wait );
vlc_mutex_init( p_new, &p_priv->var_lock ); vlc_mutex_init( p_new, &p_priv->var_lock );
vlc_spin_init( &p_priv->spin );
p_priv->pipes[0] = p_priv->pipes[1] = -1; p_priv->pipes[0] = p_priv->pipes[1] = -1;
if( i_type == VLC_OBJECT_GLOBAL ) if( i_type == VLC_OBJECT_GLOBAL )
...@@ -443,6 +444,7 @@ void __vlc_object_destroy( vlc_object_t *p_this ) ...@@ -443,6 +444,7 @@ void __vlc_object_destroy( vlc_object_t *p_this )
vlc_mutex_destroy( &p_this->object_lock ); vlc_mutex_destroy( &p_this->object_lock );
vlc_cond_destroy( &p_this->object_wait ); vlc_cond_destroy( &p_this->object_wait );
vlc_spin_destroy( &p_priv->spin );
if( p_priv->pipes[0] != -1 ) if( p_priv->pipes[0] != -1 )
close( p_priv->pipes[0] ); close( p_priv->pipes[0] );
if( p_priv->pipes[1] != -1 ) if( p_priv->pipes[1] != -1 )
...@@ -532,24 +534,48 @@ error: ...@@ -532,24 +534,48 @@ error:
* Assuming the pipe is readable, vlc_object_wait() will not block. * Assuming the pipe is readable, vlc_object_wait() will not block.
* Also note that, as with vlc_object_wait(), there may be spurious wakeups. * Also note that, as with vlc_object_wait(), there may be spurious wakeups.
* *
* @param obj object that would be signaled (object lock MUST hold) * @param obj object that would be signaled
* @return a readable pipe descriptor, or -1 on error. * @return a readable pipe descriptor, or -1 on error.
*/ */
int __vlc_object_waitpipe( vlc_object_t *obj ) int __vlc_object_waitpipe( vlc_object_t *obj )
{ {
int *pipes = obj->p_internals->pipes; int pfd[2] = { -1, -1 };
vlc_assert_locked( &obj->object_lock ); struct vlc_object_internals_t *internals = obj->p_internals;
vlc_bool_t race = VLC_FALSE, signaled = VLC_FALSE;
if( pipes[1] == -1 ) vlc_spin_lock (&internals->spin);
if (internals->pipes[0] == -1)
{ {
/* This can only ever happen if someone killed us without locking */ /* This can only ever happen if someone killed us without locking: */
assert( pipes[0] == -1 ); assert (internals->pipes[1] == -1);
vlc_spin_unlock (&internals->spin);
if( pipe( pipes ) ) if (pipe (pfd))
return -1; return -1;
vlc_spin_lock (&internals->spin);
signaled = internals->b_signaled;
if ((!signaled) && (internals->pipes[0] == -1))
{
internals->pipes[0] = pfd[0];
internals->pipes[1] = pfd[1];
}
} }
vlc_spin_unlock (&internals->spin);
return pipes[0]; if (race || signaled)
{
close (pfd[0]);
close (pfd[1]);
if (signaled)
{ /* vlc_object_signal() was already invoked! */
errno = EINTR;
return -1;
}
}
return internals->pipes[0];
} }
...@@ -562,16 +588,19 @@ int __vlc_object_waitpipe( vlc_object_t *obj ) ...@@ -562,16 +588,19 @@ int __vlc_object_waitpipe( vlc_object_t *obj )
*/ */
vlc_bool_t __vlc_object_wait( vlc_object_t *obj ) vlc_bool_t __vlc_object_wait( vlc_object_t *obj )
{ {
int fd;
vlc_assert_locked( &obj->object_lock ); vlc_assert_locked( &obj->object_lock );
int fd = obj->p_internals->pipes[0]; fd = obj->p_internals->pipes[0];
if( fd != -1 ) if (fd != -1)
{ {
while (read (fd, &(char){ 0 }, 1 < 0)); while (read (fd, &(char){ 0 }, 1) < 0);
return obj->b_die; return obj->b_die;
} }
vlc_cond_wait( &obj->object_wait, &obj->object_lock ); vlc_cond_wait( &obj->object_wait, &obj->object_lock );
obj->p_internals->b_signaled = VLC_FALSE;
return obj->b_die; return obj->b_die;
} }
...@@ -633,9 +662,16 @@ vlc_bool_t __vlc_object_alive( vlc_object_t *obj ) ...@@ -633,9 +662,16 @@ vlc_bool_t __vlc_object_alive( vlc_object_t *obj )
*/ */
void __vlc_object_signal_unlocked( vlc_object_t *obj ) void __vlc_object_signal_unlocked( vlc_object_t *obj )
{ {
vlc_assert_locked( &obj->object_lock ); struct vlc_object_internals_t *internals = obj->p_internals;
int fd;
vlc_assert_locked (&obj->object_lock);
vlc_spin_lock (&internals->spin);
fd = internals->pipes[1];
internals->b_signaled = VLC_TRUE;
vlc_spin_unlock (&internals->spin);
int fd = obj->p_internals->pipes[1];
if( fd != -1 ) if( fd != -1 )
while( write( fd, &(char){ 0 }, 1 ) < 0 ); while( write( fd, &(char){ 0 }, 1 ) < 0 );
......
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