NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/54818: 9.0_RC1 pagedaemon spins



Hi,

(just to remind folks, this is with NetBSD 8.1)

It seems that the behaviour from the audio.c driver is that each time
I start a playback in firefox, the dtrace script logs 4 instances of
uvm_km_kmem_alloc(), but only two of uvm_km_kmem_free().

On a hunch, I tried with this diff:

--- audio.c     7 Jun 2018 18:24:16 -0000       1.357.2.13
+++ audio.c     15 Mar 2020 09:18:57 -0000
@@ -1491,6 +1491,9 @@ audio_stream_ctor(audio_stream_t *stream
        int frame_size;
 
        size = min(size, AU_RING_SIZE);
+       /* Will overwrite, may need to release */
+       if (stream->start != NULL)
+               kmem_free(stream->start, stream->bufsize);
        stream->bufsize = size;
        stream->start = kmem_zalloc(size, KM_SLEEP);
        frame_size = (param->precision + 7) / 8 * param->channels;

but that doesn't appear to have any effect.  The trace changes
slightly with the above patch in place, in that the audio_stream_ctor
is now visible in the dtrace output as

  0        -> uvm_km_kmem_alloc               size: 65536
              netbsd`kmem_intr_alloc+0x6d
              netbsd`kmem_intr_zalloc+0xf
              netbsd`audio_stream_ctor.constprop.39+0x34
              netbsd`audiosetinfo+0x10a0
              netbsd`audio_set_defaults+0xeb

There appears to be two places in audiosetinfo() which calls
audio_stream_ctor():

              netbsd`audio_stream_ctor.constprop.39+0x34
              netbsd`audiosetinfo+0x636
and
              netbsd`audio_stream_ctor.constprop.39+0x34
              netbsd`audiosetinfo+0x10a0

and each of them allocates twice.  auidio_stream_dtor() is always
called from the same spot:

              netbsd`audio_stream_dtor+0x1d
              netbsd`audiosetinfo+0x14d5

The two places in "audiosetinfo()" which calls audio_stream_ctor()
decodes to

(gdb) x/i audiosetinfo+0x636
   0xffffffff8079076d <audiosetinfo+1590>:      test   %eax,%eax
(gdb) i li *0xffffffff8079076d
Line 1307 of "/usr/src/sys/dev/audio.c"
   starts at address 0xffffffff80790762 <audiosetinfo+1579>
   and ends at 0xffffffff80790775 <audiosetinfo+1598>.
(gdb) x/i audiosetinfo+0x10a0
   0xffffffff807911d7 <audiosetinfo+4256>:      test   %eax,%eax
(gdb) i li *0xffffffff807911d7
Line 1389 of "/usr/src/sys/dev/audio.c"
   starts at address 0xffffffff807911c5 <audiosetinfo+4238>
   and ends at 0xffffffff807911df <audiosetinfo+4264>.
(gdb)

The first one is the audio_stream_ctor() inside
audio_setup_pfilters(), the second is in audio_setup_rfilters().
Both appear to have been hoisted into audiosetinfo() by the
optimizer.

The visible trace of audio_stream_dtor() invocation is near the end of
audio_setup_pfilters().  However, the "destroy old filters" part in
audio_setup_rfilters() appears to never call the audio_stream_dtor(),
despite there being a loop near the end:

        /* Destroy old filters. */
        for (i = 0; i < onfilters; i++) {
                of[i]->dtor(of[i]);
                audio_stream_dtor(&os[i]);
        }

        return 0;

onfilters is set from vc->sc_nrfilters, and that field is subsequently
set to rfilters->req_size, and the preceding loop which contains the
call to audio_stream_ctor() is over rfilters->req_size.

So ... I can't quite figure out what is going on and why it's leaking
two allocations on each audio device activation.  It would seem that
vc->sc_nrfilters is zero(?)

Anyone have any hints?  (I'll have opportunity to test a new kernel
tomorrow.)

Regards,

- Havard


Home | Main Index | Thread Index | Old Index