resolving dead-locks using InterlockedPushEntrySList on MacOS #29657
Joerg-Cyril.Hoehle at t-systems.com
Joerg-Cyril.Hoehle at t-systems.com
Fri Jan 20 12:19:29 CST 2012
Hi,
Let's assume for the discussion that
Winecoreaudio/mmdevdrv.c: ca_in_buffer_cb(...)
{
OSSpinLockLock(&This->lock);
list_add_tail(&This->avail_buffers, &buf->entry);
This->inbuf_frames += buffer->mAudioDataByteSize / This->fmt->nBlockAlign;
OSSpinLockUnlock(&This->lock);
}
really is causing deadlocks and leads to bogus code like releasing
locks mid-function to call other functions that may take the lock too:
OSSpinLockUnlock(&This->lock);
sc = AudioQueueFlush(This->aqueue);
sc = AudioQueuePause(This->aqueue);
OSSpinLockLock(&This->lock);
-- alas allowing any other thread to enter mmdevdrv in between.
(I'll have to perform more checks this week-end).
For reference, see bug #29657.
I thought about using lock-free data structures:
a) MacOS lock-free FIFO
b) MS' InterlockedPushEntrySList
c) other schemes
a) MacOS' lock-free FIFO:
MacOS OSAtomicFifoEnqueue is only available with Lion, which rules it out.
http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/index.html#//apple_ref/c/func/OSAtomicFifoEnqueue
b) MS' InterlockedPushEntrySList:
That is implemented in dlls/ntdll/rtl.c
However, I presumably can't call that from within the MacOS
callback, because the cross-library call might get logged
by +relay, and that's a no-no within the native callback
(RunLoop) execution context.
Work-around: copy&paste that function into winecoreaudio
I don't like that much but do you have a better idea?
c) other schemes:
Assuming list elements are returned in the order we sent them out, we
don't need to enqueue them and instead could set a bit or use
InterlockedIncrement (like the MCI does with winmm headers).
Is there any other suggestion that comes to mind?
IMHO, ca_in_buffer_cb doesn't need a transaction around
enqueue+inbuf. Enqueue and inbuf+= could be performed
separately, inbuf+= could even be deferred to GetCurrentPadding,
leaving one single operation left to do within the MacOS callback.
Regards,
Jörg Höhle
More information about the wine-devel
mailing list