Re: FIX top [was Re: strange idle%]

Albert D. Cahalan (acahalan@cs.uml.edu)
Thu, 13 May 1999 14:45:49 -0400 (EDT)


Pavel Machek writes:

>> I was running top, and I noticed a very odd idle% pop up from time to time:
>>
>> 11:03am up 11:04, 1 user, load average: 2.00, 2.00, 2.00
>> 36 processes: 32 sleeping, 4 running, 0 zombie, 0 stopped
>> CPU states: 0.4% user, 0.1% system, 99.4% nice, 428639.3% idle
>> ^^^^^^^^^
>> I'm running the rc5des client on both cpu's of my dual PII running 2.2.7.
>> Nothing bad has happened, but I'm curious as to whether this might be an
>> overflow in whatever file in /proc top get's its info from...
>
> Fix top. Top really lies about % idle: it computes it as 100-(%'s of
> processes it sees). That's WRONG.

Damn WRONG in fact, since top doesn't use that method anymore.

> % idle should be get from % of idle
> process. Then, 100-(sum) could be reported as % unknown. Yes, %unknown
> happen: if gcc exits just before top runs, you have %'s for
> non-existent process and top does not see that %'s. It currently adds
> it to %idle which is wrong.

That is interesting, but also bad. There is simply no way for top to
atomically read all of /proc, so you still get odd numbers.

The current code is below. Feel free to improve it.

---------

This function determines how CPU ticks were used since it was last called.
It returns crummy data the first time it is called, but that isn't as
annoying as the old method.

#define JT unsigned long
int four_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret) {
static JT u, n, s, i;
JT user_j, nice_j, sys_j, idle_j;

FILE_TO_BUF(STAT_FILE,stat_fd);
sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &idle_j);
SET_IF_DESIRED(uret, user_j-u);
SET_IF_DESIRED(nret, nice_j-n);
SET_IF_DESIRED(sret, sys_j-s);
SET_IF_DESIRED(iret, idle_j-i);
u=user_j;
n=nice_j;
s=sys_j;
i=idle_j;
return 0;
}
#undef JT

-----------

This bit of code prints out the values.

four_cpu_numbers(&user_ticks,&nice_ticks,&system_ticks,&idle_ticks);
do{
unsigned long sum;
sum = user_ticks+nice_ticks+system_ticks+idle_ticks;
user_ticks = (user_ticks * 1000) / sum;
system_ticks = (system_ticks * 1000) / sum;
nice_ticks = (nice_ticks * 1000) / sum;
idle_ticks = (idle_ticks * 1000) / sum;
}while(0);
printf("CPU states:"
" %2ld.%ld%% user, %2ld.%ld%% system,"
" %2ld.%ld%% nice, %2ld.%ld%% idle",
user_ticks / 10UL, user_ticks % 10UL,
system_ticks / 10UL, system_ticks % 10UL,
nice_ticks / 10UL, nice_ticks % 10UL,
idle_ticks / 10UL, idle_ticks % 10UL
);

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