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