On Thu, Dec 14, 2017 at 06:47:02PM -0600, Scott Cheloha wrote: > Hi, > > Attached is a diff adding a new clockid, CLOCK_BOOTTIME, for use with > clock_gettime(2). The value of CLOCK_BOOTTIME is the time elapsed > since the system booted, i.e. the system uptime. The diff puts it to > use in top(1), w(1), and snmpd(8). > > CLOCK_BOOTTIME originated in Linux in the 2.6.39 kernel [1, 2]. > > The base motivation for adding CLOCK_BOOTTIME to OpenBSD is that there > is currently no direct interface for userland to query the system > uptime, i.e., the time elapsed since the machine was last (re)booted. > > We have several callers using the kern.boottime sysctl, but all of > them immediately subtract the result from the current time of day to > derive the system uptime. This is is (a) cumbersome, and (b) involves > a race with settimeofday(2), etc. > > We could add a new sysctl, but sysctl(3) itself is cumbersome, > especially when compared to clock_gettime(2). > > Although CLOCK_MONOTONIC is currently implemented with nanouptime(9) > and is thus an interface to the system uptime, this is only coincidentally > so. The standard notes that the value returned by CLOCK_MONOTONIC is > meaningless in isolation: it is only portably useful for interval > measurement. Overloading CLOCK_MONOTONIC as an interface to the system > uptime would confuse the purpose of the clock, promote the creation of non- > portable code, and prevent us from changing the clock's implementation > in the future. > > On top of enriching base with a nice interface to the system uptime, > this diff also makes CLOCK_BOOTTIME available to ports with the same > semantics it has in Linux. CLOCK_BOOTTIME has been available in Linux > for over five years, so there are almost certainly ports that can make > use of it. > > The diff in its current form is the result of discussion and revision > with guenther@, jca@, and tb@. All gave their ok. > > Thoughts and feedback? >
No objections, you can add me to the ok list... -ml > -- > Scott Cheloha > > [1] https://marc.info/?l=linux-kernel&m=129783004314557&w=2 > [2] > https://github.com/torvalds/linux/commit/420c1c572d4ceaa2f37b6311b7017ac6cf049fe2 > > Index: lib/libc/sys/clock_gettime.2 > =================================================================== > RCS file: /cvs/src/lib/libc/sys/clock_gettime.2,v > retrieving revision 1.27 > diff -u -p -r1.27 clock_gettime.2 > --- lib/libc/sys/clock_gettime.2 10 Sep 2015 17:55:21 -0000 1.27 > +++ lib/libc/sys/clock_gettime.2 15 Dec 2017 00:43:29 -0000 > @@ -73,6 +73,9 @@ time that increments as a wall clock sho > is meaningless and cannot jump, > providing accurate realtime interval measurement, > even across suspend and resume > +.It Dv CLOCK_BOOTTIME > +time whose absolute value is the time that has elapsed since the > +system was booted > .It Dv CLOCK_UPTIME > time whose absolute value is the time the system has been running > and not suspended, > @@ -157,8 +160,10 @@ functions conform to > .St -p1003.1-2008 . > .Pp > The > +.Dv CLOCK_BOOTTIME > +and > .Dv CLOCK_UPTIME > -clock is an extension to that. > +clocks are extensions to that. > .Sh HISTORY > The > .Dv CLOCK_PROCESS_CPUTIME_ID > @@ -174,3 +179,11 @@ and was added to > .Ox > in > .Ox 5.5 . > +The > +.Dv CLOCK_BOOTTIME > +clock first appeared in > +Linux 2.6.39 > +and was added to > +.Ox > +in > +.Ox 6.3 . > Index: sys/kern/kern_time.c > =================================================================== > RCS file: /cvs/src/sys/kern/kern_time.c,v > retrieving revision 1.99 > diff -u -p -r1.99 kern_time.c > --- sys/kern/kern_time.c 24 Jan 2017 00:58:55 -0000 1.99 > +++ sys/kern/kern_time.c 15 Dec 2017 00:43:29 -0000 > @@ -124,6 +124,7 @@ clock_gettime(struct proc *p, clockid_t > bintime2timespec(&bt, tp); > break; > case CLOCK_MONOTONIC: > + case CLOCK_BOOTTIME: > nanouptime(tp); > break; > case CLOCK_PROCESS_CPUTIME_ID: > @@ -223,6 +224,7 @@ sys_clock_getres(struct proc *p, void *v > switch (clock_id) { > case CLOCK_REALTIME: > case CLOCK_MONOTONIC: > + case CLOCK_BOOTTIME: > case CLOCK_UPTIME: > case CLOCK_PROCESS_CPUTIME_ID: > case CLOCK_THREAD_CPUTIME_ID: > Index: sys/sys/_time.h > =================================================================== > RCS file: /cvs/src/sys/sys/_time.h,v > retrieving revision 1.8 > diff -u -p -r1.8 _time.h > --- sys/sys/_time.h 3 Sep 2016 15:06:06 -0000 1.8 > +++ sys/sys/_time.h 15 Dec 2017 00:43:29 -0000 > @@ -37,6 +37,7 @@ > #define CLOCK_MONOTONIC 3 > #define CLOCK_THREAD_CPUTIME_ID 4 > #define CLOCK_UPTIME 5 > +#define CLOCK_BOOTTIME 6 > > #if __BSD_VISIBLE > /* > Index: usr.bin/w/w.c > =================================================================== > RCS file: /cvs/src/usr.bin/w/w.c,v > retrieving revision 1.64 > diff -u -p -r1.64 w.c > --- usr.bin/w/w.c 14 Dec 2017 18:03:03 -0000 1.64 > +++ usr.bin/w/w.c 15 Dec 2017 00:43:29 -0000 > @@ -66,7 +66,6 @@ > > #include "extern.h" > > -struct timeval boottime; > struct utmp utmp; > struct winsize ws; > kvm_t *kd; > @@ -426,10 +425,9 @@ static void > pr_header(time_t *nowp, int nusers) > { > double avenrun[3]; > + struct timespec boottime; > time_t uptime; > int days, hrs, i, mins; > - int mib[2]; > - size_t size; > char buf[256]; > > /* > @@ -441,13 +439,9 @@ pr_header(time_t *nowp, int nusers) > > /* > * Print how long system has been up. > - * (Found by getting "boottime" from the kernel) > */ > - mib[0] = CTL_KERN; > - mib[1] = KERN_BOOTTIME; > - size = sizeof(boottime); > - if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) { > - uptime = now - boottime.tv_sec; > + if (clock_gettime(CLOCK_BOOTTIME, &boottime) != -1) { > + uptime = boottime.tv_sec; > if (uptime > 59) { > uptime += 30; > days = uptime / SECSPERDAY; > Index: usr.bin/top/display.c > =================================================================== > RCS file: /cvs/src/usr.bin/top/display.c,v > retrieving revision 1.52 > diff -u -p -r1.52 display.c > --- usr.bin/top/display.c 15 Mar 2017 04:24:14 -0000 1.52 > +++ usr.bin/top/display.c 15 Dec 2017 00:43:29 -0000 > @@ -57,7 +57,6 @@ > #include <stdlib.h> > #include <string.h> > #include <unistd.h> > -#include <sys/sysctl.h> > > #include "screen.h" /* interface to screen package */ > #include "layout.h" /* defines for screen position layout */ > @@ -209,22 +208,15 @@ display_init(struct statics * statics) > static void > format_uptime(char *buf, size_t buflen) > { > - time_t now, uptime; > + time_t uptime; > int days, hrs, mins; > - int mib[2]; > - size_t size; > - struct timeval boottime; > + struct timespec boottime; > > - now = time(NULL); > /* > * Print how long system has been up. > - * (Found by getting "boottime" from the kernel) > */ > - mib[0] = CTL_KERN; > - mib[1] = KERN_BOOTTIME; > - size = sizeof(boottime); > - if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) { > - uptime = now - boottime.tv_sec; > + if (clock_gettime(CLOCK_BOOTTIME, &boottime) != -1) { > + uptime = boottime.tv_sec; > uptime += 30; > days = uptime / (3600 * 24); > uptime %= (3600 * 24); > Index: usr.sbin/snmpd/mib.c > =================================================================== > RCS file: /cvs/src/usr.sbin/snmpd/mib.c,v > retrieving revision 1.84 > diff -u -p -r1.84 mib.c > --- usr.sbin/snmpd/mib.c 1 Jun 2017 14:38:28 -0000 1.84 > +++ usr.sbin/snmpd/mib.c 15 Dec 2017 00:43:29 -0000 > @@ -451,18 +451,13 @@ static struct oid hr_mib[] = { > int > mib_hrsystemuptime(struct oid *oid, struct ber_oid *o, struct ber_element > **elm) > { > - struct timeval boottime; > - int mib[] = { CTL_KERN, KERN_BOOTTIME }; > - time_t now; > - size_t len; > + struct timespec uptime; > + long long ticks; > > - (void)time(&now); > - len = sizeof(boottime); > - > - if (sysctl(mib, 2, &boottime, &len, NULL, 0) == -1) > + if (clock_gettime(CLOCK_BOOTTIME, &uptime) == -1) > return (-1); > - > - *elm = ber_add_integer(*elm, (now - boottime.tv_sec) * 100); > + ticks = uptime.tv_sec * 100 + uptime.tv_nsec / 10000000; > + *elm = ber_add_integer(*elm, ticks); > ber_set_header(*elm, BER_CLASS_APPLICATION, SNMP_T_TIMETICKS); > > return (0); >
