• Thomas Gleixner's avatar
    posix-cpu-timers: prevent signal delivery starvation · fe8187b8
    Thomas Gleixner authored
    The integer divisions in the timer accounting code can round the result
    down to 0.  Adding 0 is without effect and the signal delivery stops.
    
    Clamp the division result to minimum 1 to avoid this.
    
    Problem was reported by Seongbae Park <spark@google.com>, who provided
    also an inital patch.
    
    Roland sayeth:
    
      I have had some more time to think about the problem, and to reproduce it
      using Toyo's test case.  For the record, if my understanding of the problem
      is correct, this happens only in one very particular case.  First, the
      expiry time has to be so soon that in cputime_t units (usually 1s/HZ ticks)
      it's < nthreads so the division yields zero.  Second, it only affects each
      thread that is so new that its CPU time accumulation is zero so now+0 is
      still zero and ->it_*_expires winds up staying zero.  For the VIRT and PROF
      clocks when cputime_t is tick granularity (or the SCHED clock on
      configurations where sched_clock's value only advances on clock ticks), this
      is not hard to arrange with new threads starting up and blocking before they
      accumulate a whole tick of CPU time.  That's what happens in Toyo's test
      case.
    
      Note that in general it is fine for that division to round down to zero,
      and set each thread's expiry time to its "now" time.  The problem only
      arises with thread's whose "now" value is still zero, so that now+0 winds up
      0 and is interpreted as "not set" instead of ">= now".  So it would be a
      sufficient and more precise fix to just use max(ticks, 1) inside the loop
      when setting each it_*_expires value.
    
      But, it does no harm to round the division up to one and always advance
      every thread's expiry time.  If the thread didn't already fire timers for
      the expiry time of "now", there is no expectation that it will do so before
      the next tick anyway.  So I followed Thomas's patch in lifting the max out
      of the loops.
    
      This patch also covers the reload cases, which are harder to write a test
      for (and I didn't try).  I've tested it with Toyo's case and it fixes that.
    
    [toyoa@mvista.com: fix: min_t -> max_t]
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
    fe8187b8
posix-cpu-timers.c 41.6 KB