Page MenuHomeFreeBSD

sound: Unlock around uiomove() in midi_{read,write}()
Needs ReviewPublic

Authored by christos on Mon, Dec 8, 4:03 PM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Dec 29, 5:57 PM
Unknown Object (File)
Sun, Dec 28, 4:51 AM
Unknown Object (File)
Mon, Dec 22, 9:35 PM
Unknown Object (File)
Sun, Dec 21, 8:04 AM
Unknown Object (File)
Fri, Dec 19, 11:49 PM
Unknown Object (File)
Thu, Dec 18, 11:10 AM
Unknown Object (File)
Thu, Dec 18, 8:23 AM
Unknown Object (File)
Thu, Dec 18, 7:30 AM

Details

Reviewers
markj
emaste
Summary

Sponsored by: The FreeBSD Foundation
MFC after: 1 week

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 69128
Build 66011: arc lint + arc unit

Event Timeline

sys/dev/sound/midi/midi.c
474

are there any struct snd_midimembers that could be invalid after dropping and reacquiring the lock? E.g. could m->flags & M_RX no longer be true?

sys/dev/sound/midi/midi.c
474

The only place where M_RX gets cleared is in midi_close(), so I'm not sure we should worry about this, since by that time we'll have closed and midi_read() will just need to flush. Or am I missing something?

sys/dev/sound/midi/midi.c
551

used is calculated above: used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid). What if the amount of available space changed while the lock was dropped?

sys/dev/sound/midi/midi.c
551

I'm not really sure how to address this. I suppose if the available size since then has changed to something less than used, I suppose we will discard a few bytes. Shouldn't that be the normal case though? We've got a statically-sized buffer,so if some other thread fills it first, then we won't have available space until we drain it.

Still not sure this is good. It is working as-it for me; uiomove will not sleep if the lock is taken just above!

Still not sure this is good. It is working as-it for me; uiomove will not sleep if the lock is taken just above!

We have to unlock since we are using a non-sleepable lock.

I'm not convinced we have to unlock here, but this may give a breathe to the interrupt, so why not (during my last test I found too much latency but I don't know yet if it is relative to my userspace code or not).

I'm not convinced we have to unlock here, but this may give a breathe to the interrupt, so why not (during my last test I found too much latency but I don't know yet if it is relative to my userspace code or not).

That's how uiomove() works. If you hold a non-sleepable lock when it runs, you'll get an error from WITNESS.

I see. You may only have to check for M_RX inside the loop and not at line 433 (file closed), in addition to the extra lock/unlock.

I see. You may only have to check for M_RX inside the loop and not at line 433 (file closed), in addition to the extra lock/unlock.

Why? Even if M_RX gets unset during the loop, we should still drain the read().

If M_RX gets unset, the device file was closed, so no read will occur anymore and draining or keeping data is useless. I made a successful test with this extra lock/unlock.

If M_RX gets unset, the device file was closed, so no read will occur anymore and draining or keeping data is useless. I made a successful test with this extra lock/unlock.

I agree it will essentially be "useless", but I do not get the value of introducing a check for every single loop, since read() will fail anyway if the file is closed mid-read.

sys/dev/sound/midi/midi.c
551

@markj Bump ^

Two different processes cannot have an opened descriptor to the same MIDI device. So, I think the only problematic case is when a process opens the device and a child thread is waiting in blocking mode; if the descriptor is closed by the parent thread, will this properly stop the blocking read?

Two different processes cannot have an opened descriptor to the same MIDI device. So, I think the only problematic case is when a process opens the device and a child thread is waiting in blocking mode; if the descriptor is closed by the parent thread, will this properly stop the blocking read?

@markj @kib Haven't had a chance to test this scenario yet, do you have any idea regarding this?

I just realized that the outer loop "while (uio->uio_resid > 0)" is NOT needed at all in midi_read, which solves the problem. We must return as soon as some data is read.

Same thing, probably, in midi_write.