123 lines
4.3 KiB
Diff
123 lines
4.3 KiB
Diff
Read the time of system boot from /proc/stat (entry: btime) instead
|
|
of computing it as the difference between the current time and the
|
|
uptime. This is the only way to get a consistent result which won't
|
|
possibly change from one run to the next.
|
|
|
|
The problems with the original code were:
|
|
* Both the current time and the uptime are rounded down to the second,
|
|
but the system doesn't boot on an integer second value so they do not
|
|
tick at the same moment. Thus, the rounding errors can cause a one
|
|
second difference from one run to the next.
|
|
* We can't read the uptime and the current time at the exact same moment
|
|
anyway, so the time difference we compute is bound to be inaccurate.
|
|
|
|
Signed-off-by: Jean Delvare <jdelvare@suse.de>
|
|
---
|
|
proc/sysinfo.c | 26 ++++++++++++++++++++++++++
|
|
proc/sysinfo.h | 1 +
|
|
ps/output.c | 2 +-
|
|
3 files changed, 28 insertions(+), 1 deletion(-)
|
|
|
|
--- procps-3.2.7/proc/sysinfo.c
|
|
+++ procps-3.2.7/proc/sysinfo.c 2007-08-31 11:55:32.000000000 +0000
|
|
@@ -90,6 +90,35 @@ int uptime(double *restrict uptime_secs,
|
|
return up; /* assume never be zero seconds in practice */
|
|
}
|
|
|
|
+unsigned long getbtime(void) {
|
|
+ static unsigned long btime = 0;
|
|
+ FILE *f;
|
|
+
|
|
+ if (btime)
|
|
+ return btime;
|
|
+
|
|
+ /* /proc/stat can get very large on multi-CPU systems so we
|
|
+ can't use FILE_TO_BUF */
|
|
+ if (!(f = fopen(STAT_FILE, "r"))) {
|
|
+ fputs(BAD_OPEN_MESSAGE, stderr);
|
|
+ fflush(NULL);
|
|
+ _exit(102);
|
|
+ }
|
|
+
|
|
+ while ((fgets(buf, sizeof buf, f))) {
|
|
+ if (sscanf(buf, "btime %lu", &btime) == 1)
|
|
+ break;
|
|
+ }
|
|
+ fclose(f);
|
|
+
|
|
+ if (!btime) {
|
|
+ fputs("missing btime in " STAT_FILE "\n", stderr);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ return btime;
|
|
+}
|
|
+
|
|
/***********************************************************************
|
|
* Some values in /proc are expressed in units of 1/HZ seconds, where HZ
|
|
* is the kernel clock tick rate. One of these units is called a jiffy.
|
|
--- procps-3.2.7/proc/sysinfo.h
|
|
+++ procps-3.2.7/proc/sysinfo.h 2007-08-31 08:18:58.000000000 +0000
|
|
@@ -17,6 +17,7 @@ extern void eight_cpu_numbers(JT *uret,
|
|
#endif
|
|
|
|
extern int uptime (double *uptime_secs, double *idle_secs);
|
|
+extern unsigned long getbtime(void);
|
|
extern void loadavg(double *av1, double *av5, double *av15);
|
|
|
|
|
|
--- procps-3.2.7/ps/output.c
|
|
+++ procps-3.2.7/ps/output.c 2010-09-07 16:31:59.776958123 +0000
|
|
@@ -77,7 +77,6 @@ static unsigned max_leftward = 0x1234567
|
|
static int wide_signals; /* true if we have room */
|
|
|
|
static unsigned long seconds_since_1970;
|
|
-static unsigned long time_of_boot;
|
|
static unsigned long page_shift;
|
|
|
|
|
|
@@ -793,7 +792,7 @@ static int pr_bsdtime(char *restrict con
|
|
static int pr_bsdstart(char *restrict const outbuf, const proc_t *restrict const pp){
|
|
time_t start;
|
|
time_t seconds_ago;
|
|
- start = time_of_boot + pp->start_time / Hertz;
|
|
+ start = getbtime() + pp->start_time / Hertz;
|
|
seconds_ago = seconds_since_1970 - start;
|
|
if(seconds_ago < 0) seconds_ago=0;
|
|
if(seconds_ago > 3600*24) strcpy(outbuf, ctime(&start)+4);
|
|
@@ -907,7 +906,7 @@ static int pr_pmem(char *restrict const
|
|
|
|
static int pr_lstart(char *restrict const outbuf, const proc_t *restrict const pp){
|
|
time_t t;
|
|
- t = time_of_boot + pp->start_time / Hertz;
|
|
+ t = getbtime() + pp->start_time / Hertz;
|
|
return snprintf(outbuf, COLWID, "%24.24s", ctime(&t));
|
|
}
|
|
|
|
@@ -930,7 +929,7 @@ static int pr_stime(char *restrict const
|
|
our_time = localtime(&seconds_since_1970); /* not reentrant */
|
|
tm_year = our_time->tm_year;
|
|
tm_yday = our_time->tm_yday;
|
|
- t = time_of_boot + pp->start_time / Hertz;
|
|
+ t = getbtime() + pp->start_time / Hertz;
|
|
proc_time = localtime(&t); /* not reentrant, this corrupts our_time */
|
|
fmt = "%H:%M"; /* 03:02 23:59 */
|
|
if(tm_yday != proc_time->tm_yday) fmt = "%b%d"; /* Jun06 Aug27 */
|
|
@@ -941,7 +940,7 @@ static int pr_stime(char *restrict const
|
|
static int pr_start(char *restrict const outbuf, const proc_t *restrict const pp){
|
|
time_t t;
|
|
char *str;
|
|
- t = time_of_boot + pp->start_time / Hertz;
|
|
+ t = getbtime() + pp->start_time / Hertz;
|
|
str = ctime(&t);
|
|
if(str[8]==' ') str[8]='0';
|
|
if(str[11]==' ') str[11]='0';
|
|
@@ -1961,7 +1960,6 @@ void init_output(void){
|
|
// available space: page_size*outbuf_pages-SPACE_AMOUNT
|
|
|
|
seconds_since_1970 = time(NULL);
|
|
- time_of_boot = seconds_since_1970 - seconds_since_boot;
|
|
|
|
meminfo();
|
|
|