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



The following reply was made to PR kern/54818; it has been noted by GNATS.

From: Havard Eidnes <he%uninett.no@localhost>
To: gnats-bugs%netbsd.org@localhost, ""@uninett.no
Cc: ad%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost, tsutsui%ceres.dti.ne.jp@localhost
Subject: Re: kern/54818: 9.0_RC1 pagedaemon spins
Date: Sun, 15 Mar 2020 11:38:20 +0100 (CET)

 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