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

Simon Arlott
2007-03-06T18:43:22Z

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