[wdmaudiodev] Re: AW: Re: Possible problem in IPortDMus::Notify and servicegroup dispatching?

  • From: "Evert van der Poll" <evert@xxxxxxxxxxx>
  • To: <wdmaudiodev@xxxxxxxxxxxxx>
  • Date: Mon, 16 Aug 2010 11:50:20 +0100

Hi Tobias,

This is indeed an annoying problem and probably easy to fix if you have the
source code of PortCls. But somehow I doubt that is going to happen. Is
PortCls even supported still? I know that Microsoft pulled the plug for
DirectMusic some time ago.

>> A clarification from Microsoft whether IAllocatorMXF::PutMessage()
>> and IAllocatorMXF::GetMessage() can be used while holding a lock
>> would be nice

The problem is not with IAllocatorMXF::PutMessage() or
IAllocatorMXF::GetMessage(). My Syser aided investigation showed that the
deadlock occurs AFTER you return to PortCls from IMXF::PutMessage() on a
capture filter.

My guess about what happens is this: IMXF::PutMessage() is called on a
capture filter to retrieve MIDI data from it. It is a response to calling
IPortDMus::Notify() on your capture port. PortCls will continue to call
IMXF::PutMessage() until that function returns NULL, meaning there is no
more data.
The processing that PortCls does after receiving data from
IMXF::PutMessage() needs to acquire two spinlocks. About the same time
IPortDMus::Notify() needs to acquire the same two spinlocks but in reversed
order; a classic deadlock scenario.
The important thing in the above sentence is that, if there is no data
returned from IMXF::PutMessage() there will be no processing and hence no
need to acquire the spinlocks. That is why my solution will work; because
there will be no new IPortDMus::Notify() call until IMXF::PutMessage()
returns NULL.

>> Good if this clears up the problem for you, but I'm a bit uneasy
>> with this approach since I would always doubt if a freeze could
>> not come up under other conditions (more concurrent virtual ports,
>> more CPUs, other system-load, more port-throughput).

I agree that there is no guarantee this solution will work with multiple
ports, the only condition that I think is relevant.
However, I tested this extensively with MidiTest (another one of those
indispensible tools ;)) and had no freeze choking 4 ports simultaneously. To
put this in perspective, before my fix just one port would freeze the system
in less than a minute.
So, don't worry!


Regards,
Evert






-----Original Message-----
From: wdmaudiodev-bounce@xxxxxxxxxxxxx
[mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx]On Behalf Of Tobias Erichsen
Sent: Monday, August 16, 2010 6:15 AM
To: wdmaudiodev@xxxxxxxxxxxxx
Subject: [wdmaudiodev] AW: Re: Possible problem in IPortDMus::Notify and
servicegroup dispatching?


Hi Evert,

thanks for your feedback...

> I have seen this exact behaviour in my own driver and for
> months I couldn't figure out what was wrong. It only happened
> on multi-processor or hyper-threaded machines, so it was
> obviously caused by something deadlocking. The symptoms were:
> complete system freeze at random moments.
> Only hard-reset would help.

It seems that other people (especially those with virtual MIDI
drivers that support multiple virtual ports) have this problem
as well.

> I went through my code over and over again but couldn't find
> anything wrong.
> Like you I also suspected IAllocatorMXF::PutMessage(). In the
> end I used Syser to track down the problem (where would we be
> without Syser? Ok, it's not perfect, but I couldn't have
> fixed this without it).

A clarification from Microsoft whether IAllocatorMXF::PutMessage()
and IAllocatorMXF::GetMessage() can be used while holding a lock
would be nice - especially since the DMusUart sample does so for
PutMessage() in the ConsumeEvents method, but others on this
mailing-list warn (with good cause) to call OS-functionality
while holding a lock - but implementing SourceEvtsToPort and
ConsumeEvents without holding a lock could be a complete
race-condition-nightmare...

> I also found IPortDMus::Notify() to be the culprit. Of course
> it's hard to provide irrefutable evidence but I'd say this
> qualifies as a system bug.

I would hope that the Microsoft guys on this list will participate
in this discussion and help resolve this issue.

> What solved it for me is to minimize the IPortDMus::Notify()
> calls. I use some sort of flag for indicating that the port
> has been notified which will only be reset after the queue
> has been emptied.
> For as long as the flag is set I don't call
> IPortDMus::Notify() anymore, since I know that queue
> processing will continue anyway.

Good if this clears up the problem for you, but I'm a bit uneasy
with this approach since I would always doubt if a freeze could
not come up under other conditions (more concurrent virtual ports,
more CPUs, other system-load, more port-throughput).

So I'd consider a "real" solution for this issue in the PortCls
to be appropriate.

I hope some other people with experience could chime in on this
subject as well...

Best regards,
Tobias

******************

WDMAUDIODEV addresses:
Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx
Subscribe:    mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe
Unsubscribe:  mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe
Moderator:    mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx

URL to WDMAUDIODEV page:
http://www.wdmaudiodev.com/


******************

WDMAUDIODEV addresses:
Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx
Subscribe:    mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe
Unsubscribe:  mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe
Moderator:    mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx

URL to WDMAUDIODEV page:
http://www.wdmaudiodev.com/

Other related posts: