lkml.org 
[lkml]   [2019]   [Apr]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 1/3] timers: raise timer softirq on __mod_timer/add_timer_on
    For isolated CPUs, we'd like to skip awakening ktimersoftd
    (the switch to and then back from ktimersoftd takes 10us in
    virtualized environments, in addition to other OS overhead,
    which exceeds telco requirements for packet forwarding for
    5G) from the sched tick.

    The patch "timers: do not raise softirq unconditionally" from Thomas
    attempts to address that by checking, in the sched tick, whether its
    necessary to raise the timer softirq. Unfortunately, it attempts to grab
    the tvec base spinlock which generates the issue described in the patch
    "Revert "timers: do not raise softirq unconditionally"".

    tvec_base->lock protects addition of timers to the wheel versus
    timer interrupt execution.

    This patch does not grab the tvec base spinlock from irq context,
    but rather performs a lockless access to base->pending_map.

    It handles the the race between timer addition and timer interrupt
    execution by unconditionally (in case of isolated CPUs) raising the
    timer softirq after making sure the updated bitmap is visible
    on remote CPUs.

    This patch reduces cyclictest latency from 25us to 14us
    on my testbox.

    Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

    ---
    kernel/time/timer.c | 38 ++++++++++++++++++++++++++++++++++++++
    1 file changed, 38 insertions(+)

    Index: linux-rt-devel/kernel/time/timer.c
    ===================================================================
    --- linux-rt-devel.orig/kernel/time/timer.c 2019-04-15 13:56:06.974210992 -0300
    +++ linux-rt-devel/kernel/time/timer.c 2019-04-15 14:21:02.788704354 -0300
    @@ -41,6 +41,7 @@
    #include <linux/sched/sysctl.h>
    #include <linux/sched/nohz.h>
    #include <linux/sched/debug.h>
    +#include <linux/sched/isolation.h>
    #include <linux/slab.h>
    #include <linux/compat.h>
    #include <linux/swait.h>
    @@ -907,6 +908,12 @@
    #endif
    }

    +static DEFINE_PER_CPU(call_single_data_t, raise_timer_csd);
    +
    +static void raise_timer_softirq(void *arg)
    +{
    + raise_softirq(TIMER_SOFTIRQ);
    +}

    /*
    * We are using hashed locking: Holding per_cpu(timer_bases[x]).lock means
    @@ -1056,6 +1063,17 @@
    internal_add_timer(base, timer);
    }

    + if (!housekeeping_cpu(base->cpu, HK_FLAG_TIMER) &&
    + !(timer->flags & TIMER_DEFERRABLE)) {
    + call_single_data_t *c;
    +
    + c = per_cpu_ptr(&raise_timer_csd, base->cpu);
    +
    + /* Make sure bitmap updates are visible on remote CPUs */
    + smp_wmb();
    + smp_call_function_single_async(base->cpu, c);
    + }
    +
    out_unlock:
    raw_spin_unlock_irqrestore(&base->lock, flags);

    @@ -1175,6 +1193,17 @@

    debug_activate(timer, timer->expires);
    internal_add_timer(base, timer);
    +
    + if (!housekeeping_cpu(base->cpu, HK_FLAG_TIMER) &&
    + !(timer->flags & TIMER_DEFERRABLE)) {
    + call_single_data_t *c;
    +
    + c = per_cpu_ptr(&raise_timer_csd, base->cpu);
    +
    + /* Make sure bitmap updates are visible on remote CPUs */
    + smp_wmb();
    + smp_call_function_single_async(base->cpu, c);
    + }
    raw_spin_unlock_irqrestore(&base->lock, flags);
    }
    EXPORT_SYMBOL_GPL(add_timer_on);
    @@ -1970,6 +1999,15 @@
    {
    int cpu;

    + for_each_possible_cpu(cpu) {
    + call_single_data_t *c;
    +
    + c = per_cpu_ptr(&raise_timer_csd, cpu);
    + c->func = raise_timer_softirq;
    + c->info = NULL;
    + c->flags = 0;
    + }
    +
    for_each_possible_cpu(cpu)
    init_timer_cpu(cpu);
    }

    \
     
     \ /
      Last update: 2019-04-15 22:17    [W:4.072 / U:0.956 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site