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

Reply via email to