[PATCH 2/3] posix_timers: Defer per process timer stop after timers processing

From: Frederic Weisbecker
Date: Thu Apr 18 2013 - 13:24:51 EST


When we process the posix cpu timers from the tick, we run through
two passes:

1) get the timers that want to fire and walk through the remaining
ones in order to set the next expiry time.

2) execute the firing timers and possibly reschedule some of them and
thus update the next expiry time again.

If there are no more timers in the queue after the firing ones in the
first pass, we may call stop_process_timers() there. If some firing
timers are rescheduled in the second pass, this leaves a tiny frame
where it is considered we have no process timers running, while we
are going to re-enqueue some.

This is a problem if there are full dynticks CPUs around. Having posix CPU
timers running is one of the reasons for full dynticks CPU to
prevent from stopping their tick. If they see this tiny frame clear of
timers by verifying that sig->cputimer.running == 0, they may stop their tick.

One solution would be to send these CPUs a notification if we re-enqueue
timers in the second pass so that they restart their tick accordingly. But
it looks like a hammer.

The other solution is to defer the call to stop_process_timers() after
the second pass once we are really sure that no more timers are in the queue
by the very end of the posix cpu timers processing.

This perhaps implies a little more contention against threadgroup lock and
sig->cputimer.lock if some other CPUs are concurrently checking the process
timers while we are executing those that fired. But this is probably not a big
issue in practice.

Signed-off-by: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Cc: Chris Metcalf <cmetcalf@xxxxxxxxxx>
Cc: Christoph Lameter <cl@xxxxxxxxx>
Cc: Geoff Levand <geoff@xxxxxxxxxxxxx>
Cc: Gilad Ben Yossef <gilad@xxxxxxxxxxxxx>
Cc: Hakan Akkan <hakanakkan@xxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Kevin Hilman <khilman@xxxxxxxxxx>
Cc: Li Zhong <zhong@xxxxxxxxxxxxxxxxxx>
Cc: Oleg Nesterov <oleg@xxxxxxxxxx>
Cc: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>
Cc: Paul Gortmaker <paul.gortmaker@xxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Steven Rostedt <rostedt@xxxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
kernel/posix-cpu-timers.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 8fd709c..3b73ae8 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1130,8 +1130,6 @@ static void check_process_timers(struct task_struct *tsk,
sig->cputime_expires.prof_exp = prof_expires;
sig->cputime_expires.virt_exp = virt_expires;
sig->cputime_expires.sched_exp = sched_expires;
- if (task_cputime_zero(&sig->cputime_expires))
- stop_process_timers(sig);
}

/*
@@ -1279,6 +1277,7 @@ void run_posix_cpu_timers(struct task_struct *tsk)
LIST_HEAD(firing);
struct k_itimer *timer, *next;
unsigned long flags;
+ struct signal_struct *sig;

BUG_ON(!irqs_disabled());

@@ -1336,6 +1335,10 @@ void run_posix_cpu_timers(struct task_struct *tsk)
cpu_timer_fire(timer);
spin_unlock(&timer->it_lock);
}
+
+ sig = tsk->signal;
+ if (task_cputime_zero(&sig->cputime_expires))
+ stop_process_timers(sig);
}

/*
--
1.7.5.4

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