I've noticed something weird.  The audio(7I) man page claims the following:

     The final close(2) of the file descriptor hangs until all of
     the  audio  output  has  drained. If a signal interrupts the
     close(), or if the process exits without closing the device,
     any  remaining  data  queued for audio output is flushed and
     the device is closed immediately.

The peculiar thing here is the difference in the semantics for a process 
that does exit() versus one that cleanly calls close().  I've never seen 
any thing in the DDI that would indicate that it is possible for a 
driver to know this distinction.  So I got curious and looked around in 
the audio mixer code, and found this gem:

            while (!(chpptr->acp_flags & AM_CHNL_EMPTY) &&
                !(curthread->t_proc_flag & TP_LWPEXIT)) {

This is the code that waits for the queue to drain in am_close_audio.

Now, I figure it is really poor form to be looking at curthread at all, 
certainly not DDI safe.  But, thinking about it, it seems like 
ddi_can_receive_sig() might be a better approach.  The implementation 
certainly seems to imply this:

    boolean_t
    ddi_can_receive_sig(void)
    {
        proc_t *pp;

        if (curthread->t_proc_flag & TP_LWPEXIT)
            return (B_FALSE);
        if ((pp = ttoproc(curthread)) == NULL)
            return (B_FALSE);
        return (pp->p_as != &kas);
    }


My question is, does it seem reasonable to rely on ddi_can_receive_sig() 
to pick up on this?  I'm not sure that the fact that exit()'ing 
processes return false for ddi_can_receive_sig() is a condition that is 
necessarily guaranteed and not just an implementation side effect.

Another possible concern with this approach that I see is that if a 
kernel thread opens the audio device, it won't get the drain semantics 
for closing the audio stream.  I'm not yet convinced that this is a 
problem for this particular application, but perhaps I could use 
ddi_get_pid()?  (Does ddi_get_pid() return 0 for kernel thread?)

So a possible "DDI safe" rewrite of the above logic *could* be:

            while (!(chpptr->acp_flags & AM_CHNL_EMPTY) &&
                (ddi_can_receive_sig() && ddi_get_pid() != 0)) {

Thoughts?

    -- Garrett


Reply via email to