[PATCH 2/5] winepulse: Use a critical section for PE-side locking.

Andrew Eikum aeikum at codeweavers.com
Thu May 27 14:32:28 CDT 2021


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Wed, May 26, 2021 at 04:18:43PM +0200, Jacek Caban wrote:
> Signed-off-by: Jacek Caban <jacek at codeweavers.com>
> ---
>  dlls/winepulse.drv/mmdevdrv.c | 63 ++++++++++++++++++++---------------
>  dlls/winepulse.drv/pulse.c    | 33 ++++++++++++------
>  dlls/winepulse.drv/unixlib.h  |  2 --
>  3 files changed, 58 insertions(+), 40 deletions(-)
> 
> 

> diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
> index 1a39db0f72b..0350cb52e8c 100644
> --- a/dlls/winepulse.drv/mmdevdrv.c
> +++ b/dlls/winepulse.drv/mmdevdrv.c
> @@ -68,6 +68,15 @@ static GUID pulse_render_guid =
>  static GUID pulse_capture_guid =
>  { 0x25da76d0, 0x033c, 0x4235, { 0x90, 0x02, 0x19, 0xf4, 0x88, 0x94, 0xac, 0x6f } };
>  
> +static CRITICAL_SECTION session_cs;
> +static CRITICAL_SECTION_DEBUG session_cs_debug = {
> +    0, 0, &session_cs,
> +    { &session_cs_debug.ProcessLocksList,
> +      &session_cs_debug.ProcessLocksList },
> +    0, 0, { (DWORD_PTR)(__FILE__ ": session_cs") }
> +};
> +static CRITICAL_SECTION session_cs = { &session_cs_debug, -1, 0, 0, 0, 0 };
> +
>  BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
>  {
>      if (reason == DLL_PROCESS_ATTACH) {
> @@ -367,9 +376,9 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
>          if (This->pulse_stream) {
>              pulse->release_stream(This->pulse_stream, This->timer);
>              This->pulse_stream = NULL;
> -            pulse->lock();
> +            EnterCriticalSection(&session_cs);
>              list_remove(&This->entry);
> -            pulse->unlock();
> +            LeaveCriticalSection(&session_cs);
>          }
>          IUnknown_Release(This->marshal);
>          IMMDevice_Release(This->parent);
> @@ -549,10 +558,10 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>          return E_INVALIDARG;
>      }
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>  
>      if (This->pulse_stream) {
> -        pulse->unlock();
> +        LeaveCriticalSection(&session_cs);
>          return AUDCLNT_E_ALREADY_INITIALIZED;
>      }
>  
> @@ -562,7 +571,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>          if (!(pulse_thread = CreateThread(NULL, 0, pulse_mainloop_thread, event, 0, NULL)))
>          {
>              ERR("Failed to create mainloop thread.\n");
> -            pulse->unlock();
> +            LeaveCriticalSection(&session_cs);
>              CloseHandle(event);
>              return E_FAIL;
>          }
> @@ -577,14 +586,14 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>      free(name);
>      if (FAILED(hr))
>      {
> -        pulse->unlock();
> +        LeaveCriticalSection(&session_cs);
>          return hr;
>      }
>  
>      if (!(This->vol = malloc(channel_count * sizeof(*This->vol))))
>      {
>          pulse->release_stream(stream, NULL);
> -        pulse->unlock();
> +        LeaveCriticalSection(&session_cs);
>          return E_OUTOFMEMORY;
>      }
>      for (i = 0; i < channel_count; i++)
> @@ -595,7 +604,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>      {
>          free(This->vol);
>          This->vol = NULL;
> -        pulse->unlock();
> +        LeaveCriticalSection(&session_cs);
>          pulse->release_stream(stream, NULL);
>          return E_OUTOFMEMORY;
>      }
> @@ -605,7 +614,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
>      list_add_tail(&This->session->clients, &This->entry);
>      set_stream_volumes(This);
>  
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> @@ -1445,12 +1454,12 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
>      if (count != This->channel_count)
>          return E_INVALIDARG;
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      for (i = 0; i < count; ++i)
>          This->vol[i] = levels[i];
>  
>      set_stream_volumes(This);
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> @@ -1470,10 +1479,10 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
>      if (count != This->channel_count)
>          return E_INVALIDARG;
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      for (i = 0; i < count; ++i)
>          levels[i] = This->vol[i];
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> @@ -1492,10 +1501,10 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
>      if (index >= This->channel_count)
>          return E_INVALIDARG;
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      This->vol[index] = level;
>      set_stream_volumes(This);
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> @@ -1514,9 +1523,9 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
>      if (index >= This->channel_count)
>          return E_INVALIDARG;
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      *level = This->vol[index];
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> @@ -1614,7 +1623,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
>      if (!state)
>          return NULL_PTR_ERR;
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      if (list_empty(&This->session->clients)) {
>          *state = AudioSessionStateExpired;
>          goto out;
> @@ -1628,7 +1637,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
>      *state = AudioSessionStateInactive;
>  
>  out:
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> @@ -2004,11 +2013,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
>  
>      TRACE("PulseAudio does not support session volume control\n");
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      session->master_vol = level;
>      LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
>          set_stream_volumes(client);
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>  
>      return S_OK;
>  }
> @@ -2041,11 +2050,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
>      if (context)
>          FIXME("Notifications not supported yet\n");
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      session->mute = mute;
>      LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
>          set_stream_volumes(client);
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>  
>      return S_OK;
>  }
> @@ -2148,11 +2157,11 @@ static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
>  
>      TRACE("PulseAudio does not support session volume control\n");
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      session->channel_vols[index] = level;
>      LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
>          set_stream_volumes(client);
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>  
>      return S_OK;
>  }
> @@ -2199,12 +2208,12 @@ static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
>  
>      TRACE("PulseAudio does not support session volume control\n");
>  
> -    pulse->lock();
> +    EnterCriticalSection(&session_cs);
>      for(i = 0; i < count; ++i)
>          session->channel_vols[i] = levels[i];
>      LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
>          set_stream_volumes(client);
> -    pulse->unlock();
> +    LeaveCriticalSection(&session_cs);
>      return S_OK;
>  }
>  
> diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
> index 143406988d4..2511e8fea39 100644
> --- a/dlls/winepulse.drv/pulse.c
> +++ b/dlls/winepulse.drv/pulse.c
> @@ -99,12 +99,12 @@ static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
>  UINT8 mult_alaw_sample(UINT8, float);
>  UINT8 mult_ulaw_sample(UINT8, float);
>  
> -static void WINAPI pulse_lock(void)
> +static void pulse_lock(void)
>  {
>      pthread_mutex_lock(&pulse_mutex);
>  }
>  
> -static void WINAPI pulse_unlock(void)
> +static void pulse_unlock(void)
>  {
>      pthread_mutex_unlock(&pulse_mutex);
>  }
> @@ -178,13 +178,13 @@ static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout,
>  static void WINAPI pulse_main_loop(HANDLE event)
>  {
>      int ret;
> +    pulse_lock();
>      pulse_ml = pa_mainloop_new();
>      pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
>      NtSetEvent(event, NULL);
> -    pulse_lock();
>      pa_mainloop_run(pulse_ml, &ret);
> -    pulse_unlock();
>      pa_mainloop_free(pulse_ml);
> +    pulse_unlock();
>  }
>  
>  static void pulse_contextcallback(pa_context *c, void *userdata)
> @@ -799,11 +799,19 @@ static HRESULT WINAPI pulse_create_stream(const char *name, EDataFlow dataflow,
>      unsigned int i, bufsize_bytes;
>      HRESULT hr;
>  
> +    pulse_lock();
> +
>      if (FAILED(hr = pulse_connect(name)))
> +    {
> +        pulse_unlock();
>          return hr;
> +    }
>  
>      if (!(stream = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*stream))))
> +    {
> +        pulse_unlock();
>          return E_OUTOFMEMORY;
> +    }
>  
>      stream->dataflow = dataflow;
>      for (i = 0; i < ARRAY_SIZE(stream->vol); ++i)
> @@ -867,6 +875,9 @@ static HRESULT WINAPI pulse_create_stream(const char *name, EDataFlow dataflow,
>          }
>      }
>  
> +    *channel_count = stream->ss.channels;
> +    *ret = stream;
> +
>  exit:
>      if (FAILED(hr)) {
>          free(stream->local_buffer);
> @@ -875,12 +886,10 @@ exit:
>              pa_stream_unref(stream->stream);
>              RtlFreeHeap(GetProcessHeap(), 0, stream);
>          }
> -        return hr;
>      }
>  
> -    *channel_count = stream->ss.channels;
> -    *ret = stream;
> -    return S_OK;
> +    pulse_unlock();
> +    return hr;
>  }
>  
>  static void WINAPI pulse_release_stream(struct pulse_stream *stream, HANDLE timer)
> @@ -1802,13 +1811,15 @@ static HRESULT WINAPI pulse_set_event_handle(struct pulse_stream *stream, HANDLE
>  
>  static BOOL WINAPI pulse_is_started(struct pulse_stream *stream)
>  {
> -    return pulse_stream_valid(stream) && stream->started;
> +    BOOL ret;
> +    pulse_lock();
> +    ret = pulse_stream_valid(stream) && stream->started;
> +    pulse_unlock();
> +    return ret;
>  }
>  
>  static const struct unix_funcs unix_funcs =
>  {
> -    pulse_lock,
> -    pulse_unlock,
>      pulse_main_loop,
>      pulse_create_stream,
>      pulse_release_stream,
> diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h
> index 797ed3bdaa5..b8a579ebef4 100644
> --- a/dlls/winepulse.drv/unixlib.h
> +++ b/dlls/winepulse.drv/unixlib.h
> @@ -33,8 +33,6 @@ struct pulse_config
>  
>  struct unix_funcs
>  {
> -    void (WINAPI *lock)(void);
> -    void (WINAPI *unlock)(void);
>      void (WINAPI *main_loop)(HANDLE event);
>      HRESULT (WINAPI *create_stream)(const char *name, EDataFlow dataflow, AUDCLNT_SHAREMODE mode,
>                                      DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period,
> 




More information about the wine-devel mailing list