lkml.org 
[lkml]   [2007]   [Feb]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    SubjectRe: dynticks + iptables almost stops the boot process [was: Re: 2.6.20-rc6-mm3]
    From
    Date
    On Wed, 2007-02-07 at 00:12 +0100, Tilman Schmidt wrote:
    > > No, not this. Anyway the last patch Thomas forwarded does fix the
    > > problem.
    >
    > Which one would that be? I might try it for comparison.

    Find the combined patch of all fixlets on top of -mm3 below.

    tglx

    Index: linux-2.6.20/kernel/timer.c
    ===================================================================
    --- linux-2.6.20.orig/kernel/timer.c
    +++ linux-2.6.20/kernel/timer.c
    @@ -985,8 +985,9 @@ static int timekeeping_resume(struct sys

    if (now && (now > timekeeping_suspend_time)) {
    unsigned long sleep_length = now - timekeeping_suspend_time;
    +
    xtime.tv_sec += sleep_length;
    - jiffies_64 += (u64)sleep_length * HZ;
    + wall_to_monotonic.tv_sec -= sleep_length;
    }
    /* re-base the last cycle value */
    clock->cycle_last = clocksource_read(clock);
    @@ -994,7 +995,7 @@ static int timekeeping_resume(struct sys
    timekeeping_suspended = 0;
    write_sequnlock_irqrestore(&xtime_lock, flags);

    - clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
    + touch_softlockup_watchdog();
    /* Resume hrtimers */
    clock_was_set();

    Index: linux-2.6.20/kernel/time/clockevents.c
    ===================================================================
    --- linux-2.6.20.orig/kernel/time/clockevents.c
    +++ linux-2.6.20/kernel/time/clockevents.c
    @@ -42,8 +42,8 @@ unsigned long clockevent_delta2ns(unsign
    u64 clc = ((u64) latch << evt->shift);

    do_div(clc, evt->mult);
    - if (clc < KTIME_MONOTONIC_RES.tv64)
    - clc = KTIME_MONOTONIC_RES.tv64;
    + if (clc < 1000)
    + clc = 1000;
    if (clc > LONG_MAX)
    clc = LONG_MAX;

    @@ -72,18 +72,22 @@ void clockevents_set_mode(struct clock_e
    *
    * Returns 0 on success, -ETIME when the event is in the past.
    */
    -int clockevents_program_event(struct clock_event_device *dev, ktime_t expires)
    +int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
    + ktime_t now)
    {
    unsigned long long clc;
    int64_t delta;

    - delta = ktime_to_ns(ktime_sub(expires, ktime_get()));
    + delta = ktime_to_ns(ktime_sub(expires, now));

    if (delta <= 0)
    return -ETIME;

    dev->next_event = expires;

    + if (dev->mode == CLOCK_EVT_MODE_SHUTDOWN)
    + return 0;
    +
    if (delta > dev->max_delta_ns)
    delta = dev->max_delta_ns;
    if (delta < dev->min_delta_ns)
    Index: linux-2.6.20/kernel/time/tick-broadcast.c
    ===================================================================
    --- linux-2.6.20.orig/kernel/time/tick-broadcast.c
    +++ linux-2.6.20/kernel/time/tick-broadcast.c
    @@ -159,6 +159,8 @@ static void tick_do_periodic_broadcast(v
    */
    static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
    {
    + dev->next_event.tv64 = KTIME_MAX;
    +
    tick_do_periodic_broadcast();

    /*
    @@ -174,7 +176,7 @@ static void tick_handle_periodic_broadca
    for (;;) {
    ktime_t next = ktime_add(dev->next_event, tick_period);

    - if (!clockevents_program_event(dev, next))
    + if (!clockevents_program_event(dev, next, ktime_get()))
    return;
    tick_do_periodic_broadcast();
    }
    @@ -294,17 +296,31 @@ cpumask_t *tick_get_broadcast_oneshot_ma
    return &tick_broadcast_oneshot_mask;
    }

    +static int tick_broadcast_set_event(ktime_t expires, int force)
    +{
    + struct clock_event_device *bc = tick_broadcast_device.evtdev;
    + ktime_t now = ktime_get();
    + int res;
    +
    + for(;;) {
    + res = clockevents_program_event(bc, expires, now);
    + if (!res || !force)
    + return res;
    + now = ktime_get();
    + expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
    + }
    +}
    +
    /*
    * Reprogram the broadcast device:
    *
    * Called with tick_broadcast_lock held and interrupts disabled.
    */
    -static int tick_broadcast_reprogram(int force)
    +static int tick_broadcast_reprogram(void)
    {
    - struct clock_event_device *bc = tick_broadcast_device.evtdev;
    - ktime_t tmp, expires = { .tv64 = KTIME_MAX };
    + ktime_t expires = { .tv64 = KTIME_MAX };
    struct tick_device *td;
    - int cpu, res;
    + int cpu;

    /*
    * Find the event which expires next:
    @@ -319,13 +335,7 @@ static int tick_broadcast_reprogram(int
    if (expires.tv64 == KTIME_MAX)
    return 0;

    - for(;;) {
    - res = clockevents_program_event(bc, expires);
    - if (!res || !force)
    - return res;
    - tmp = ktime_set(0, bc->min_delta_ns << 1);
    - expires = ktime_add(ktime_get(), tmp);
    - }
    + return tick_broadcast_set_event(expires, 0);
    }

    /*
    @@ -333,14 +343,15 @@ static int tick_broadcast_reprogram(int
    */
    static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
    {
    - ktime_t now;
    struct tick_device *td;
    - cpumask_t mask = CPU_MASK_NONE;
    + cpumask_t mask;
    + ktime_t now;
    int cpu;

    spin_lock(&tick_broadcast_lock);
    -
    again:
    + dev->next_event.tv64 = KTIME_MAX;
    + mask = CPU_MASK_NONE;
    now = ktime_get();
    /* Find all expired events */
    for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
    @@ -360,7 +371,7 @@ again:
    * events. This happens in dyntick mode, as the
    * maximum PIT delta is quite small.
    */
    - if (tick_broadcast_reprogram(0))
    + if (tick_broadcast_reprogram())
    goto again;
    }
    spin_unlock(&tick_broadcast_lock);
    @@ -398,6 +409,8 @@ void tick_broadcast_oneshot_control(unsi
    if (!cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
    cpu_set(cpu, tick_broadcast_oneshot_mask);
    clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
    + if (dev->next_event.tv64 < bc->next_event.tv64)
    + tick_broadcast_set_event(dev->next_event, 1);
    }
    } else {
    if (cpu_isset(cpu, tick_broadcast_oneshot_mask)) {
    @@ -408,8 +421,6 @@ void tick_broadcast_oneshot_control(unsi
    }
    }

    - if (!cpus_empty(tick_broadcast_oneshot_mask))
    - tick_broadcast_reprogram(1);
    out:
    spin_unlock_irqrestore(&tick_broadcast_lock, flags);
    }
    @@ -422,6 +433,7 @@ void tick_broadcast_setup_oneshot(struct
    if (bc->mode != CLOCK_EVT_MODE_ONESHOT) {
    bc->event_handler = tick_handle_oneshot_broadcast;
    clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
    + bc->next_event.tv64 = KTIME_MAX;
    }
    }

    Index: linux-2.6.20/include/linux/clockchips.h
    ===================================================================
    --- linux-2.6.20.orig/include/linux/clockchips.h
    +++ linux-2.6.20/include/linux/clockchips.h
    @@ -128,7 +128,7 @@ extern void clockevents_set_mode(struct
    extern int clockevents_register_notifier(struct notifier_block *nb);
    extern void clockevents_unregister_notifier(struct notifier_block *nb);
    extern int clockevents_program_event(struct clock_event_device *dev,
    - ktime_t expires);
    + ktime_t expires, ktime_t now);

    extern void clockevents_notify(unsigned long reason, void *arg);

    Index: linux-2.6.20/kernel/time/tick-common.c
    ===================================================================
    --- linux-2.6.20.orig/kernel/time/tick-common.c
    +++ linux-2.6.20/kernel/time/tick-common.c
    @@ -89,7 +89,7 @@ void tick_handle_periodic(struct clock_e
    for (;;) {
    ktime_t next = ktime_add(dev->next_event, tick_period);

    - if (!clockevents_program_event(dev, next))
    + if (!clockevents_program_event(dev, next, ktime_get()))
    return;
    tick_periodic(cpu);
    }
    @@ -120,7 +120,7 @@ void tick_setup_periodic(struct clock_ev
    clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);

    for (;;) {
    - if (!clockevents_program_event(dev, next))
    + if (!clockevents_program_event(dev, next, ktime_get()))
    return;
    next = ktime_add(next, tick_period);
    }
    Index: linux-2.6.20/kernel/time/tick-oneshot.c
    ===================================================================
    --- linux-2.6.20.orig/kernel/time/tick-oneshot.c
    +++ linux-2.6.20/kernel/time/tick-oneshot.c
    @@ -28,14 +28,15 @@
    int tick_program_event(ktime_t expires, int force)
    {
    struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
    + ktime_t now = ktime_get();

    while (1) {
    - int ret = clockevents_program_event(dev, expires);
    + int ret = clockevents_program_event(dev, expires, now);

    if (!ret || !force)
    return ret;
    - expires = ktime_add(expires,
    - ktime_set(0, dev->min_delta_ns << 2));
    + now = ktime_get();
    + expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
    }
    }

    @@ -48,7 +49,7 @@ void tick_setup_oneshot(struct clock_eve
    {
    newdev->event_handler = handler;
    clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
    - clockevents_program_event(newdev, next_event);
    + clockevents_program_event(newdev, next_event, ktime_get());
    }

    /**
    Index: linux-2.6.20/kernel/time/tick-sched.c
    ===================================================================
    --- linux-2.6.20.orig/kernel/time/tick-sched.c
    +++ linux-2.6.20/kernel/time/tick-sched.c
    @@ -137,13 +137,15 @@ __setup("nohz=", setup_tick_nohz);
    */
    void tick_nohz_update_jiffies(void)
    {
    - struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
    + int cpu = smp_processor_id();
    + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
    unsigned long flags;
    ktime_t now;

    if (!ts->tick_stopped)
    return;

    + cpu_clear(cpu, nohz_cpu_mask);
    now = ktime_get();

    local_irq_save(flags);
    @@ -161,17 +163,24 @@ void tick_nohz_update_jiffies(void)
    void tick_nohz_stop_sched_tick(void)
    {
    unsigned long seq, last_jiffies, next_jiffies, delta_jiffies, flags;
    - struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
    + struct tick_sched *ts;
    ktime_t last_update, expires, now, delta;
    -
    - if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
    - return;
    + int cpu;

    local_irq_save(flags);

    + cpu = smp_processor_id();
    + ts = &per_cpu(tick_cpu_sched, cpu);
    +
    + if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
    + goto end;
    +
    if (need_resched())
    goto end;

    + cpu = smp_processor_id();
    + BUG_ON(local_softirq_pending());
    +
    now = ktime_get();
    /*
    * When called from irq_exit we need to account the idle sleep time
    @@ -196,12 +205,20 @@ void tick_nohz_stop_sched_tick(void)
    next_jiffies = get_next_timer_interrupt(last_jiffies);
    delta_jiffies = next_jiffies - last_jiffies;

    - /* Do not stop the tick, if we are only one off */
    - if (!ts->tick_stopped && delta_jiffies == 1)
    + /*
    + * Do not stop the tick, if we are only one off
    + * or if the cpu is required for rcu
    + */
    + if (!ts->tick_stopped && (delta_jiffies == 1 || rcu_needs_cpu(cpu)))
    goto out;

    /* Schedule the tick, if we are at least one jiffie off */
    if ((long)delta_jiffies >= 1) {
    +
    + if (rcu_needs_cpu(cpu))
    + delta_jiffies = 1;
    + else
    + cpu_set(cpu, nohz_cpu_mask);
    /*
    * nohz_stop_sched_tick can be called several times before
    * the nohz_restart_sched_tick is called. This happens when
    @@ -237,6 +254,7 @@ void tick_nohz_stop_sched_tick(void)
    * softirq.
    */
    tick_do_update_jiffies64(ktime_get());
    + cpu_clear(cpu, nohz_cpu_mask);
    }
    raise_softirq_irqoff(TIMER_SOFTIRQ);
    out:
    @@ -253,7 +271,8 @@ end:
    */
    void tick_nohz_restart_sched_tick(void)
    {
    - struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
    + int cpu = smp_processor_id();
    + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
    unsigned long ticks;
    ktime_t now, delta;

    @@ -265,6 +284,7 @@ void tick_nohz_restart_sched_tick(void)

    local_irq_disable();
    tick_do_update_jiffies64(now);
    + cpu_clear(cpu, nohz_cpu_mask);

    /* Account the idle time */
    delta = ktime_sub(now, ts->idle_entrytime);

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-02-07 00:19    [W:4.097 / U:0.276 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site