On Mon, Sep 16, 2019 at 03:44:32PM -0300, Martin Pieuchot wrote:
> On 16/09/19(Mon) 19:31, Alexandre Ratchov wrote:
> > On Sun, Sep 15, 2019 at 03:01:36PM -0300, Martin Pieuchot wrote:
> > > On 29/08/19(Thu) 10:52, Alexandre Ratchov wrote:
> > > > The diff below allows to specifiy "an alternate device" to use in case
> > > > the audio device is disconnected. If so, programs continue playing
> > > > using the other device.
> > > > 
> > > > For instance, if dmesg contains:
> > > > 
> > > >         audio0 at azalia0
> > > >         audio1 at uaudio0
> > > > 
> > > > and /etc/rc.conf.local contains:
> > > > 
> > > >         sndiod_flags=-f rsnd/0 -F rsnd/1
> > > > 
> > > > then sndiod will try to use the usb device by default. If it's
> > > > disconnected, programs continue using the internal one. Note that
> > > > there's no way to detect that the usb device is reconnected;
> > > 
> > > Instead of doing a open/reopen dance in userland, which is inherently
> > > racy, did you consider introducing a driver abstracting the various
> > > audio(4) drivers attached?  I'm thinking of something like wsmux(4) for
> > > audio.  This should allow us to transparently attach/detach usb audio
> > > devices.
> > 
> > I don't see any race conditions: once a device disappears, it is
> > closed and another one is opened in place. This only relies on calls
> > to open() and close() which are not racy. Unlike with hotplug(4),
> > there's no concurency between multiple code-paths; it's all
> > sequencial.
> 
> I understand the logic for closing an existing device, but what about
> plugging a new one?  I understand that this is not the scope of the
> diff, I wondering if that would fit in the model you're suggesting.
> 
> It is just a matter of sending SIGHUP, so I could fake that when
> uaudio(4) attaches for example?

Yes. That's the best we can do with "unix file open/close semantics"
only. Going further, if desired, would require some kind of kernel
support.

There's a full range of "clever" and complicated ways to handle
hot-plugging automatically (and to configure it!). I don't know what's
the best one, some experimenting is needed first.

> Regarding the race I was talking about, doesn't dev_reopen() close the
> current device before trying to open a new one, possibly finding an
> incompatible device or failing to open it?  What happens in this case?

After a SIGHUP, if the new device is incompatible, the old one is
reopened and sound continues. Now I understand your remark: oops!
close() and open() are called in the wrong order, so another process
could steal the device. I'll fix that.

> > I've considered the wsmux-style device for audio. Multiple audio
> > devices can't be combined, so the audio mux device would be a switch
> > between the devices, which is roughly what the diff does.
> > 
> > Switching between devices, when possible, is not trivial, because the
> > state of one device must be restored on another device. It may require
> > channel mapping and/or format conversions, in case the devices don't
> > have the same capabilities. We don't want such complicated code to run
> > with full kernel privileges and to have access to all the physical
> > memory. FWIW, this was one of the reasons for moving the audio
> > sub-system completely to user-space, leaving in the kernel only the
> > code to access the hardware.
> 
> I understand.
> 
> Another question, if a machine has multiple audio devices, including an
> USB one, can't we assume that we should try this one first?  Or could a
> choice mechanism like kern.timecounter with default value could be
> implemented to make this new feature work out of the box?

Almost. The reverse attaching order seems to cover most practical use
cases. If the user coonects a USB device, it's probably because he
wants to use it, so it would make sense for it to be tried first.

But a choice mechanism seems necessary in certain cases. For instance
"pro" audio interfaces need to be handled separately; certain USB
devices (ex. webcams) come with an unused audio interface that the
user may want to skip.

> 
> Finally, is there any downside of having a smaller DEFAULT_ROUND?

No. FWIW, the large default block and buffer sizes used to be
necessary 10+ years ago because MP kernels could delay interrupts for
more than a audio block which used to confuse azalia(4) and envy(4)
permanently. Now drivers are resilient to interrupt loss and any block
size could be used. Recent MP kernels behave better.

Reply via email to