From: RĂ©mi Denis-Courmont Date: Sun, 29 Nov 2009 10:38:39 +0000 (+0200) Subject: Debug audio output lock ordering X-Git-Tag: 1.1.0-ff~2331 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=7a87d5768beaecfc8132a875d08b53ec5b780bee;p=vlc Debug audio output lock ordering --- diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h index a2acd1809e..6ef8da46cd 100644 --- a/src/audio_output/aout_internal.h +++ b/src/audio_output/aout_internal.h @@ -164,51 +164,83 @@ int aout_DecGetResetLost( aout_instance_t *, aout_input_t * ); void aout_DecChangePause( aout_instance_t *, aout_input_t *, bool b_paused, mtime_t i_date ); void aout_DecFlush( aout_instance_t *, aout_input_t * ); -/* Helpers */ +/* Audio output locking */ + +#if !defined (NDEBUG) \ + && defined __linux__ && (defined (__i386__) || defined (__x86_64__)) +# define AOUT_DEBUG 1 +#endif + +#ifdef AOUT_DEBUG +enum +{ + MIXER_LOCK=1, + INPUT_LOCK=2, + INPUT_FIFO_LOCK=4, + OUTPUT_FIFO_LOCK=8, +}; + +void aout_lock (unsigned); +void aout_unlock (unsigned); + +#else +# define aout_lock( i ) (void)0 +# define aout_unlock( i ) (void)0 +#endif static inline void aout_lock_mixer( aout_instance_t *p_aout ) { + aout_lock( MIXER_LOCK ); vlc_mutex_lock( &p_aout->mixer_lock ); } static inline void aout_unlock_mixer( aout_instance_t *p_aout ) { + aout_unlock( MIXER_LOCK ); vlc_mutex_unlock( &p_aout->mixer_lock ); } static inline void aout_lock_input_fifos( aout_instance_t *p_aout ) { + aout_lock( INPUT_FIFO_LOCK ); vlc_mutex_lock( &p_aout->input_fifos_lock ); } static inline void aout_unlock_input_fifos( aout_instance_t *p_aout ) { + aout_unlock( INPUT_FIFO_LOCK ); vlc_mutex_unlock( &p_aout->input_fifos_lock ); } static inline void aout_lock_output_fifo( aout_instance_t *p_aout ) { + aout_lock( OUTPUT_FIFO_LOCK ); vlc_mutex_lock( &p_aout->output_fifo_lock ); } static inline void aout_unlock_output_fifo( aout_instance_t *p_aout ) { + aout_unlock( OUTPUT_FIFO_LOCK ); vlc_mutex_unlock( &p_aout->output_fifo_lock ); } static inline void aout_lock_input( aout_instance_t *p_aout, aout_input_t * p_input ) { (void)p_aout; + aout_lock( INPUT_LOCK ); vlc_mutex_lock( &p_input->lock ); } static inline void aout_unlock_input( aout_instance_t *p_aout, aout_input_t * p_input ) { (void)p_aout; + aout_unlock( INPUT_LOCK ); vlc_mutex_unlock( &p_input->lock ); } +/* Helpers */ + /** * This function will safely mark aout input to be restarted as soon as * possible to take configuration changes into account */ diff --git a/src/audio_output/common.c b/src/audio_output/common.c index 62b11e8cc8..0c9cda76bc 100644 --- a/src/audio_output/common.c +++ b/src/audio_output/common.c @@ -114,6 +114,54 @@ static void aout_Destructor( vlc_object_t * p_this ) vlc_mutex_destroy( &p_aout->output_fifo_lock ); } +/* Lock ordering rules: + * + * Mixer Input IFIFO OFIFO (< Inner lock) + * Mixer No! N/A Yes Yes + * Input N/A No! Yes N/A + * In FIFOs No! No! No! No! + * Out FIFOs No! N/A Yes No! + * (^ Outer lock) + */ +#ifdef AOUT_DEBUG +/* Lock debugging */ +static __thread unsigned aout_locks = 0; + +void aout_lock (unsigned i) +{ + unsigned allowed; + switch (i) + { + case MIXER_LOCK: + allowed = 0; + break; + case INPUT_LOCK: + allowed = 0; + break; + case OUTPUT_FIFO_LOCK: + allowed = MIXER_LOCK; + break; + case INPUT_FIFO_LOCK: + allowed = MIXER_LOCK|INPUT_LOCK|OUTPUT_FIFO_LOCK; + break; + } + + if (aout_locks & ~allowed) + { + fprintf (stderr, "Illegal audio lock transition (%x -> %x)\n", + aout_locks, aout_locks|i); + vlc_backtrace (); + //abort (); + } + aout_locks |= i; +} + +void aout_unlock (unsigned i) +{ + assert (aout_locks & i); + aout_locks &= ~i; +} +#endif /* * Formats management (internal and external)