[wdmaudiodev] Problem capturing midi on multiprocessor (SMP) XP machines

  • From: joel@xxxxxxxxxxx
  • To: wdmaudiodev@xxxxxxxxxxxxx
  • Date: Thu, 13 Jan 2005 18:12:13 -0500 (EST)

Hello, I?m having a problem capturing midi on multiprocessor (SMP) XP
machines
My problem seems to be experienced by others on this list. I get to that
in a second.
Background:
All driver development so far has been done and tested on XP SP1 and XP SP2
I have successfully made a midi driver based upon the DMUSUART DDK example.
I create a miniport class inheriting from the IMiniportDMus class.
I can capture and render midi no problem on a single processor machine.
This driver has no hardware associated with it, it talks to a USB driver I
created through a private interface (acquired with
IRP_MN_QUERY_INTERFACE).
My nodes and pins look good in KS. I took my filter descriptor from DMUSUART.
Regular standard midi is captured and rendered on single processor (intel
and AMD) machines, no problem. No SYSEX messages, just status, byte one
and byte two.
It works well with MidiOx and other audio programs.

So far so good until?
I tested my midi driver out on a dual processor machine (SMP).  All the
dual processor machines I have tested on have been SMP AMD Opteron. After
about a minute of sending midi I got a reproducible bug check. Upon
further analysis I found MXF::PutMessage(some_midi_message) to be culprit.
Commenting it out gets rid of the bug check. To prevent problems with dual
processors I wrapped my entire ?send midi to portcls? routine in a spin
lock. This is the routine that contains MXF::GetMessage() and
MXF::PutMessage().
The spin lock doesn?t prevent the bugcheck.
The problem appears to be inside of MXF::PutMessage().
When I send a list of messages at once (taking advantage of pNextEvt) I
get the same bug check and call stack every time (I list it below). The
problem also happens when I send midi messages too quickly in succession,
same bugcheck / call stack.

Fortunately this is not a problem exclusive to me.
Others on this list have hit this same wall (Philip Lukidis in particular):
//www.freelists.org/archives/wdmaudiodev/02-2004/msg00021.html

I?ve read through these all these posts and spent a couple days trying all
the suggestions to the best of my ability.
I had much hope in using KeSetTargetProcessorDpc(). Unfortunately this
function didn?t help. Maybe my use is wrong, I queue a DPC when I want to
send captured midi to portcls. In my DPC I call my ?send captured midi?
routine and provide midi messages from an internal midi buffer. It works
great on a single processor system.
The problem is that I get the same bug check (minidump is below) on a dual
processor system.
I also tried the thread affinity method:
KAFFINITY threadAffinityMask = NumberOfActiveProcessors & (1 <<
TargetProcessorNumber);
// TargetProcessorNumber is a zero based number
status = ZwSetInformationThread((HANDLE)-2, //current thread handle
                                ThreadAffinityMask,
                                &threadAffinityMask,
                                sizeof(KAFFINITY));
That did not work either.

I?ve even written a IMiniportMidi version of my midi driver (just like
Philip Lukidis claims to have done). It works but has critical issues
which I get to below.

First here is the Minidump from dual processor machines when calling
MXF::PutMessage() too quickly or with a list of midi events:

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address
at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
Arguments:
Arg1: 00000002, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: f8003bd2, address which referenced memory

Debugging Details:
------------------


READ_ADDRESS:  00000002

CURRENT_IRQL:  2

FAULTING_IP:
portcls!CPackerMXF::ProcessQueues+66
f8003bd2 0fb74a02         movzx   ecx,word ptr [edx+0x2]

CUSTOMER_CRASH_COUNT:  1

DEFAULT_BUCKET_ID:  DRIVER_FAULT

BUGCHECK_STR:  0xD1

LAST_CONTROL_TRANSFER:  from f8002afd to f8003bd2

STACK_TEXT:
f8988fa0 f8002afd 822d2108 8223a3c8 f8002ec9
portcls!CPackerMXF::ProcessQueues+0x66
f8988fac f8002ec9 f8988fcc f7fff497 82225418
portcls!CPortPinDMus::ServeCapture+0x37
f8988fb4 f7fff497 82225418 806e4427 ffdff000
portcls!CPortPinDMus::RequestService+0x26
f8988fcc 80544e5f 822d20e8 822d20d8 00000000
portcls!CServiceGroup::ServiceDpc+0x2a
ffdff980 ffdff980 f8989000 00015f52 00000000 nt!WmiTraceEvent+0x3e8


FOLLOWUP_IP:
portcls!CPackerMXF::ProcessQueues+66
f8003bd2 0fb74a02         movzx   ecx,word ptr [edx+0x2]

SYMBOL_STACK_INDEX:  0

FOLLOWUP_NAME:  MachineOwner

SYMBOL_NAME:  portcls!CPackerMXF::ProcessQueues+66

MODULE_NAME:  portcls

IMAGE_NAME:  portcls.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  41107f13

STACK_COMMAND:  kb

BUCKET_ID:  0xD1_portcls!CPackerMXF::ProcessQueues+66

Followup: MachineOwner

This could be a separate post, but I?ll include it here because it relates
to sending captured midi to portcls.
I?ve written a IMiniportMidi version of my midi driver. I?d be perfectly
happy using the IMiniportMidi version except that I?m having some trouble.
Everything works fine with my IMiniportMidi version except when I try to
send captured midi data to portcls. The driver can start up when I open it
in MidiOx, IMiniportMidiStream::SetState() gets called with KSSTATE_RUN.
IMiniportMidiStream::Write() will send me midi to render. Under XP SP1 on
a single or a dual processor machine I can send captured midi to MidiOx
successfully under certain conditions.
When I try to return captured midi data in IMiniportMidiStream::Read() too
quickly (more than a message every 2 seconds) my system will hang. Sounds
weird right?
This happens on single and multiprocessor machines. XP SP1 and SP2. SP1 is
a little better in that I can get a message off every couple seconds,
anything faster will freeze the system. SP2 will freeze the first time I
send any midi off.
I instigate portcls to call my IMiniportMidiStream::Read() function by
calling IServiceGroup:: RequestService () or IPortMidi::Notify() from a
DPC.
My Read function looks pretty simple.

STDMETHODIMP_(NTSTATUS) CMiniportMidiStream::Read
(
                IN PVOID BufferAddress,
                IN ULONG BufferLength,
                OUT PULONG BytesRead
)
{
 NTSTATUS ntStatus = STATUS_SUCCESS; // STATUS_NOT_IMPLEMENTED

 *BytesRead =0;

 if (BufferAddress && BytesRead && BufferLength == 4)
 {
   BYTE *midi_event = (BYTE *)BufferAddress;
   // if I return any thing here my system
   // hangs on SP2
   // on SP1 I can only call return data every couple
   // seconds without hanging the system
   // anything more frequent will hang
   *BytesRead =3;
   // it doesn?t matter what data I send
   midi_event[0] = 0x90;
   midi_event[1] = 0x30;
   midi_event[2] = 0x7f;
  }

  return ntStatus;
}

Since the documentation for this stuff is pretty straight forward and
there are no examples of sending captured midi data with
IMiniportMidiStream, I?m not sure what is going on.
Like I said IMiniportMidiStream::Write() works great!

So all in all I?m having some issues sending captured midi to portcls.

Any help would be greatly appreciated
I'd be happy to show more source code if needed or send the minidump
anyones way.
Thanks
Joel Willard
******************

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.de/

Other related posts: