• Linus Torvalds's avatar
    signal: avoid double atomic counter increments for user accounting · d695cdb9
    Linus Torvalds authored
    BugLink: https://bugs.launchpad.net/bugs/1868629
    
    [ Upstream commit fda31c50 ]
    
    When queueing a signal, we increment both the users count of pending
    signals (for RLIMIT_SIGPENDING tracking) and we increment the refcount
    of the user struct itself (because we keep a reference to the user in
    the signal structure in order to correctly account for it when freeing).
    
    That turns out to be fairly expensive, because both of them are atomic
    updates, and particularly under extreme signal handling pressure on big
    machines, you can get a lot of cache contention on the user struct.
    That can then cause horrid cacheline ping-pong when you do these
    multiple accesses.
    
    So change the reference counting to only pin the user for the _first_
    pending signal, and to unpin it when the last pending signal is
    dequeued.  That means that when a user sees a lot of concurrent signal
    queuing - which is the only situation when this matters - the only
    atomic access needed is generally the 'sigpending' count update.
    
    This was noticed because of a particularly odd timing artifact on a
    dual-socket 96C/192T Cascade Lake platform: when you get into bad
    contention, on that machine for some reason seems to be much worse when
    the contention happens in the upper 32-byte half of the cacheline.
    
    As a result, the kernel test robot will-it-scale 'signal1' benchmark had
    an odd performance regression simply due to random alignment of the
    'struct user_struct' (and pointed to a completely unrelated and
    apparently nonsensical commit for the regression).
    
    Avoiding the double increments (and decrements on the dequeueing side,
    of course) makes for much less contention and hugely improved
    performance on that will-it-scale microbenchmark.
    
    Quoting Feng Tang:
    
     "It makes a big difference, that the performance score is tripled! bump
      from original 17000 to 54000. Also the gap between 5.0-rc6 and
      5.0-rc6+Jiri's patch is reduced to around 2%"
    
    [ The "2% gap" is the odd cacheline placement difference on that
      platform: under the extreme contention case, the effect of which half
      of the cacheline was hot was 5%, so with the reduced contention the
      odd timing artifact is reduced too ]
    
    It does help in the non-contended case too, but is not nearly as
    noticeable.
    Reported-and-tested-by: default avatarFeng Tang <feng.tang@intel.com>
    Cc: Eric W. Biederman <ebiederm@xmission.com>
    Cc: Huang, Ying <ying.huang@intel.com>
    Cc: Philip Li <philip.li@intel.com>
    Cc: Andi Kleen <andi.kleen@intel.com>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
    Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
    Signed-off-by: default avatarKelsey Skunberg <kelsey.skunberg@canonical.com>
    d695cdb9
signal.c 96.8 KB