[PATCH] Correct timespec implementation [BZ #26232]

H.J. Lu hjl.tools@gmail.com
Tue Jul 14 13:12:23 GMT 2020


On Tue, Jul 14, 2020 at 5:18 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > There are
> >
> > time_t
> > support_timespec_ns (struct timespec time)
> > {
> >   time_t time_ns;
> >   if (INT_MULTIPLY_WRAPV(time.tv_sec, TIMESPEC_HZ, &time_ns))
> >     return time.tv_sec < 0 ? TYPE_MINIMUM(time_t) : TYPE_MAXIMUM(time_t);
> >   if (INT_ADD_WRAPV(time_ns, time.tv_nsec, &time_ns))
> >     return time.tv_nsec < 0 ? TYPE_MINIMUM(time_t) : TYPE_MAXIMUM(time_t);
> >   return time_ns;
> > }
> >
> > Even if support_timespec_ns is changed to return long long, we still
> > may need to keep
> >
> >  time_t time_ns;
> >
> > for
> >
> >    if (INT_MULTIPLY_WRAPV(time.tv_sec, TIMESPEC_HZ, &time_ns))
> >
> > and
> >
> >   if (INT_ADD_WRAPV(time_ns, time.tv_nsec, &time_ns))
> >
> > It looks odd to return long long here.
>
> Why?
>
> You can use the GCC built-ins for checked arithmetic, they support mixed
> types.
>

This doesn't work on i686:

diff --git a/support/timespec.c b/support/timespec.c
index edbdb165ec..c35e8a8201 100644
--- a/support/timespec.c
+++ b/support/timespec.c
@@ -63,10 +63,10 @@ test_timespec_equal_or_after_impl (const char
*file, int line,
 /* Convert TIME to nanoseconds stored in a time_t.
    Returns time_t maximum or minimum if the conversion overflows
    or underflows, respectively.  */
-time_t
+long long
 support_timespec_ns (struct timespec time)
 {
-  time_t time_ns;
+  long long time_ns;
   if (INT_MULTIPLY_WRAPV(time.tv_sec, TIMESPEC_HZ, &time_ns))
     return time.tv_sec < 0 ? TYPE_MINIMUM(time_t) : TYPE_MAXIMUM(time_t);
   if (INT_ADD_WRAPV(time_ns, time.tv_nsec, &time_ns))
diff --git a/support/timespec.h b/support/timespec.h
index 1a6775a882..68055f42c3 100644
--- a/support/timespec.h
+++ b/support/timespec.h
@@ -48,7 +48,7 @@ void test_timespec_equal_or_after_impl (const char
*file, int line,
                                         const struct timespec left,
                                         const struct timespec right);

-time_t support_timespec_ns (struct timespec time);
+long long support_timespec_ns (struct timespec time);

 struct timespec support_timespec_normalize (struct timespec time);

This works:

diff --git a/support/timespec.c b/support/timespec.c
index edbdb165ec..b117e7c0d2 100644
--- a/support/timespec.c
+++ b/support/timespec.c
@@ -63,7 +63,7 @@ test_timespec_equal_or_after_impl (const char *file, int line,
 /* Convert TIME to nanoseconds stored in a time_t.
    Returns time_t maximum or minimum if the conversion overflows
    or underflows, respectively.  */
-time_t
+long long
 support_timespec_ns (struct timespec time)
 {
   time_t time_ns;
diff --git a/support/timespec.h b/support/timespec.h
index 1a6775a882..68055f42c3 100644
--- a/support/timespec.h
+++ b/support/timespec.h
@@ -48,7 +48,7 @@ void test_timespec_equal_or_after_impl (const char
*file, int line,
                                         const struct timespec left,
                                         const struct timespec right);

-time_t support_timespec_ns (struct timespec time);
+long long support_timespec_ns (struct timespec time);

 struct timespec support_timespec_normalize (struct timespec time);

What is the advantage of long long over time_t?

-- 
H.J.


More information about the Libc-alpha mailing list