Hi,
The Description section in this page has always bugged me. The author
chose to save space by merging the description of two different system
calls into a single paragraph. Then the rules and caveats for
settimeofday() are off in a separate paragraph. Meh.
I recently revised the clock_gettime.2 page and I have bits I want to
crib from there to improve this page. Then there are other things on
the page that nag at me.
Anyway, here are the changes by section. Any questions or
uncertainties I have are appended after the list in each section.
NAME
- Explicitly note that this is the UTC time.
I like the sound of "get or set the time of day" better, but the
phrase "time of day" feels a little imprecise. Unsure.
SYNOPSIS
- I think the variable name "tp" is mediocre. Change "tp" to "now",
just like we did in clock_gettime.2. "now" helps reinforce what the
variable represents.
- While here change "tzp" to "tz". If we have no "tp" we don't need
the trailing 'p' for consistency.
DESCRIPTION
- Talk about gettimeofday() first, in its own paragraph. It is the most
important interface here and belongs right at the top.
- Then describe the UTC clock itself. Call it "UTC," not "Greenwich
time". Describe how the clock behaves, too.
I think a discussion of the granularity of the clock is outside the
scope of this page. Tick-based timecounters (i.e., those that are
only advanced during the clock interrupt) are exceedingly rare. The
time is almost always kept by a dedicated hardware counter.
Explicitly discourage people from using gettimeofday() to measure
elapsed time. Point them to clock_gettime(2).
- Then talk about settimeofday(). Merge the settimeofday() paragraph
with the paragraph describing its rules and caveats.
I don't think we need to mention that adjtime(2) can still slow the
effective clock frequency when securelevel >= 2. The adjustment is
capped at 5000ppm, which hardly cripples the system. You can do way,
way more damage with the newer adjfreq(2) call, anyway, and I don't
want to mention both.
I *do* think we ought to mention that settimeofday(2) cancels
whatever adjtime(2) was doing. That is a side effect of the call
and we need to mention it explicitly.
- Update the timeval structure description to match the current code
in sys/time.h
- Last and very much least, the historical timezone parameter.
Clarify that we no longer keep timezone information in the
kernel, not that we just don't track it at all.
Use active voice when describing the consequences when tz is not
NULL.
I am a little uncertain about telling the reader not to use
gettimeofday() to measure time right in the middle of the Description.
That said, it's an extremely common mistake, and I don't think it
should be appended in Caveats.
Thoughts?
SEE ALSO
- Reference timeradd(3). We're working with timevals on this page.
ERRORS
- Simplify leading sentences.
- Use more active voice.
- Strictly speaking, you don't need to try to set the time to get
EPERM. Any unprivileged process gets EPERM when it calls
settimeofday(), even if the first argument is NULL. More accurate to
say that the caller wasn't root, not what the caller tried to do.
- Document the securelevel(7) EPERM error.
Should we document the other error, the UINT_MAX seconds cap? See
settime() in sys/kern/kern_time.c. I'm leaning towards "no".
STANDARDS
- settimeofday() has never been standardized, but it's available
everywhere. I think we should note this. It's not unique to
us, or even to BSD. Linux, Solaris, AIX, whatever, they all
have it.
HISTORY
I want to rework the first sentence here but I'm stumped at the
moment. I'll circle back to it.
CAVEATS
Should this warning be here? Isn't this more relevant to a system
administrator in the date(1) page?
It feels out of scope for a system call manpage to be making
recommendations about rebooting the system after you use it. A system
administrator doesn't use the settimeofday(2) system call directly,
nor are they necessarily even aware of the underlying system call at
all. They use a tool like date(1) to set the clock.
Thoughts?
--
Index: gettimeofday.2
===================================================================
RCS file: /cvs/src/lib/libc/sys/gettimeofday.2,v
retrieving revision 1.31
diff -u -p -r1.31 gettimeofday.2
--- gettimeofday.2 4 Sep 2019 14:27:55 -0000 1.31
+++ gettimeofday.2 30 Jul 2021 14:37:46 -0000
@@ -35,97 +35,121 @@
.Sh NAME
.Nm gettimeofday ,
.Nm settimeofday
-.Nd get/set date and time
+.Nd get or set the UTC time
.Sh SYNOPSIS
.In sys/time.h
.Ft int
-.Fn gettimeofday "struct timeval *tp" "struct timezone *tzp"
+.Fn gettimeofday "struct timeval *now" "struct timezone *tz"
.Ft int
-.Fn settimeofday "const struct timeval *tp" "const struct timezone *tzp"
+.Fn settimeofday "const struct timeval *now" "const struct timezone *tz"
.Sh DESCRIPTION
-The system's notion of the current Greenwich time is obtained with the
+The
+.Fn gettimeofday
+function writes the absolute value of the system's Coordinated Universal Time
+.Pq UTC
+clock to
+.Fa now
+unless
+.Fa now
+is
+.Dv NULL .
+.Pp
+The UTC clock's absolute value is the time elapsed since
+Jan 1 1970 00:00:00 +0000
+.Pq the Epoch .
+The clock normally advances continuously,
+though it may jump discontinuously if a process calls
+.Fn settimeofday
+or
+.Xr clock_settime 2 .
+For this reason,
.Fn gettimeofday
-call and set with the
+is not generally suitable for measuring elapsed time.
+Whenever possible,
+use
+.Xr clock_gettime 2
+to measure elapsed time with one of the system's monotonic clocks instead.
+.Pp
+The
.Fn settimeofday
-call.
-The time is expressed in seconds and microseconds
-since midnight (0 hour), January 1, 1970.
-The resolution of the system clock is hardware dependent, and the time
-may be updated continuously or in
-.Dq ticks .
-If
-.Fa tp
+function sets the system's UTC clock to the absolute value
+.Fa now
+unless
+.Fa now
is
-.Dv NULL ,
-the time will not be returned or set.
+.Dv NULL .
+Only the superuser may set the clock.
+If the system
+.Xr securelevel 7
+is 2 or greater the clock may only be advanced.
+This limitation is imposed to prevent a malicious superuser
+from setting arbitrary timestamps on files.
+Setting the clock cancels any ongoing
+.Xr adjtime 2
+adjustment.
+.Pp
The structure pointed to by
-.Fa tp
+.Fa now
is defined in
.In sys/time.h
as:
.Bd -literal
struct timeval {
- time_t tv_sec; /* seconds since Jan. 1, 1970 */
+ time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* and microseconds */
};
.Ed
.Pp
The
-.Fa tzp
-parameter is historical and timezone information is no longer
-tracked by the system.
-All code should pass
-.Dv NULL
-for
-.Fa tzp .
-For
-.Fn gettimeofday ,
-if
-.Fa tzp
-is
-.Pf non- Dv NULL
-an empty
-.Dv timezone
-structure will be returned.
-For
-.Fn settimeofday ,
-if
-.Fa tzp
-is
-.Pf non- Dv NULL
-its contents are ignored.
-.Pp
-Only the superuser may set the time of day.
-If the system securelevel is greater than 1 (see
-.Xr init 8 ) ,
-the time may only be advanced.
-This limitation is imposed to prevent a malicious superuser
-from setting arbitrary time stamps on files.
-The system time can still be adjusted backwards using the
-.Xr adjtime 2
-system call even when the system is secure.
+.Fa tz
+argument is historical:
+the system no longer maintains timezone information in the kernel.
+The
+.Fa tz
+argument should always be
+.Dv NULL .
+.Fn gettimeofday
+zeroes
+.Fa tz
+if it is not
+.Dv NULL .
+.Fn settimeofday
+ignores the contents of
+.Fa tz
+if it is not
+.Dv NULL .
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
.Fn gettimeofday
and
.Fn settimeofday
-will succeed unless:
+will fail if:
.Bl -tag -width Er
.It Bq Er EFAULT
-An argument address referenced invalid memory.
+.Fa now
+or
+.Fa tz
+are not
+.Dv NULL
+and reference invalid memory.
.El
.Pp
-In addition,
.Fn settimeofday
-may return the following errors:
+will also fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
-.Fa tp
-specified a microsecond value less than zero or greater than or equal to
-1 million.
+.Fa now
+specifies a microsecond value less than zero or greater than or equal to
+one million.
+.It Bq Er EPERM
+The caller is not the superuser.
.It Bq Er EPERM
-A user other than the superuser attempted to set the time.
+The system
+.Xr securelevel 7
+is 2 or greater and
+.Fa now
+specifies a time in the past.
.El
.Sh SEE ALSO
.Xr date 1 ,
@@ -133,14 +157,21 @@ A user other than the superuser attempte
.Xr clock_gettime 2 ,
.Xr getitimer 2 ,
.Xr ctime 3 ,
-.Xr time 3
+.Xr time 3 ,
+.Xr timeradd 3
.Sh STANDARDS
The
.Fn gettimeofday
function conforms to
.St -p1003.1-2008 .
+.Pp
+The
+.Fn settimeofday
+function is non-standard,
+though many systems offer it.
.Sh HISTORY
-As predecessors of these functions, former system calls
+As predecessors of these functions,
+former system calls
.Fn time
and
.Fn stime