On Fri, Jul 30, 2021 at 09:41:38AM -0500, Scott Cheloha wrote:
> 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.
>
reads fine to me.
jmc
> 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
>