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 @@ ...@@ -41,11 +41,13 @@
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/div64.h>
#define LOAD_INT(x) ((x) >> FSHIFT) #define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) #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, ...@@ -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, static int uptime_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
unsigned long uptime; u64 uptime;
unsigned long idle; unsigned long uptime_remainder;
int len; int len;
uptime = jiffies; uptime = get_jiffies_64();
idle = init_task.utime + init_task.stime; uptime_remainder = (unsigned long) do_div(uptime, HZ);
/* 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.
*/
#if HZ!=100 #if HZ!=100
len = sprintf(page,"%lu.%02lu %lu.%02lu\n", {
uptime / HZ, u64 idle = init_task.utime + init_task.stime;
(((uptime % HZ) * 100) / HZ) % 100, unsigned long idle_remainder;
idle / HZ,
(((idle % HZ) * 100) / HZ) % 100); 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 #else
len = sprintf(page,"%lu.%02lu %lu.%02lu\n", {
uptime / HZ, unsigned long idle = init_task.times.tms_utime
uptime % HZ, + init_task.times.tms_stime;
idle / HZ,
idle % HZ); len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime,
uptime_remainder,
idle / HZ,
idle % HZ);
}
#endif #endif
return proc_calc_metrics(page, start, off, count, eof, len); 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, ...@@ -317,7 +321,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
{ {
int i, len; int i, len;
extern unsigned long total_forks; 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; unsigned int sum = 0, user = 0, nice = 0, system = 0, idle = 0, iowait = 0;
for (i = 0 ; i < NR_CPUS; i++) { for (i = 0 ; i < NR_CPUS; i++) {
...@@ -358,6 +362,7 @@ static int kstat_read_proc(char *page, char **start, off_t off, ...@@ -358,6 +362,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
len += sprintf(page + len, " %u", kstat_irqs(i)); len += sprintf(page + len, " %u", kstat_irqs(i));
#endif #endif
do_div(jif, HZ);
len += sprintf(page + len, len += sprintf(page + len,
"\nctxt %lu\n" "\nctxt %lu\n"
"btime %lu\n" "btime %lu\n"
...@@ -365,7 +370,7 @@ static int kstat_read_proc(char *page, char **start, off_t off, ...@@ -365,7 +370,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
"procs_running %lu\n" "procs_running %lu\n"
"procs_blocked %lu\n", "procs_blocked %lu\n",
nr_context_switches(), nr_context_switches(),
xtime.tv_sec - jif / HZ, xtime.tv_sec - (unsigned long) jif,
total_forks, total_forks,
nr_running(), nr_running(),
nr_iowait()); nr_iowait());
......
...@@ -26,8 +26,10 @@ ...@@ -26,8 +26,10 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/div64.h>
/* /*
* per-CPU timer vector definitions: * per-CPU timer vector definitions:
...@@ -1085,13 +1087,16 @@ asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp) ...@@ -1085,13 +1087,16 @@ asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
asmlinkage long sys_sysinfo(struct sysinfo *info) asmlinkage long sys_sysinfo(struct sysinfo *info)
{ {
struct sysinfo val; struct sysinfo val;
u64 uptime;
unsigned long mem_total, sav_total; unsigned long mem_total, sav_total;
unsigned int mem_unit, bitcount; unsigned int mem_unit, bitcount;
memset((char *)&val, 0, sizeof(struct sysinfo)); memset((char *)&val, 0, sizeof(struct sysinfo));
read_lock_irq(&xtime_lock); 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[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
val.loads[1] = avenrun[1] << (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