bootchart: don't parse /proc/uptime, use CLOCK_BOOTTIME
* systemd-bootchart always parses /proc/uptime, although the information is unnecessary when --rel specified * use /proc/uptime is overkill, since Linux 2.6.39 we have clock_gettime(CLOCK_BOOTTIME, ...). The backend on kernel side is get_monotonic_boottime() in both cases. * main() uses "if (graph_start <= 0.0)" to detect that /proc is available. This is fragile solution as graph_start is always smaller than zero on all systems after suspend/resume (e.g. laptops), because in this case the system uptime includes suspend time and uptime is always greater number than monotonic time. For example right now difference between uptime and monotonic time is 37 hours on my laptop. Note that main() calls log_uptime() (to parse /proc/uptime) for each sample when it believes that /proc is not available. So on my laptop systemd-boochars spends all live with /proc/uptime parsing + nanosleep(), try strace /usr/lib/systemd/systemd-bootchart to see the never ending loop. This patch uses access("/proc/vmstat", F_OK) to detect procfs.
This commit is contained in:
parent
799a8f39d8
commit
c358d728e7
|
@ -131,7 +131,9 @@
|
|||
not graph the time elapsed since boot
|
||||
and before systemd-bootchart was
|
||||
started, as it may result in extremely
|
||||
large graphs. </para></listitem>
|
||||
large graphs. The time elapsed since boot
|
||||
might also include any time that the system
|
||||
was suspended.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
|
|
@ -310,6 +310,7 @@ int main(int argc, char *argv[]) {
|
|||
time_t t = 0;
|
||||
int r;
|
||||
struct rlimit rlim;
|
||||
bool has_procfs = false;
|
||||
|
||||
parse_conf();
|
||||
|
||||
|
@ -349,6 +350,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
log_uptime();
|
||||
|
||||
has_procfs = access("/proc/vmstat", F_OK) == 0;
|
||||
|
||||
LIST_HEAD_INIT(head);
|
||||
|
||||
/* main program loop */
|
||||
|
@ -385,11 +388,11 @@ int main(int argc, char *argv[]) {
|
|||
parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &build, NULL);
|
||||
}
|
||||
|
||||
/* wait for /proc to become available, discarding samples */
|
||||
if (graph_start <= 0.0)
|
||||
log_uptime();
|
||||
else
|
||||
if (has_procfs)
|
||||
log_sample(samples, &sampledata);
|
||||
else
|
||||
/* wait for /proc to become available, discarding samples */
|
||||
has_procfs = access("/proc/vmstat", F_OK) == 0;
|
||||
|
||||
sample_stop = gettime_ns();
|
||||
|
||||
|
|
|
@ -57,27 +57,22 @@ double gettime_ns(void) {
|
|||
return (n.tv_sec + (n.tv_nsec / 1000000000.0));
|
||||
}
|
||||
|
||||
static double gettime_up(void) {
|
||||
struct timespec n;
|
||||
|
||||
clock_gettime(CLOCK_BOOTTIME, &n);
|
||||
return (n.tv_sec + (n.tv_nsec / 1000000000.0));
|
||||
}
|
||||
|
||||
void log_uptime(void) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
char str[32];
|
||||
double uptime;
|
||||
|
||||
f = fopen("/proc/uptime", "re");
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
if (!fscanf(f, "%s %*s", str))
|
||||
return;
|
||||
|
||||
uptime = strtod(str, NULL);
|
||||
|
||||
log_start = gettime_ns();
|
||||
|
||||
/* start graph at kernel boot time */
|
||||
if (arg_relative)
|
||||
graph_start = log_start;
|
||||
else
|
||||
graph_start = log_start = gettime_ns();
|
||||
else {
|
||||
double uptime = gettime_up();
|
||||
|
||||
log_start = gettime_ns();
|
||||
graph_start = log_start - uptime;
|
||||
}
|
||||
}
|
||||
|
||||
static char *bufgetline(char *buf) {
|
||||
|
|
Loading…
Reference in New Issue