Subject: polled output advice
To: None <tech-kern@NetBSD.org>
From: Chapman Flack <chap@anastigmatix.net>
List: tech-kern
Date: 01/12/2006 12:47:19
I'm thinking of changing a timing-related design decision in midi
and looking for a sanity check.

Some midi output devices (e.g. ic/mpu) do not have an output-ready
interrupt. The output routine has to poll for the ready bit. mpu.c
does this in a loop with delay(10) between tests. So, everything but
unmasked interrupts grinds to a halt while output is active, for a
time that should be, at midi data rates, about 320us times the
buffered byte count.

In midi.c there is at present an arbitrary constant MIDI_WRITE_MAX
(currently 32, or about 10ms worth) which is the max number of
bytes it will dare submit to the hw driver consecutively.
If there are more than that many buffered, it sets a callout to
resume the output after an arbitrary delay of MIDI_WAIT (currently
10ms).

I understand the concern, but I have reservations about the solution.
MIDI traffic is bursty and time-sensitive. There will be macroscopic
stretches of no traffic at all, but when a lot of simultaneous
notes hit the buffer, they really should be sent with no added
delay - arbitrary delays on the order of 10ms could have audible
consequences. And the approach isn't doing anything to reduce the
total time burned busy waiting--the cpu will still busy wait for
most of 10ms for every 32 bytes output, just taking another 10ms
rest after--perhaps improving scheduling latency for other things,
but effectively cutting the midi data rate in half.

So I am tempted to eliminate the MIDI_MAX_WRITE/MIDI_WAIT callout
business entirely, and go ahead and send everything in the buffer
whenever called, making sure interrupts are enabled during the hw
output calls. That's actually easier without the callout, as the
output code can be running at splnone when invoked by the top half,
whereas with the callout solution it's running at splsoftclock for
the 2nd and subsequent calls, which /worsens/ the impact of the
busy wait.

So interrupts won't be lost, but other processes won't be scheduled.
I doubt any noticeable effect during ordinary sequenced music (short
bursts with macroscopic delays between). For large bulk transfers
(patch dumps and such), the safety valve is the size of the output
buffer and the ordinary scheduling of the writing process. And the
whole issue applies only to systems with the old noninterrupting
midi hw anyway.

Does this sound like a sane approach?

-Chap