Subject: Implementation of CLOCK_MONOTONIC (was: mono_time exported? ...)
To: Tad Hunt <tad@entrisphere.com>
From: Simon Burge <simonb@wasabisystems.com>
List: tech-kern
Date: 01/27/2002 01:00:32
Jason R Thorpe wrote:
> On Sat, Jan 26, 2002 at 02:29:32PM +1100, Simon Burge wrote:
>
> > I'd suggest either adding a gethrtime() syscall (ala solaris and
> > possibly other SVR4-type OS's), or (probably better) adding a
> > CLOCK_MONOTIME or CLOCK_MONOTONIC for clock_{getres,gettime,settime}(2)
> > to use. If we do the latter, we can easily do gethrtime() as a libc
> > function that calls clock_gettime() with the right arguments.
>
> ...but make sure clock_settime() doesn't actually do anything in the
> MONOTIME case :-)
Heh. Ok :)
Below is a diff that implements a CLOCK_MONOTONIC for the clock_*(2)
calls. FWIW, the real time on my pc164 has drifted about 5 seconds
faster that the monotonic time over an uptime about about 2 hours:
real time: 1012053364.318731000
mono mono: 1012053359.322848000
I will note that the kernel mono_time variable strickly speaking
doesn't increase monotonically - the "BUMPTIME(&mono_time, delta);" in
kern_clock.c occurs _after_ delta has been adjusted after any possible
adjtime() adjustments have occurred.
If I get no (reasonable!) complaints, I'll commit this in a couple of
days. At this stage, I see no need for a gethrtime() call. Comments
on that?
Simon.
--
Simon Burge <simonb@wasabisystems.com>
NetBSD CDs, Support and Service: http://www.wasabisystems.com/
Index: lib/libc/sys/clock_settime.2
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/sys/clock_settime.2,v
retrieving revision 1.9
diff -d -p -u -r1.9 clock_settime.2
--- lib/libc/sys/clock_settime.2 2001/10/16 16:08:55 1.9
+++ lib/libc/sys/clock_settime.2 2002/01/26 13:40:28
@@ -95,6 +95,23 @@ and obtained by
represent the amount of time (in seconds and nanoseconds)
since 00:00 Universal Coordinated Time, January 1, 1970.
.Pp
+A
+.Fa clock_id
+of
+.Dv CLOCK_MONOTONIC
+identifies a clock that increases at a steady rate (monotonically).
+This clock
+is not affected by calls to
+.Xr adjtime 2
+and
+.Xr settimeofday 2
+and will
+fail with an
+.Er EINVAL
+error if it the clock specified in a call to
+.Fn clock_settime .
+The origin of the clock is unspecified.
+.Pp
If the calling user is not the syper-user, then the
.Fn clock_settime
function in the standard C library will try to use the
@@ -141,6 +158,10 @@ The
.Fa tp
argument specified a nanosecond value less than zero of greater than or equal
1000 million.
+.It Bq Er EINVAL
+The
+.Fa clock_id
+argument is a clock that can not be adjusted.
.It Bq Er EPERM
The
calling process does not have the appropriate privilege to set the specified
Index: sys/kern/kern_time.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_time.c,v
retrieving revision 1.60
diff -d -p -u -r1.60 kern_time.c
--- sys/kern/kern_time.c 2001/12/09 16:10:43 1.60
+++ sys/kern/kern_time.c 2002/01/26 13:40:29
@@ -166,13 +166,24 @@ sys_clock_gettime(p, v, retval)
clockid_t clock_id;
struct timeval atv;
struct timespec ats;
+ int s;
clock_id = SCARG(uap, clock_id);
- if (clock_id != CLOCK_REALTIME)
+ switch (clock_id) {
+ case CLOCK_REALTIME:
+ microtime(&atv);
+ TIMEVAL_TO_TIMESPEC(&atv,&ats);
+ break;
+ case CLOCK_MONOTONIC:
+ /* XXX "hz" granularity */
+ s = splclock();
+ atv = mono_time;
+ splx(s);
+ TIMEVAL_TO_TIMESPEC(&atv,&ats);
+ break;
+ default:
return (EINVAL);
-
- microtime(&atv);
- TIMEVAL_TO_TIMESPEC(&atv,&ats);
+ }
return copyout(&ats, SCARG(uap, tp), sizeof(ats));
}
@@ -209,12 +220,17 @@ clock_settime1(clock_id, tp)
if ((error = copyin(tp, &ats, sizeof(ats))) != 0)
return (error);
- if (clock_id != CLOCK_REALTIME)
+ switch (clock_id) {
+ case CLOCK_REALTIME:
+ TIMESPEC_TO_TIMEVAL(&atv, &ats);
+ if ((error = settime(&atv)) != 0)
+ return (error);
+ break;
+ case CLOCK_MONOTONIC:
+ return (EINVAL); /* read-only clock */
+ default:
return (EINVAL);
-
- TIMESPEC_TO_TIMEVAL(&atv, &ats);
- if ((error = settime(&atv)) != 0)
- return (error);
+ }
return 0;
}
@@ -234,15 +250,18 @@ sys_clock_getres(p, v, retval)
int error = 0;
clock_id = SCARG(uap, clock_id);
- if (clock_id != CLOCK_REALTIME)
- return (EINVAL);
-
- if (SCARG(uap, tp)) {
+ switch (clock_id) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
ts.tv_sec = 0;
ts.tv_nsec = 1000000000 / hz;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (SCARG(uap, tp))
error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
- }
return error;
}
Index: sys/sys/time.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/time.h,v
retrieving revision 1.33
diff -d -p -u -r1.33 time.h
--- sys/sys/time.h 2001/12/09 16:10:43 1.33
+++ sys/sys/time.h 2002/01/26 13:40:29
@@ -154,6 +154,7 @@ struct clockinfo {
#define CLOCK_REALTIME 0
#define CLOCK_VIRTUAL 1
#define CLOCK_PROF 2
+#define CLOCK_MONOTONIC 3
#define TIMER_RELTIME 0x0 /* relative timer */
#define TIMER_ABSTIME 0x1 /* absolute timer */