util-linux/lib/monotonic.c
Konstantin Khlebnikov 9bf622dad9 dmesg: adjust timestamps according to suspended time
Timestamps in kernel log comes from monotonic clocksource which does not
tick when system suspended. Suspended time easily sums into hours and days
rendering human readable timestamps in dmesg useless.

Adjusting timestamps accouring to current delta between boottime and
monotonic clocksources produces accurate timestamps for messages printed
since last resume. Which are supposed to be most interesting.

Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
2020-06-04 10:57:36 +02:00

82 lines
1.6 KiB
C

/*
* Please, don't add this file to libcommon because clock_gettime() requires
* -lrt on systems with old libc.
*
* No copyright is claimed. This code is in the public domain; do with
* it what you wish.
*/
#include <time.h>
#include <signal.h>
#ifdef HAVE_SYSINFO
#include <sys/sysinfo.h>
#endif
#include <sys/time.h>
#include "c.h"
#include "monotonic.h"
int get_boot_time(struct timeval *boot_time)
{
#ifdef CLOCK_BOOTTIME
struct timespec hires_uptime;
struct timeval lores_uptime;
#endif
struct timeval now;
#ifdef HAVE_SYSINFO
struct sysinfo info;
#endif
if (gettimeofday(&now, NULL) != 0)
return -errno;
#ifdef CLOCK_BOOTTIME
if (clock_gettime(CLOCK_BOOTTIME, &hires_uptime) == 0) {
TIMESPEC_TO_TIMEVAL(&lores_uptime, &hires_uptime);
timersub(&now, &lores_uptime, boot_time);
return 0;
}
#endif
#ifdef HAVE_SYSINFO
/* fallback */
if (sysinfo(&info) != 0)
return -errno;
boot_time->tv_sec = now.tv_sec - info.uptime;
boot_time->tv_usec = 0;
return 0;
#else
return -ENOSYS;
#endif
}
time_t get_suspended_time(void)
{
#if defined(CLOCK_BOOTTIME) && defined(CLOCK_MONOTONIC)
struct timespec boot, mono;
if (clock_gettime(CLOCK_BOOTTIME, &boot) == 0 &&
clock_gettime(CLOCK_MONOTONIC, &mono) == 0)
return boot.tv_sec - mono.tv_sec;
#endif
return 0;
}
int gettime_monotonic(struct timeval *tv)
{
#ifdef CLOCK_MONOTONIC
/* Can slew only by ntp and adjtime */
int ret;
struct timespec ts;
/* Linux specific, can't slew */
if (!(ret = clock_gettime(UL_CLOCK_MONOTONIC, &ts))) {
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
}
return ret;
#else
return gettimeofday(tv, NULL);
#endif
}