Re: [PATCH (update 4)] timer: Run calc_load halfway through eachround_jiffies second

From: Simon Arlott
Date: Tue Mar 06 2007 - 13:43:59 EST


On 05/03/07 22:35, Simon Arlott wrote:
On 01/01/02 03:05, Pavel Machek wrote:
This changes calc_load so that it updates load half a second after any tasks scheduled using round_jiffies.

Hmm, otoh this makes calc_load more expensive, power-wise, because it
needs to wake the cpu once more?

I suddenly realised that since calc_load was already being called at second + 1 tick, moving it back 1 tick should mean it gets called and allowed to finish before the other tasks:

[ 1392.745730] cxacru_poll_status jiffies=1064000 [start]
[ 1392.765628] cxacru_poll_status jiffies=1064020 [finish]
[ 1393.745284] calc_load(1) jiffies=1065000 count=5000 count=5000
[ 1393.745320] cxacru_poll_status jiffies=1065000 [start]
[ 1393.754412] cxacru_poll_status jiffies=1065009 [finish]

How will this work in the presence of multiple CPUs? Will the scheduled task be run on another CPU while calc_load is run? I don't have anything I can test it on.

However since 5*HZ is unlikely to be a factor of 2^32, as soon as jiffies wraps a second time it will no longer be in sync:

HZ=100 0 (time after jiffies wrap that calc_load will be run)
HZ=100 4
HZ=100 8
HZ=100 12
HZ=100 16
...

It takes 3.2 *years* (increasing 40ms each time) at HZ=100 before it's back in sync. This would be ok for my task which is unlikely to ever take 40ms or more to complete, but could still hit other tasks.

HZ=1000 0
HZ=1000 704
HZ=1000 408
HZ=1000 112
HZ=1000 816
...

It takes 16.9 years (jumping around, only <=40ms 4 times) at HZ=1000 before it's back in sync.

Since calc_load is now running on the second already and this is preferable to different times during a second than other tasks, it can be rounded more easily than before:

kernel/timer.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/kernel/timer.c b/kernel/timer.c
index 6663a87..4abead0 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1226,17 +1226,19 @@ EXPORT_SYMBOL(avenrun);
static inline void calc_load(unsigned long ticks)
{
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;

count -= ticks;
- if (unlikely(count < 0)) {
+ if (unlikely(count <= 0)) {
active_tasks = count_active_tasks();
do {
CALC_LOAD(avenrun[0], EXP_1, active_tasks);
CALC_LOAD(avenrun[1], EXP_5, active_tasks);
CALC_LOAD(avenrun[2], EXP_15, active_tasks);
count += LOAD_FREQ;
- } while (count < 0);
+ } while (count <= 0);
+
+ count = round_jiffies_relative(count);
}
}


--
Simon Arlott
-
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/