This patch bumps the precision of durations printed by csh(1), ksh(1),
and time(1) from centiseconds to milliseconds.  The csh(1) and ksh(1)
builtins "time" and "times" are affected.

My thinking is:

- All practical OpenBSD platforms have a timecounter with at least
  millisecond precision.

- It's not uncommon for people to run a custom HZ=1000 kernel.
  At HZ=1000, the profiled user and system durations offered by
  getrusage(2) are (arguably) millisecond precision.

  Yes, I know those numbers are profiled and thus not especially
  trustworthy, but it's no different from the situation on a
  HZ=100 kernel.

- The timing commands offered in other shells like bash and dash
  provide (at least) millisecond precision.

- Centiseconds are a bit odd.  They don't align with the tidy
  "thousands" separation typical of metric units.

- The POSIX standard for time(1) and the "times" builtin specifies
  that the durations are formatted as a floating point value of
  seconds, i.e. "%f".  This means millisecond precision is okay:

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/time.html
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#times

Index: bin/csh/time.c
===================================================================
RCS file: /cvs/src/bin/csh/time.c,v
retrieving revision 1.18
diff -u -p -r1.18 time.c
--- bin/csh/time.c      8 Mar 2023 04:43:04 -0000       1.18
+++ bin/csh/time.c      14 Jun 2023 03:23:29 -0000
@@ -40,6 +40,7 @@
  * C Shell - routines handling process timing and niceing
  */
 static void    pdeltat(struct timeval *, struct timeval *);
+static void    pdelta_hms(const struct timespec *, const struct timespec *);
 
 void
 settimes(void)
@@ -145,7 +146,7 @@ prusage(struct rusage *r0, struct rusage
                break;
 
            case 'E':           /* elapsed (wall-clock) time */
-               pcsecs((long) ms);
+               pdelta_hms(e, b);
                break;
 
            case 'P':           /* percent time spent running */
@@ -227,8 +228,7 @@ pdeltat(struct timeval *t1, struct timev
     struct timeval td;
 
     timersub(t1, t0, &td);
-    (void) fprintf(cshout, "%lld.%01ld", (long long)td.tv_sec,
-       td.tv_usec / 100000);
+    fprintf(cshout, "%lld.%03ld", (long long)td.tv_sec, td.tv_usec / 1000);
 }
 
 #define  P2DIG(i) (void) fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
@@ -254,23 +254,18 @@ minsec:
 }
 
 void
-pcsecs(long l)                 /* PWP: print mm:ss.dd, l is in sec*100 */
+pdelta_hms(const struct timespec *t1, const struct timespec *t0)
 {
-    int i;
+    struct timespec elapsed;
+    long long hours, minutes, seconds;
 
-    i = l / 360000;
-    if (i) {
-       (void) fprintf(cshout, "%d:", i);
-       i = (l % 360000) / 100;
-       P2DIG(i / 60);
-       goto minsec;
-    }
-    i = l / 100;
-    (void) fprintf(cshout, "%d", i / 60);
-minsec:
-    i %= 60;
-    (void) fputc(':', cshout);
-    P2DIG(i);
-    (void) fputc('.', cshout);
-    P2DIG((int) (l % 100));
+    timespecsub(t1, t0, &elapsed);
+    hours = elapsed.tv_sec / 3600;
+    minutes = (elapsed.tv_sec % 3600) / 60;
+    seconds = elapsed.tv_sec % 60;
+    if (hours != 0)
+       fprintf(cshout, "%lld:%02lld:", hours, minutes);
+    else
+       fprintf(cshout, "%lld:", minutes);
+    fprintf(cshout, "%02lld.%03ld", seconds, elapsed.tv_nsec / 1000000);
 }
Index: bin/ksh/c_sh.c
===================================================================
RCS file: /cvs/src/bin/ksh/c_sh.c,v
retrieving revision 1.64
diff -u -p -r1.64 c_sh.c
--- bin/ksh/c_sh.c      22 May 2020 07:50:07 -0000      1.64
+++ bin/ksh/c_sh.c      14 Jun 2023 03:23:29 -0000
@@ -681,13 +681,13 @@ p_tv(struct shf *shf, int posix, struct 
     char *suffix)
 {
        if (posix)
-               shf_fprintf(shf, "%s%*lld.%02ld%s", prefix ? prefix : "",
-                   width, (long long)tv->tv_sec, tv->tv_usec / 10000, suffix);
+               shf_fprintf(shf, "%s%*lld.%03ld%s", prefix ? prefix : "",
+                   width, (long long)tv->tv_sec, tv->tv_usec / 1000, suffix);
        else
-               shf_fprintf(shf, "%s%*lldm%02lld.%02lds%s", prefix ? prefix : 
"",
+               shf_fprintf(shf, "%s%*lldm%02lld.%03lds%s", prefix ? prefix : 
"",
                    width, (long long)tv->tv_sec / 60,
                    (long long)tv->tv_sec % 60,
-                   tv->tv_usec / 10000, suffix);
+                   tv->tv_usec / 1000, suffix);
 }
 
 static void
@@ -695,14 +695,14 @@ p_ts(struct shf *shf, int posix, struct 
     char *suffix)
 {
        if (posix)
-               shf_fprintf(shf, "%s%*lld.%02ld%s", prefix ? prefix : "",
-                   width, (long long)ts->tv_sec, ts->tv_nsec / 10000000,
+               shf_fprintf(shf, "%s%*lld.%03ld%s", prefix ? prefix : "",
+                   width, (long long)ts->tv_sec, ts->tv_nsec / 1000000,
                    suffix);
        else
-               shf_fprintf(shf, "%s%*lldm%02lld.%02lds%s", prefix ? prefix : 
"",
+               shf_fprintf(shf, "%s%*lldm%02lld.%03lds%s", prefix ? prefix : 
"",
                    width, (long long)ts->tv_sec / 60,
                    (long long)ts->tv_sec % 60,
-                   ts->tv_nsec / 10000000, suffix);
+                   ts->tv_nsec / 1000000, suffix);
 }
 
 
Index: usr.bin/time/time.c
===================================================================
RCS file: /cvs/src/usr.bin/time/time.c,v
retrieving revision 1.25
diff -u -p -r1.25 time.c
--- usr.bin/time/time.c 21 Aug 2017 13:38:02 -0000      1.25
+++ usr.bin/time/time.c 14 Jun 2023 03:23:29 -0000
@@ -100,19 +100,19 @@ main(int argc, char *argv[])
        timespecsub(&after, &before, &during);
 
        if (portableflag) {
-               fprintf(stderr, "real %9lld.%02ld\n",
-                       (long long)during.tv_sec, during.tv_nsec/10000000);
-               fprintf(stderr, "user %9lld.%02ld\n",
-                       (long long)ru.ru_utime.tv_sec, 
ru.ru_utime.tv_usec/10000);
-               fprintf(stderr, "sys  %9lld.%02ld\n",
-                       (long long)ru.ru_stime.tv_sec, 
ru.ru_stime.tv_usec/10000);
+               fprintf(stderr, "real %9lld.%03ld\n",
+                   (long long)during.tv_sec, during.tv_nsec / 1000000);
+               fprintf(stderr, "user %9lld.%03ld\n",
+                   (long long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec / 1000);
+               fprintf(stderr, "sys  %9lld.%03ld\n",
+                   (long long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec / 1000);
        } else {
-               fprintf(stderr, "%9lld.%02ld real ",
-                       (long long)during.tv_sec, during.tv_nsec/10000000);
-               fprintf(stderr, "%9lld.%02ld user ",
-                       (long long)ru.ru_utime.tv_sec, 
ru.ru_utime.tv_usec/10000);
-               fprintf(stderr, "%9lld.%02ld sys\n",
-                       (long long)ru.ru_stime.tv_sec, 
ru.ru_stime.tv_usec/10000);
+               fprintf(stderr, "%9lld.%03ld real ",
+                   (long long)during.tv_sec, during.tv_nsec / 1000000);
+               fprintf(stderr, "%9lld.%0ld user ",
+                   (long long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec / 1000);
+               fprintf(stderr, "%9lld.%03ld sys\n",
+                   (long long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec / 1000);
        }
 
        if (lflag) {

Reply via email to