winepulse: Use a critical section for PE-side locking.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-05-26 16:18:43 +02:00 committed by Alexandre Julliard
parent b4c7823bbb
commit a4149d53f7
3 changed files with 58 additions and 40 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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,