qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] coreaudio: Lock only the buffer


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH] coreaudio: Lock only the buffer
Date: Tue, 22 Jun 2021 08:57:47 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.1

On 6/22/21 3:50 AM, Akihiko Odaki wrote:
> On macOS 11.3.1, Core Audio calls AudioDeviceIOProc after calling an
> internal function named HALB_Mutex::Lock(), which locks a mutex in
> HALB_IOThread::Entry(void*). HALB_Mutex::Lock() is also called in
> AudioObjectGetPropertyData, which is called by coreaudio driver.
> Therefore, a deadlock will occur if coreaudio driver calls
> AudioObjectGetPropertyData while holding a lock for a mutex and tries
> to lock the same mutex in AudioDeviceIOProc.
> 
> audioDeviceIOProc, which implements AudioDeviceIOProc in coreaudio
> driver, requires an exclusive access for the device configuration and
> the buffer. Fortunately, a mutex is necessary only for the buffer in
> audioDeviceIOProc because a change for the device configuration occurs
> only before setting up AudioDeviceIOProc or after stopping the playback
> with AudioDeviceStop.
> 
> With this change, the mutex owned by the driver will only be used for
> the buffer, and the device configuration change will be protected with
> the implicit iothread mutex.
> 
> Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
> ---
>  audio/coreaudio.c | 59 +++++++++++------------------------------------
>  1 file changed, 13 insertions(+), 46 deletions(-)
> 
> diff --git a/audio/coreaudio.c b/audio/coreaudio.c
> index 578ec9b8b2e..c8d9f01d275 100644
> --- a/audio/coreaudio.c
> +++ b/audio/coreaudio.c
> @@ -26,6 +26,7 @@
>  #include <CoreAudio/CoreAudio.h>
>  #include <pthread.h>            /* pthread_X */
>  
> +#include "qemu/main-loop.h"
>  #include "qemu/module.h"
>  #include "audio.h"
>  

Suggestions to complete your patch, document init_out_device()
and update_device_playback_state() are called with iothread
lock taken:

@@ -456,6 +456,7 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
     return 0;
 }

+/* Called with iothread lock taken. */
 static void fini_out_device(coreaudioVoiceOut *core)
 {
     OSStatus status;
@@ -486,6 +487,7 @@ static void fini_out_device(coreaudioVoiceOut *core)
     core->outputDeviceID = kAudioDeviceUnknown;
 }

+/* Called with iothread lock taken. */
 static void update_device_playback_state(coreaudioVoiceOut *core)
 {
     OSStatus status;

> @@ -551,9 +552,7 @@ static OSStatus handle_voice_change(
>      OSStatus status;
>      coreaudioVoiceOut *core = in_client_data;
>  
> -    if (coreaudio_lock(core, __func__)) {
> -        abort();
> -    }
> +    qemu_mutex_lock_iothread();
>  
>      if (core->outputDeviceID) {
>          fini_out_device(core);
> @@ -564,7 +563,7 @@ static OSStatus handle_voice_change(
>          update_device_playback_state(core);
>      }
>  
> -    coreaudio_unlock (core, __func__);
> +    qemu_mutex_unlock_iothread();
>      return status;
>  }
>  
> @@ -582,11 +581,7 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct 
> audsettings *as,
>      err = pthread_mutex_init(&core->mutex, NULL);
>      if (err) {
>          dolog("Could not create mutex\nReason: %s\n", strerror (err));
> -        goto mutex_error;
> -    }
> -
> -    if (coreaudio_lock(core, __func__)) {
> -        goto lock_error;
> +        return -1;
>      }
>  
>      obt_as = *as;
> @@ -606,37 +601,21 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct 
> audsettings *as,
>      if (status != kAudioHardwareNoError) {
>          coreaudio_playback_logerr (status,
>                                     "Could not listen to voice property 
> change\n");
> -        goto listener_error;
> +        return -1;
>      }
>  
>      if (init_out_device(core)) {
> -        goto device_error;
> +        status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
> +                                                   &voice_addr,
> +                                                   handle_voice_change,
> +                                                   core);
> +        if (status != kAudioHardwareNoError) {
> +            coreaudio_playback_logerr(status,
> +                                      "Could not remove voice property 
> change listener\n");
> +        }
>      }
>  
> -    coreaudio_unlock(core, __func__);
>      return 0;
> -
> -device_error:
> -    status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
> -                                               &voice_addr,
> -                                               handle_voice_change,
> -                                               core);
> -    if (status != kAudioHardwareNoError) {
> -        coreaudio_playback_logerr(status,
> -                                  "Could not remove voice property change 
> listener\n");
> -    }
> -
> -listener_error:
> -    coreaudio_unlock(core, __func__);
> -
> -lock_error:
> -    err = pthread_mutex_destroy(&core->mutex);
> -    if (err) {
> -        dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
> -    }
> -
> -mutex_error:
> -    return -1;
>  }
>  
>  static void coreaudio_fini_out (HWVoiceOut *hw)
> @@ -645,10 +624,6 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
>      int err;
>      coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
>  
> -    if (coreaudio_lock(core, __func__)) {
> -        abort();
> -    }
> -
>      status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
>                                                 &voice_addr,
>                                                 handle_voice_change,
> @@ -659,8 +634,6 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
>  
>      fini_out_device(core);
>  
> -    coreaudio_unlock(core, __func__);
> -
>      /* destroy mutex */
>      err = pthread_mutex_destroy(&core->mutex);
>      if (err) {
> @@ -672,14 +645,8 @@ static void coreaudio_enable_out(HWVoiceOut *hw, bool 
> enable)
>  {
>      coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
>  
> -    if (coreaudio_lock(core, __func__)) {
> -        abort();
> -    }
> -
>      core->enabled = enable;
>      update_device_playback_state(core);
> -
> -    coreaudio_unlock(core, __func__);
>  }
>  
>  static void *coreaudio_audio_init(Audiodev *dev)
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]