Commit 4143137c authored by Tim Schmielau's avatar Tim Schmielau Committed by Linus Torvalds

[PATCH] use 64 bit jiffies: fix utime wrap

Use 64 bit jiffies for reporting uptime.
parent 3da2fe13
......@@ -41,11 +41,13 @@
#include <linux/profile.h>
#include <linux/blkdev.h>
#include <linux/hugetlb.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/div64.h>
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
......@@ -98,34 +100,36 @@ static int loadavg_read_proc(char *page, char **start, off_t off,
static int uptime_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
unsigned long uptime;
unsigned long idle;
u64 uptime;
unsigned long uptime_remainder;
int len;
uptime = jiffies;
idle = init_task.utime + init_task.stime;
/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
that would overflow about every five days at HZ == 100.
Therefore the identity a = (a / b) * b + a % b is used so that it is
calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
The part in front of the '+' always evaluates as 0 (mod 100). All divisions
in the above formulas are truncating. For HZ being a power of 10, the
calculations simplify to the version in the #else part (if the printf
format is adapted to the same number of digits as zeroes in HZ.
*/
uptime = get_jiffies_64();
uptime_remainder = (unsigned long) do_div(uptime, HZ);
#if HZ!=100
len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
uptime / HZ,
(((uptime % HZ) * 100) / HZ) % 100,
idle / HZ,
(((idle % HZ) * 100) / HZ) % 100);
{
u64 idle = init_task.utime + init_task.stime;
unsigned long idle_remainder;
idle_remainder = (unsigned long) do_div(idle, HZ);
len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime,
(uptime_remainder * 100) / HZ,
(unsigned long) idle,
(idle_remainder * 100) / HZ);
}
#else
len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
uptime / HZ,
uptime % HZ,
idle / HZ,
idle % HZ);
{
unsigned long idle = init_task.times.tms_utime
+ init_task.times.tms_stime;
len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime,
uptime_remainder,
idle / HZ,
idle % HZ);
}
#endif
return proc_calc_metrics(page, start, off, count, eof, len);
}
......@@ -317,7 +321,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
{
int i, len;
extern unsigned long total_forks;
unsigned long jif = jiffies;
u64 jif = get_jiffies_64();
unsigned int sum = 0, user = 0, nice = 0, system = 0, idle = 0, iowait = 0;
for (i = 0 ; i < NR_CPUS; i++) {
......@@ -358,6 +362,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
len += sprintf(page + len, " %u", kstat_irqs(i));
#endif
do_div(jif, HZ);
len += sprintf(page + len,
"\nctxt %lu\n"
"btime %lu\n"
......@@ -365,7 +370,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
"procs_running %lu\n"
"procs_blocked %lu\n",
nr_context_switches(),
xtime.tv_sec - jif / HZ,
xtime.tv_sec - (unsigned long) jif,
total_forks,
nr_running(),
nr_iowait());
......
......@@ -26,8 +26,10 @@
#include <linux/mm.h>
#include <linux/notifier.h>
#include <linux/thread_info.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
/*
* per-CPU timer vector definitions:
......@@ -1085,13 +1087,16 @@ asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
asmlinkage long sys_sysinfo(struct sysinfo *info)
{
struct sysinfo val;
u64 uptime;
unsigned long mem_total, sav_total;
unsigned int mem_unit, bitcount;
memset((char *)&val, 0, sizeof(struct sysinfo));
read_lock_irq(&xtime_lock);
val.uptime = jiffies / HZ;
uptime = jiffies_64;
do_div(uptime, HZ);
val.uptime = (unsigned long) uptime;
val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment