public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [RFC PATCH 04/52] Y2038: add function __mktime64 (and timelocal)
  2017-09-07 22:42     ` [RFC PATCH 03/52] Y2038: add functions using struct tm Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42       ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:42         ` [RFC PATCH 05/52] Y2038: add function __timegm64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

__mktime64 is designed similar to mktime, including checks on (64-bit)
integer limits, and respects the same Posix requirements as __mktime does,
i.e. calls tzset().

timelocal is a macro which evaluates to mktime, so when APIs are enabled,
both mktime and timelocal will become Y2038-proof

Also, the implementation does not require a Y2038-proof kernel.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                       |   9 +
 sysdeps/unix/sysv/linux/arm/Versions |   1 +
 time/mktime.c                        | 403 +++++++++++++++++++++++++++++++++++
 3 files changed, 413 insertions(+)

diff --git a/include/time.h b/include/time.h
index d2b1080fd6..79ab6ab6a1 100644
--- a/include/time.h
+++ b/include/time.h
@@ -57,6 +57,15 @@ extern time_t __mktime_internal (struct tm *__tp,
 				 struct tm *(*__func) (const time_t *,
 						       struct tm *),
 				 time_t *__offset);
+
+/* Subroutine of `__mktime64'.  Return the `__time64_t' representation of TP and
+   normalize TP, given that a `struct tm *' maps to a `__time64_t' as performed
+   by FUNC.  Keep track of next guess for __time64_t offset in *OFFSET.  */
+extern __time64_t __mktime64_internal (struct tm *__tp,
+				 struct tm *(*__func) (const __time64_t *,
+						       struct tm *),
+				 __time64_t *__offset);
+
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index dd6a160c75..546d7c60ee 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -25,5 +25,6 @@ libc {
     __ctime64; __ctime64_r;
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
+    __mktime64; __timelocal64_r;
   }
 }
diff --git a/time/mktime.c b/time/mktime.c
index 4c48d358a1..c0ba4e5761 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -599,6 +599,409 @@ weak_alias (mktime, timelocal)
 libc_hidden_def (mktime)
 libc_hidden_weak (timelocal)
 #endif
+
+/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
+   (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
+   were not adjusted between the time stamps.
+
+   The YEAR values uses the same numbering as TP->tm_year.  Values
+   need not be in the usual range.  However, YEAR1 must not be less
+   than 2 * INT_MIN or greater than 2 * INT_MAX.
+
+   The result may overflow.  It is the caller's responsibility to
+   detect overflow.  */
+
+static __time64_t
+ydhms64_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
+	    int year0, int yday0, int hour0, int min0, int sec0)
+{
+  verify (C99_integer_division, -1 / 2 == 0);
+
+  /* Compute intervening leap days correctly even if year is negative.
+     Take care to avoid integer overflow here.  */
+  int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
+  int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
+  int a100 = a4 / 25 - (a4 % 25 < 0);
+  int b100 = b4 / 25 - (b4 % 25 < 0);
+  int a400 = SHR (a100, 2);
+  int b400 = SHR (b100, 2);
+  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
+
+  /* Compute the desired time in __time64_t precision.  Overflow might
+     occur here.  */
+  __time64_t tyear1 = year1;
+  __time64_t years = tyear1 - year0;
+  __time64_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
+  __time64_t hours = 24 * days + hour1 - hour0;
+  __time64_t minutes = 60 * hours + min1 - min0;
+  __time64_t seconds = 60 * minutes + sec1 - sec0;
+  return seconds;
+}
+
+/* Return the average of A and B, even if A + B would overflow.  */
+static __time64_t
+time64_t_avg (__time64_t a, __time64_t b)
+{
+  return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
+}
+
+/* Return 1 if A + B does not overflow.  If __time64_t is unsigned and if
+   B's top bit is set, assume that the sum represents A - -B, and
+   return 1 if the subtraction does not wrap around.  */
+static int
+time64_t_add_ok (__time64_t a, __time64_t b)
+{
+  if (! TYPE_SIGNED (__time64_t))
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (TIME_T_MIDPOINT <= b);
+    }
+  else if (WRAPV)
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (b < 0);
+    }
+  else
+    {
+      __time64_t avg = time64_t_avg (a, b);
+      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+    }
+}
+
+/* Return 1 if A + B does not overflow.  */
+static int
+time64_t_int_add_ok (__time64_t a, int b)
+{
+  verify (int_no_wider_than_time64_t, INT_MAX <= TIME_T_MAX);
+  if (WRAPV)
+    {
+      __time64_t sum = a + b;
+      return (sum < a) == (b < 0);
+    }
+  else
+    {
+      int a_odd = a & 1;
+      __time64_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
+      return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
+    }
+}
+
+/* Return a __time64_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
+   assuming that *T corresponds to *TP and that no clock adjustments
+   occurred between *TP and the desired time.
+   If TP is null, return a value not equal to *T; this avoids false matches.
+   If overflow occurs, yield the minimal or maximal value, except do not
+   yield a value equal to *T.  */
+static __time64_t
+guess_time64_tm (long_int year, long_int yday, int hour, int min, int sec,
+	       const __time64_t *t, const struct tm *tp)
+{
+  if (tp)
+    {
+      __time64_t d = ydhms64_diff (year, yday, hour, min, sec,
+			     tp->tm_year, tp->tm_yday,
+			     tp->tm_hour, tp->tm_min, tp->tm_sec);
+      if (time64_t_add_ok (*t, d))
+	return *t + d;
+    }
+
+  /* Overflow occurred one way or another.  Return the nearest result
+     that is actually in range, except don't report a zero difference
+     if the actual difference is nonzero, as that would cause a false
+     match; and don't oscillate between two values, as that would
+     confuse the spring-forward gap detector.  */
+  return (*t < TIME_T_MIDPOINT
+	  ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
+	  : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
+}
+
+/* Use CONVERT to convert *T to a broken down time in *TP.
+   If *T is out of range for conversion, adjust it so that
+   it is the nearest in-range value and then convert that.  */
+static struct tm *
+ranged64_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
+		__time64_t *t, struct tm *tp)
+{
+  struct tm *r = convert (t, tp);
+
+  if (!r && *t)
+    {
+      __time64_t bad = *t;
+      __time64_t ok = 0;
+
+      /* BAD is a known unconvertible __time64_t, and OK is a known good one.
+	 Use binary search to narrow the range between BAD and OK until
+	 they differ by 1.  */
+      while (bad != ok + (bad < 0 ? -1 : 1))
+	{
+	  __time64_t mid = *t = time64_t_avg (ok, bad);
+	  r = convert (t, tp);
+	  if (r)
+	    ok = mid;
+	  else
+	    bad = mid;
+	}
+
+      if (!r && ok)
+	{
+	  /* The last conversion attempt failed;
+	     revert to the most recent successful attempt.  */
+	  *t = ok;
+	  r = convert (t, tp);
+	}
+    }
+
+  return r;
+}
+
+
+/* Convert *TP to a __time64_t value, inverting
+   the monotonic and mostly-unit-linear conversion function CONVERT.
+   Use *OFFSET to keep track of a guess at the offset of the result,
+   compared to what the result would be for UTC without leap seconds.
+   If *OFFSET's guess is correct, only one CONVERT call is needed.
+   This function is external because it is used also by timegm.c.  */
+__time64_t
+__mktime64_internal (struct tm *tp,
+		   struct tm *(*convert) (const __time64_t *, struct tm *),
+		   __time64_t *offset)
+{
+  __time64_t t, gt, t0, t1, t2;
+  struct tm tm;
+
+  /* The maximum number of probes (calls to CONVERT) should be enough
+     to handle any combinations of time zone rule changes, solar time,
+     leap seconds, and oscillations around a spring-forward gap.
+     POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
+  int remaining_probes = 6;
+
+  /* Time requested.  Copy it in case CONVERT modifies *TP; this can
+     occur if TP is localtime's returned value and CONVERT is localtime.  */
+  int sec = tp->tm_sec;
+  int min = tp->tm_min;
+  int hour = tp->tm_hour;
+  int mday = tp->tm_mday;
+  int mon = tp->tm_mon;
+  int year_requested = tp->tm_year;
+  int isdst = tp->tm_isdst;
+
+  /* 1 if the previous probe was DST.  */
+  int dst2;
+
+  /* Ensure that mon is in range, and set year accordingly.  */
+  int mon_remainder = mon % 12;
+  int negative_mon_remainder = mon_remainder < 0;
+  int mon_years = mon / 12 - negative_mon_remainder;
+  long_int lyear_requested = year_requested;
+  long_int year = lyear_requested + mon_years;
+
+  /* The other values need not be in range:
+     the remaining code handles minor overflows correctly,
+     assuming int and __time64_t arithmetic wraps around.
+     Major overflows are caught at the end.  */
+
+  /* Calculate day of year from year, month, and day of month.
+     The result need not be in range.  */
+  int mon_yday = ((__mon_yday[leapyear (year)]
+		   [mon_remainder + 12 * negative_mon_remainder])
+		  - 1);
+  long_int lmday = mday;
+  long_int yday = mon_yday + lmday;
+
+  __time64_t guessed_offset = *offset;
+
+  int sec_requested = sec;
+
+  if (LEAP_SECONDS_POSSIBLE)
+    {
+      /* Handle out-of-range seconds specially,
+	 since ydhms_tm_diff assumes every minute has 60 seconds.  */
+      if (sec < 0)
+	sec = 0;
+      if (59 < sec)
+	sec = 59;
+    }
+
+  /* Invert CONVERT by probing.  First assume the same offset as last
+     time.  */
+
+  t0 = ydhms64_diff (year, yday, hour, min, sec,
+		   EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
+
+  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
+    {
+      /* __time64_t isn't large enough to rule out overflows, so check
+	 for major overflows.  A gross check suffices, since if t0
+	 has overflowed, it is off by a multiple of TIME_T_MAX -
+	 TIME_T_MIN + 1.  So ignore any component of the difference
+	 that is bounded by a small value.  */
+
+      /* Approximate log base 2 of the number of time units per
+	 biennium.  A biennium is 2 years; use this unit instead of
+	 years to avoid integer overflow.  For example, 2 average
+	 Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
+	 which is 63113904 seconds, and rint (log2 (63113904)) is
+	 26.  */
+      int ALOG2_SECONDS_PER_BIENNIUM = 26;
+      int ALOG2_MINUTES_PER_BIENNIUM = 20;
+      int ALOG2_HOURS_PER_BIENNIUM = 14;
+      int ALOG2_DAYS_PER_BIENNIUM = 10;
+      int LOG2_YEARS_PER_BIENNIUM = 1;
+
+      int approx_requested_biennia =
+	(SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
+	 - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
+	 + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
+	 + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
+	 + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
+	 + (LEAP_SECONDS_POSSIBLE
+	    ? 0
+	    : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
+
+      int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
+      int diff = approx_biennia - approx_requested_biennia;
+      int approx_abs_diff = diff < 0 ? -1 - diff : diff;
+
+      /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
+	 gives a positive value of 715827882.  Setting a variable
+	 first then doing math on it seems to work.
+	 (ghazi@caip.rutgers.edu) */
+      __time64_t time64_t_max = TIME_T_MAX;
+      __time64_t time64_t_min = TIME_T_MIN;
+      __time64_t overflow_threshold =
+	(time64_t_max / 3 - time64_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
+
+      if (overflow_threshold < approx_abs_diff)
+	{
+	  /* Overflow occurred.  Try repairing it; this might work if
+	     the time zone offset is enough to undo the overflow.  */
+	  __time64_t repaired_t0 = -1 - t0;
+	  approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
+	  diff = approx_biennia - approx_requested_biennia;
+	  approx_abs_diff = diff < 0 ? -1 - diff : diff;
+	  if (overflow_threshold < approx_abs_diff)
+	    return -1;
+	  guessed_offset += repaired_t0 - t0;
+	  t0 = repaired_t0;
+	}
+    }
+
+  /* Repeatedly use the error to improve the guess.  */
+
+  for (t = t1 = t2 = t0, dst2 = 0;
+       (gt = guess_time64_tm (year, yday, hour, min, sec, &t,
+			    ranged64_convert (convert, &t, &tm)),
+	t != gt);
+       t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
+    if (t == t1 && t != t2
+	&& (tm.tm_isdst < 0
+	    || (isdst < 0
+		? dst2 <= (tm.tm_isdst != 0)
+		: (isdst != 0) != (tm.tm_isdst != 0))))
+      /* We can't possibly find a match, as we are oscillating
+	 between two values.  The requested time probably falls
+	 within a spring-forward gap of size GT - T.  Follow the common
+	 practice in this case, which is to return a time that is GT - T
+	 away from the requested time, preferring a time whose
+	 tm_isdst differs from the requested value.  (If no tm_isdst
+	 was requested and only one of the two values has a nonzero
+	 tm_isdst, prefer that value.)  In practice, this is more
+	 useful than returning -1.  */
+      goto offset_found;
+    else if (--remaining_probes == 0)
+      return -1;
+
+  /* We have a match.  Check whether tm.tm_isdst has the requested
+     value, if any.  */
+  if (isdst_differ (isdst, tm.tm_isdst))
+    {
+      /* tm.tm_isdst has the wrong value.  Look for a neighboring
+	 time with the right value, and use its UTC offset.
+
+	 Heuristic: probe the adjacent timestamps in both directions,
+	 looking for the desired isdst.  This should work for all real
+	 time zone histories in the tz database.  */
+
+      /* Distance between probes when looking for a DST boundary.  In
+	 tzdata2003a, the shortest period of DST is 601200 seconds
+	 (e.g., America/Recife starting 2000-10-08 01:00), and the
+	 shortest period of non-DST surrounded by DST is 694800
+	 seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
+	 minimum of these two values, so we don't miss these short
+	 periods when probing.  */
+      int stride = 601200;
+
+      /* The longest period of DST in tzdata2003a is 536454000 seconds
+	 (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
+	 period of non-DST is much longer, but it makes no real sense
+	 to search for more than a year of non-DST, so use the DST
+	 max.  */
+      int duration_max = 536454000;
+
+      /* Search in both directions, so the maximum distance is half
+	 the duration; add the stride to avoid off-by-1 problems.  */
+      int delta_bound = duration_max / 2 + stride;
+
+      int delta, direction;
+
+      for (delta = stride; delta < delta_bound; delta += stride)
+	for (direction = -1; direction <= 1; direction += 2)
+	  if (time64_t_int_add_ok (t, delta * direction))
+	    {
+	      __time64_t ot = t + delta * direction;
+	      struct tm otm;
+	      ranged64_convert (convert, &ot, &otm);
+	      if (! isdst_differ (isdst, otm.tm_isdst))
+		{
+		  /* We found the desired tm_isdst.
+		     Extrapolate back to the desired time.  */
+		  t = guess_time64_tm (year, yday, hour, min, sec, &ot, &otm);
+		  ranged64_convert (convert, &t, &tm);
+		  goto offset_found;
+		}
+	    }
+    }
+
+ offset_found:
+  *offset = guessed_offset + t - t0;
+
+  if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
+    {
+      /* Adjust time to reflect the tm_sec requested, not the normalized value.
+	 Also, repair any damage from a false match due to a leap second.  */
+      int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
+      if (! time64_t_int_add_ok (t, sec_requested))
+	return -1;
+      t1 = t + sec_requested;
+      if (! time64_t_int_add_ok (t1, sec_adjustment))
+	return -1;
+      t2 = t1 + sec_adjustment;
+      if (! convert (&t2, &tm))
+	return -1;
+      t = t2;
+    }
+
+  *tp = tm;
+  return t;
+}
+
+
+/* This uses a signed type wide enough to hold any UTC offset in seconds. */
+static __time64_t localtime64_offset;
+
+/* Convert *TP to a __time64_t value.  */
+__time64_t
+__mktime64 (struct tm *tp)
+{
+#ifdef _LIBC
+  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
+     time zone names contained in the external variable 'tzname' shall
+     be set as if the tzset() function had been called.  */
+  __tzset ();
+#endif
+
+  return __mktime64_internal (tp, __localtime64_r, &localtime64_offset);
+}
 \f
 #if defined DEBUG_MKTIME && DEBUG_MKTIME
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 05/52] Y2038: add function __timegm64
  2017-09-07 22:42       ` [RFC PATCH 04/52] Y2038: add function __mktime64 (and timelocal) Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42         ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:42           ` [RFC PATCH 06/52] Y2038: add struct __timespec64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Implementation is based on the same __mktime64_internal function
which was introduced in the '__mktime64' implementation change.

Again, the implementation does not require a Y2038-proof kernel.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 time/timegm.c                        | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 546d7c60ee..f7feda3650 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -26,5 +26,6 @@ libc {
     __gmtime64; __gmtime64_r;
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r;
+    __timegm64;
   }
 }
diff --git a/time/timegm.c b/time/timegm.c
index b0f5d16d16..0c8879285a 100644
--- a/time/timegm.c
+++ b/time/timegm.c
@@ -36,6 +36,9 @@
 time_t __mktime_internal (struct tm *,
 			  struct tm * (*) (time_t const *, struct tm *),
 			  time_t *);
+__time64_t __mktime64_internal (struct tm *,
+				struct tm * (*) (__time64_t const *, struct tm *),
+				__time64_t *);
 #endif
 
 time_t
@@ -45,3 +48,11 @@ timegm (struct tm *tmp)
   tmp->tm_isdst = 0;
   return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
 }
+
+__time64_t
+__timegm64 (struct tm *tmp)
+{
+  static __time64_t gmtime64_offset;
+  tmp->tm_isdst = 0;
+  return __mktime64_internal (tmp, __gmtime64_r, &gmtime64_offset);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 00/52] Make GLIBC Y2038-proof
@ 2017-09-07 22:42 Albert ARIBAUD (3ADEV)
  2017-09-07 22:42 ` [RFC PATCH 01/52] Y2038: add type __time64_t Albert ARIBAUD (3ADEV)
                   ` (2 more replies)
  0 siblings, 3 replies; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

This series implements Y2038-proof types, implementation, internal
functions, and APIs. For more information, see documentation at
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign

Each patch in this series except the last add one type or function,
with a few exception where several functions are implemented as a whole.

The last patch enables the _TIME_BITS mechanism. Once this patch is
applied, API header files will will use 64-bit time if _TIME_BITS is
defined and equal to 64 prior to their inclusion, and conversively,
will use 32-bit time if _TIME_BITS is different from 64 or does not
exist.

Albert ARIBAUD (3ADEV) (52):
  Y2038: add type __time64_t
  Y2038: add function __difftime64
  Y2038: add functions using struct tm
  Y2038: add function __mktime64 (and timelocal)
  Y2038: add function __timegm64
  Y2038: add struct __timespec64
  Y2038: add function __clock_gettime64
  Y2038: add function __clock_settime64
  Y2038: add function __clock_getres64
  Y2038: add function __clock_nanosleep64
  Y2038: add function __timespec_get64
  Y2038: add function __futimens64
  Y2038: add function __utimensat64
  Y2038: add function __sigtimedwait64
  Y2038: add struct __timeval64
  Y2038: add function __futimes64
  Y2038: add function __lutimes64
  Y2038: add struct __itimerspec64
  Y2038: add function __timer_gettime64
  Y2038: add function __timer_settime64
  Y2038: add function __timerfd_gettime64
  Y2038: add function __timerfd_settime64
  Y2038: add struct __stat64_t64
  Y2038: add function __fstat64_t64 (and __fxstat64_t64)
  Y2038: add function __stat64_t64 (and __xstat64_t64)
  Y2038: add function __lstat64_t64 (and __lxstat64_t64)
  Y2038: add function __fstatat64_t64 (and __fxstatat_t64)
  Y2038: add function __time_t64
  Y2038: add function __stime_t64
  Y2038: add function __utimes_t64
  Y2038: add function __gettimeofday_t64
  Y2038: add function __settimeofday_t64
  Y2038: add function __mq_timedsend_t64
  Y2038: add function __mq_timedreceive_t64
  Y2038: add function __msgctl_t64
  Y2038: add function __sched_rr_get_interval_t64
  Y2038: add function __nanosleep64_t64
  Y2038: add function __adjtime_t64
  Y2038: add function __utime_t64
  Y2038: add struct __itimerval_t64
  Y2038: add function __getitimer_t64
  Y2038: add function __setitimer_t64
  Y2038: add functions using futexes
  Y2038: add function __getrusage_t64
  Y2038: add struct __ntp_timeval_t64
  Y2038: add function __ntp_gettime_t64
  Y2038: add function __ntp_gettimex_t64
  Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64)
  Y2038: add function pselect
  Y2038: add function select
  Y2038: add RPC functions
  Y2038: add _TIME_BITS==64 support

 bits/typesizes.h                             |   1 +
 include/features.h                           |   4 +
 include/sys/select.h                         |  15 +
 include/sys/stat.h                           |  35 ++
 include/sys/time.h                           |   6 +
 include/time.h                               | 130 +++++-
 include/utime.h                              |   7 +
 io/Versions                                  |  11 +
 io/fstat64.c                                 |   7 +
 io/fstatat64.c                               |   7 +
 io/futimens.c                                |   9 +
 io/lstat64.c                                 |   7 +
 io/stat64.c                                  |   7 +
 io/sys/stat.h                                |  75 +++-
 io/utime.c                                   |  16 +
 io/utime.h                                   |  15 +-
 io/utimensat.c                               |   9 +
 misc/futimes.c                               |   9 +
 misc/lutimes.c                               |   8 +
 misc/sys/select.h                            |  25 ++
 misc/utimes.c                                |  15 +
 nptl/Versions                                |  11 +
 nptl/lll_timedlock_wait.c                    |  37 ++
 nptl/pthread_cond_wait.c                     | 285 +++++++++++++
 nptl/pthread_mutex_timedlock.c               | 616 +++++++++++++++++++++++++++
 nptl/pthread_rwlock_common.c                 | 591 +++++++++++++++++++++++++
 nptl/pthread_rwlock_timedrdlock.c            |  19 +
 nptl/pthread_rwlock_timedwrlock.c            |  19 +
 nptl/sem_timedwait.c                         |  18 +
 nptl/sem_wait.c                              |  24 ++
 nptl/sem_waitcommon.c                        | 172 ++++++++
 posix/Makefile                               |   3 +-
 posix/Versions                               |   7 +
 posix/bits/types.h                           |   3 +-
 posix/sched.h                                |   9 +
 posix/sched_rr_gi64.c                        |  51 +++
 resource/Makefile                            |   2 +-
 resource/Versions                            |   7 +
 resource/getrusage64.c                       | 185 ++++++++
 resource/sys/resource.h                      |   9 +
 rt/Makefile                                  |   6 +-
 rt/Versions                                  |  13 +
 rt/mq_timedreceive_t64.c                     |  45 ++
 rt/mq_timedsend_t64.c                        |  44 ++
 rt/mqueue.h                                  |  22 +
 rt/timerfd_gettime64.c                       |  28 ++
 rt/timerfd_settime64.c                       |  29 ++
 signal/signal.h                              |  10 +
 signal/sigtimedwait.c                        |  10 +
 sunrpc/clnt_udp.c                            |  27 ++
 sunrpc/pmap_rmt.c                            |  23 +
 sunrpc/rpc/clnt.h                            |  24 ++
 sunrpc/rpc/pmap_clnt.h                       |  15 +
 sysdeps/nptl/aio_misc.h                      |  39 ++
 sysdeps/nptl/lowlevellock.h                  |  17 +
 sysdeps/nptl/pthread.h                       |  41 ++
 sysdeps/posix/clock_getres.c                 |  87 +++-
 sysdeps/posix/time.c                         |  26 ++
 sysdeps/posix/utime.c                        |  22 +
 sysdeps/pthread/aio_suspend.c                | 164 +++++++
 sysdeps/pthread/semaphore.h                  |  10 +
 sysdeps/unix/clock_gettime.c                 |  46 ++
 sysdeps/unix/clock_settime.c                 |  56 ++-
 sysdeps/unix/sysv/linux/Versions             |   9 +
 sysdeps/unix/sysv/linux/adjtime.c            | 124 ++++++
 sysdeps/unix/sysv/linux/arm/Versions         |  24 ++
 sysdeps/unix/sysv/linux/arm/init-first.c     |  15 +
 sysdeps/unix/sysv/linux/arm/libc-vdso.h      |   1 +
 sysdeps/unix/sysv/linux/bits/msq.h           |  20 +
 sysdeps/unix/sysv/linux/bits/stat.h          |   6 +-
 sysdeps/unix/sysv/linux/clock_getres.c       |  40 ++
 sysdeps/unix/sysv/linux/clock_gettime.c      |  44 ++
 sysdeps/unix/sysv/linux/clock_nanosleep.c    |  87 +++-
 sysdeps/unix/sysv/linux/clock_settime.c      |  23 +
 sysdeps/unix/sysv/linux/futex-internal.h     | 123 ++++++
 sysdeps/unix/sysv/linux/futimens.c           |  38 ++
 sysdeps/unix/sysv/linux/futimes.c            |  52 +++
 sysdeps/unix/sysv/linux/fxstat64.c           |  50 +++
 sysdeps/unix/sysv/linux/fxstatat64.c         |  54 +++
 sysdeps/unix/sysv/linux/gettimeofday.c       |  26 ++
 sysdeps/unix/sysv/linux/lowlevellock-futex.h |  22 +
 sysdeps/unix/sysv/linux/lutimes.c            |  53 +++
 sysdeps/unix/sysv/linux/lxstat64.c           |  50 +++
 sysdeps/unix/sysv/linux/msgctl.c             |  72 ++++
 sysdeps/unix/sysv/linux/ntp_gettime.c        |  25 ++
 sysdeps/unix/sysv/linux/ntp_gettimex.c       |  31 ++
 sysdeps/unix/sysv/linux/pselect.c            |  61 +++
 sysdeps/unix/sysv/linux/select.c             |  66 +++
 sysdeps/unix/sysv/linux/settimeofday64.c     |  44 ++
 sysdeps/unix/sysv/linux/sigtimedwait.c       |  75 ++++
 sysdeps/unix/sysv/linux/stime.c              |  70 +++
 sysdeps/unix/sysv/linux/sys/timerfd.h        |  19 +
 sysdeps/unix/sysv/linux/sys/timex.h          |  32 +-
 sysdeps/unix/sysv/linux/time.c               |  22 +
 sysdeps/unix/sysv/linux/timer_gettime.c      |  24 ++
 sysdeps/unix/sysv/linux/timer_settime.c      |  49 +++
 sysdeps/unix/sysv/linux/timerfd_gettime64.c  |  44 ++
 sysdeps/unix/sysv/linux/timerfd_settime64.c  |  71 +++
 sysdeps/unix/sysv/linux/timespec_get.c       |  35 ++
 sysdeps/unix/sysv/linux/utimensat.c          |  36 ++
 sysdeps/unix/sysv/linux/utimes.c             |  31 ++
 sysdeps/unix/sysv/linux/xstat64.c            |  50 +++
 sysvipc/sys/msg.h                            |   9 +
 time/Makefile                                |   4 +-
 time/Versions                                |  16 +
 time/adjtime.c                               |  10 +
 time/bits/types/struct_timespec.h            |  17 +
 time/bits/types/struct_timeval.h             |   9 +
 time/bits/types/time_t.h                     |   4 +
 time/ctime.c                                 |  10 +
 time/ctime_r.c                               |   9 +
 time/difftime.c                              |   9 +
 time/getitimer64.c                           |  51 +++
 time/gettimeofday.c                          |  10 +
 time/gmtime.c                                |  15 +
 time/localtime.c                             |  17 +
 time/mktime.c                                | 403 ++++++++++++++++++
 time/nanosleep64.c                           |  61 +++
 time/offtime.c                               |  64 +++
 time/setitimer64.c                           |  69 +++
 time/settimeofday.c                          |   8 +
 time/stime.c                                 |  17 +
 time/sys/time.h                              |  74 ++++
 time/time.c                                  |  13 +
 time/time.h                                  | 161 ++++++-
 time/timegm.c                                |  11 +
 time/tzfile.c                                |   4 +-
 time/tzset.c                                 |  64 ++-
 128 files changed, 6112 insertions(+), 35 deletions(-)
 create mode 100644 posix/sched_rr_gi64.c
 create mode 100644 resource/getrusage64.c
 create mode 100644 rt/mq_timedreceive_t64.c
 create mode 100644 rt/mq_timedsend_t64.c
 create mode 100644 rt/timerfd_gettime64.c
 create mode 100644 rt/timerfd_settime64.c
 create mode 100644 sysdeps/unix/sysv/linux/settimeofday64.c
 create mode 100644 sysdeps/unix/sysv/linux/stime.c
 create mode 100644 sysdeps/unix/sysv/linux/timerfd_gettime64.c
 create mode 100644 sysdeps/unix/sysv/linux/timerfd_settime64.c
 create mode 100644 time/getitimer64.c
 create mode 100644 time/nanosleep64.c
 create mode 100644 time/setitimer64.c

-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 03/52] Y2038: add functions using struct tm
  2017-09-07 22:42   ` [RFC PATCH 02/52] Y2038: add function __difftime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42     ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:42       ` [RFC PATCH 04/52] Y2038: add function __mktime64 (and timelocal) Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

This consists in the following implementation additions:

([file] 32-bit implementation -> [file] 64-bit addition)

time/ctime.c ctime() -> __ctime64()
time/ctime_r.c ctime_r() -> __ctime64_r()
time/gmtime.c gmtime() -> __gmtime64()
time/gmtime.c gmtime_r() -> __gmtime64_r()
time/localtime.c localtime() -> __localtime64()
time/localtime.c localtime_r() -> __localtime64_r()

which require the following internal function additions

time/offtime.c __offtime() -> __offtime64()
time/tzset.c __tz_convert() -> __tz64_convert()

and internal function (32-bit-time-compatible) changes

time/tzfile.c __tzfile_compute()
time/tzset.c tzset_internal()
time/tzset.c compute_change()

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                       | 26 ++++++++++++---
 sysdeps/unix/sysv/linux/arm/Versions |  3 ++
 time/ctime.c                         | 10 ++++++
 time/ctime_r.c                       |  9 +++++
 time/gmtime.c                        | 15 +++++++++
 time/localtime.c                     | 17 ++++++++++
 time/offtime.c                       | 64 ++++++++++++++++++++++++++++++++++++
 time/tzfile.c                        |  4 +--
 time/tzset.c                         | 64 +++++++++++++++++++++++++++++++++---
 9 files changed, 201 insertions(+), 11 deletions(-)

diff --git a/include/time.h b/include/time.h
index 9956b82eb8..d2b1080fd6 100644
--- a/include/time.h
+++ b/include/time.h
@@ -8,6 +8,8 @@ extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
 extern __typeof (strptime_l) __strptime_l;
 
+extern struct tm *__localtime64 (const __time64_t *__timer);
+
 libc_hidden_proto (time)
 libc_hidden_proto (asctime)
 libc_hidden_proto (mktime)
@@ -39,13 +41,13 @@ extern int __use_tzfile attribute_hidden;
 
 extern void __tzfile_read (const char *file, size_t extra,
 			   char **extrap);
-extern void __tzfile_compute (time_t timer, int use_localtime,
+extern void __tzfile_compute (__time64_t timer, int use_localtime,
 			      long int *leap_correct, int *leap_hit,
 			      struct tm *tp);
 extern void __tzfile_default (const char *std, const char *dst,
 			      long int stdoff, long int dstoff);
 extern void __tzset_parse_tz (const char *tz);
-extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
+extern void __tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
      __THROW internal_function;
 
 /* Subroutine of `mktime'.  Return the `time_t' representation of TP and
@@ -58,23 +60,37 @@ extern time_t __mktime_internal (struct tm *__tp,
 extern struct tm *__localtime_r (const time_t *__timer,
 				 struct tm *__tp) attribute_hidden;
 
-extern struct tm *__gmtime_r (const time_t *__restrict __timer,
+extern struct tm *__localtime64_r (const __time64_t *__timer,
+				   struct tm *__tp) attribute_hidden;
+
+extern struct tm *__gmtime_r (const __time_t *__restrict __timer,
 			      struct tm *__restrict __tp);
 libc_hidden_proto (__gmtime_r)
 
+extern struct tm *__gmtime64_r (const __time64_t *__restrict __timer,
+			        struct tm *__restrict __tp);
+
 /* Compute the `struct tm' representation of *T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
    Return nonzero if successful.  */
-extern int __offtime (const time_t *__timer,
+extern int __offtime (const __time_t *__timer,
 		      long int __offset,
 		      struct tm *__tp);
 
+extern int __offtime64 (const __time64_t *__timer,
+		        long int __offset,
+		        struct tm *__tp);
+
 extern char *__asctime_r (const struct tm *__tp, char *__buf);
 extern void __tzset (void);
 
 /* Prototype for the internal function to get information based on TZ.  */
-extern struct tm *__tz_convert (const time_t *timer, int use_localtime, struct tm *tp);
+extern struct tm *__tz_convert (const __time_t *timer, int use_localtime,
+			        struct tm *tp);
+
+extern struct tm *__tz_convert64 (const __time64_t *timer,
+				  int use_localtime, struct tm *tp);
 
 extern int __nanosleep (const struct timespec *__requested_time,
 			struct timespec *__remaining);
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index d3655768c8..dd6a160c75 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -22,5 +22,8 @@ libc {
 
   GLIBC_Y2038 {
     __difftime64;
+    __ctime64; __ctime64_r;
+    __gmtime64; __gmtime64_r;
+    __localtime64; __localtime64_r;
   }
 }
diff --git a/time/ctime.c b/time/ctime.c
index 7baca1bb57..a5150c1845 100644
--- a/time/ctime.c
+++ b/time/ctime.c
@@ -26,3 +26,13 @@ ctime (const time_t *t)
      In particular, ctime and asctime must yield the same pointer.  */
   return asctime (localtime (t));
 }
+
+/* Return a string as returned by asctime which
+   is the representation of *T in that form.  */
+char *
+__ctime64 (const __time64_t *t)
+{
+  /* Apply the same rule as ctime:
+     make ctime64 (t) is equivalent to asctime (localtime64 (t)).  */
+  return asctime (__localtime64 (t));
+}
diff --git a/time/ctime_r.c b/time/ctime_r.c
index ecd7731038..74d856f17e 100644
--- a/time/ctime_r.c
+++ b/time/ctime_r.c
@@ -27,3 +27,12 @@ ctime_r (const time_t *t, char *buf)
   struct tm tm;
   return __asctime_r (__localtime_r (t, &tm), buf);
 }
+
+/* Return a string as returned by asctime which is the representation
+   of *T in that form.  Reentrant Y2038-proof version.  */
+char *
+__ctime64_r (const __time64_t *t, char *buf)
+{
+  struct tm tm;
+  return __asctime_r (__localtime64_r (t, &tm), buf);
+}
diff --git a/time/gmtime.c b/time/gmtime.c
index 049d551cdf..7662c1d1f7 100644
--- a/time/gmtime.c
+++ b/time/gmtime.c
@@ -35,3 +35,18 @@ gmtime (const time_t *t)
 {
   return __tz_convert (t, 0, &_tmbuf);
 }
+
+/* Return the `struct tm' representation of 64-bit-time *T
+   in UTC, using *TP to store the result.  */
+struct tm *
+__gmtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert64 (t, 0, tp);
+}
+
+/* Return the `struct tm' representation of 64-bit-time *T in UTC.	*/
+struct tm *
+__gmtime64 (const __time64_t *t)
+{
+  return __tz_convert64 (t, 0, &_tmbuf);
+}
diff --git a/time/localtime.c b/time/localtime.c
index 07dd67ca71..fd2d997e60 100644
--- a/time/localtime.c
+++ b/time/localtime.c
@@ -39,3 +39,20 @@ localtime (const time_t *t)
   return __tz_convert (t, 1, &_tmbuf);
 }
 libc_hidden_def (localtime)
+
+/* 64-bit-time versions */
+
+/* Return the `struct tm' representation of *T in local time,
+   using *TP to store the result.  */
+struct tm *
+__localtime64_r (const __time64_t *t, struct tm *tp)
+{
+  return __tz_convert64 (t, 1, tp);
+}
+
+/* Return the `struct tm' representation of *T in local time.  */
+struct tm *
+__localtime64 (const __time64_t *t)
+{
+  return __tz_convert64 (t, 1, &_tmbuf);
+}
diff --git a/time/offtime.c b/time/offtime.c
index 75a28fed84..84237db440 100644
--- a/time/offtime.c
+++ b/time/offtime.c
@@ -84,3 +84,67 @@ __offtime (const time_t *t, long int offset, struct tm *tp)
   tp->tm_mday = days + 1;
   return 1;
 }
+
+/* Compute the `struct tm' representation of 64-bit-time *T,
+   offset OFFSET seconds east of UTC,
+   and store year, yday, mon, mday, wday, hour, min, sec into *TP.
+   Return nonzero if successful.  */
+int
+__offtime64 (const __time64_t *t, long int offset, struct tm *tp)
+{
+  __time64_t days, rem, y;
+  const unsigned short int *ip;
+
+  days = *t / SECS_PER_DAY;
+  rem = *t % SECS_PER_DAY;
+  rem += offset;
+  while (rem < 0)
+    {
+      rem += SECS_PER_DAY;
+      --days;
+    }
+  while (rem >= SECS_PER_DAY)
+    {
+      rem -= SECS_PER_DAY;
+      ++days;
+    }
+  tp->tm_hour = rem / SECS_PER_HOUR;
+  rem %= SECS_PER_HOUR;
+  tp->tm_min = rem / 60;
+  tp->tm_sec = rem % 60;
+  /* January 1, 1970 was a Thursday.  */
+  tp->tm_wday = (4 + days) % 7;
+  if (tp->tm_wday < 0)
+    tp->tm_wday += 7;
+  y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+
+  while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+    {
+      /* Guess a corrected year, assuming 365 days per year.  */
+      __time64_t yg = y + days / 365 - (days % 365 < 0);
+
+      /* Adjust DAYS and Y to match the guessed year.  */
+      days -= ((yg - y) * 365
+	       + LEAPS_THRU_END_OF (yg - 1)
+	       - LEAPS_THRU_END_OF (y - 1));
+      y = yg;
+    }
+  tp->tm_year = y - 1900;
+  if (tp->tm_year != y - 1900)
+    {
+      /* The year cannot be represented due to overflow.  */
+      __set_errno (EOVERFLOW);
+      return 0;
+    }
+  tp->tm_yday = days;
+  ip = __mon_yday[__isleap(y)];
+  for (y = 11; days < (long int) ip[y]; --y)
+    continue;
+  days -= ip[y];
+  tp->tm_mon = y;
+  tp->tm_mday = days + 1;
+  return 1;
+}
diff --git a/time/tzfile.c b/time/tzfile.c
index d41246980b..9da9d0b38b 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -630,7 +630,7 @@ __tzfile_default (const char *std, const char *dst,
 }
 \f
 void
-__tzfile_compute (time_t timer, int use_localtime,
+__tzfile_compute (__time64_t timer, int use_localtime,
 		  long int *leap_correct, int *leap_hit,
 		  struct tm *tp)
 {
@@ -685,7 +685,7 @@ __tzfile_compute (time_t timer, int use_localtime,
 
 	  /* Convert to broken down structure.  If this fails do not
 	     use the string.  */
-	  if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
+	  if (__glibc_unlikely (! __offtime64 (&timer, 0, tp)))
 	    goto use_last;
 
 	  /* Use the rules from the TZ string to compute the change.  */
diff --git a/time/tzset.c b/time/tzset.c
index cf5fe969b6..ee462107e1 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -55,7 +55,7 @@ typedef struct
 
     /* We cache the computed time of change for a
        given year so we don't have to recompute it.  */
-    time_t change;	/* When to change to this zone.  */
+    __time64_t change;	/* When to change to this zone.  */
     int computed_for;	/* Year above is computed for.  */
   } tz_rule;
 
@@ -417,7 +417,7 @@ tzset_internal (int always)
       tz_rules[0].name = tz_rules[1].name = "UTC";
       if (J0 != 0)
 	tz_rules[0].type = tz_rules[1].type = J0;
-      tz_rules[0].change = tz_rules[1].change = (time_t) -1;
+      tz_rules[0].change = tz_rules[1].change = (__time64_t) -1;
       update_vars ();
       return;
     }
@@ -516,10 +516,11 @@ compute_change (tz_rule *rule, int year)
 
 
 /* Figure out the correct timezone for TM and set `__tzname',
-   `__timezone', and `__daylight' accordingly.  */
+   `__timezone', and `__daylight' accordingly.
+   NOTE: this takes a __time64_t value, so passing a __time_t value is OK. */
 void
 internal_function
-__tz_compute (time_t timer, struct tm *tm, int use_localtime)
+__tz_compute (__time64_t timer, struct tm *tm, int use_localtime)
 {
   compute_change (&tz_rules[0], 1900 + tm->tm_year);
   compute_change (&tz_rules[1], 1900 + tm->tm_year);
@@ -620,6 +621,61 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
 }
 
 
+/* Return the `struct tm' representation of *TIMER in the local timezone.
+   Use local time if USE_LOCALTIME is nonzero, UTC otherwise.  */
+struct tm *
+__tz_convert64 (const __time64_t *timer, int use_localtime, struct tm *tp)
+{
+  long int leap_correction;
+  int leap_extra_secs;
+
+  if (timer == NULL)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
+  __libc_lock_lock (tzset_lock);
+
+  /* Update internal database according to current TZ setting.
+     POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
+     This is a good idea since this allows at least a bit more parallelism.  */
+  tzset_internal (tp == &_tmbuf && use_localtime);
+
+  if (__use_tzfile)
+    __tzfile_compute (*timer, use_localtime, &leap_correction,
+		      &leap_extra_secs, tp);
+  else
+    {
+      if (! __offtime64 (timer, 0, tp))
+	tp = NULL;
+      else
+	__tz_compute (*timer, tp, use_localtime);
+      leap_correction = 0L;
+      leap_extra_secs = 0;
+    }
+
+  __libc_lock_unlock (tzset_lock);
+
+  if (tp)
+    {
+      if (! use_localtime)
+	{
+	  tp->tm_isdst = 0;
+	  tp->tm_zone = "GMT";
+	  tp->tm_gmtoff = 0L;
+	}
+
+      if (__offtime64 (timer, tp->tm_gmtoff - leap_correction, tp))
+        tp->tm_sec += leap_extra_secs;
+      else
+	tp = NULL;
+    }
+
+  return tp;
+}
+
+
 libc_freeres_fn (free_mem)
 {
   while (tzstring_list != NULL)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 06/52] Y2038: add struct __timespec64
  2017-09-07 22:42         ` [RFC PATCH 05/52] Y2038: add function __timegm64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42           ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:42             ` [RFC PATCH 07/52] Y2038: add function __clock_gettime64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

To be Y2038-proof, struct __timespec64 needs its tv_sec field to
be a __time64_t rather than a __time_t. However, the question is
which type should the tv_nsec field be.

Keeping tv_nsec a long (32-bit) would be compatible with Posix
requirements but would result in the GLIBC struct timespec being
binary-incompatible with the Linux 64-bit struct timespec, which
contains a 64-bit, not 32-bit, signed tv_nsec field.

In order to maintain Posix compatibility yet simplify conversion
between Posix and Linux struct timespec values, the Y2038-proof
struct time stores its tv_nsec field as a 32-bit signed integer
plus a padding which can serve as a 64-bit sign extension. This
both meets Posix requirements and makes the GLIBC and Linux
struct timespec binary compatible.

Note that in the API (which is not modified here, and will be
later alongside all Y2038-sensitive APIs), this padding is made
'invisible' by defining it as an anonymous bitfield; whereas
the struct __timespec64 introduced here has a named field for
the padding, allowing implementations to read and write it.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/time.h b/include/time.h
index 79ab6ab6a1..c436c44539 100644
--- a/include/time.h
+++ b/include/time.h
@@ -4,6 +4,8 @@
 #ifndef _ISOMAC
 # include <bits/types/locale_t.h>
 
+#include <endian.h>
+
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
 extern __typeof (strptime_l) __strptime_l;
@@ -18,6 +20,22 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+#if BYTE_ORDER == BIG_ENDIAN
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+};
+#else
+struct __timespec64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds */
+  int tv_pad: 32;		/* Padding named for checking/setting */
+};
+#endif
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 02/52] Y2038: add function __difftime64
  2017-09-07 22:42 ` [RFC PATCH 01/52] Y2038: add type __time64_t Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42   ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:42     ` [RFC PATCH 03/52] Y2038: add functions using struct tm Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Note: the implementation expects __time64_t arguments but returns
a double like its 32-bit-time counterpart, in order to remain as
source-code-compatible as possible, even though the precision of a
double is only about 55 bits.

The implementation is simpler than its 32-bit counterpart, as it
assumes that all __time64_t implementations are just 64-bit integers.

Also, the implementation does not require a Y2038-proof kernel.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/arm/Versions | 7 +++++++
 time/difftime.c                      | 9 +++++++++
 2 files changed, 16 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 7e5ba53455..d3655768c8 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -16,4 +16,11 @@ libc {
     # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime).
     __vdso_clock_gettime;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __difftime64;
+  }
 }
diff --git a/time/difftime.c b/time/difftime.c
index e5e3311744..1b2494c727 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -119,3 +119,12 @@ __difftime (time_t time1, time_t time0)
   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
 }
 strong_alias (__difftime, difftime)
+
+/* Return the difference between 64-bit TIME1 and TIME0.  */
+double
+__difftime64 (__time64_t time1, __time64_t time0)
+{
+  /* Subtract the smaller integer from the larger, convert the difference to
+     double, and then negate if needed.  */
+  return time1 < time0 ? - (time0 - time1) : (time1 - time0);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 07/52] Y2038: add function __clock_gettime64
  2017-09-07 22:42           ` [RFC PATCH 06/52] Y2038: add struct __timespec64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42             ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43               ` [RFC PATCH 08/52] Y2038: add function __clock_settime64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Note: __clock_gettime64 is implemented in VDSO.
Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                           |  8 ++++++
 sysdeps/unix/clock_gettime.c             | 46 ++++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/arm/Versions     |  3 +++
 sysdeps/unix/sysv/linux/arm/init-first.c | 15 +++++++++++
 sysdeps/unix/sysv/linux/arm/libc-vdso.h  |  1 +
 sysdeps/unix/sysv/linux/clock_gettime.c  | 44 ++++++++++++++++++++++++++++++
 6 files changed, 117 insertions(+)

diff --git a/include/time.h b/include/time.h
index c436c44539..eeefbb4e98 100644
--- a/include/time.h
+++ b/include/time.h
@@ -20,6 +20,11 @@ libc_hidden_proto (localtime)
 libc_hidden_proto (strftime)
 libc_hidden_proto (strptime)
 
+/* Indicates whether the underlying kernel has 64-bit time support.
+   This is required for e.g. librt, which cannot directly check the
+   flag variable that init-first.c sets when detecting support. */
+extern int __y2038_kernel_support (void);
+
 #if BYTE_ORDER == BIG_ENDIAN
 struct __timespec64
 {
@@ -43,6 +48,9 @@ extern __typeof (clock_settime) __clock_settime;
 extern __typeof (clock_nanosleep) __clock_nanosleep;
 extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
+extern int __clock_gettime64 (clockid_t __clock_id,
+			      struct __timespec64 *__tp) __THROW;
+
 /* Now define the internal interfaces.  */
 struct tm;
 
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 5262066f51..ac224c919b 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -134,3 +134,49 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp)
 }
 weak_alias (__clock_gettime, clock_gettime)
 libc_hidden_def (__clock_gettime)
+
+/* Get current value of CLOCK and store it in TP, 64-bit version.  */
+int
+__clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp)
+{
+  int retval = -1;
+
+  switch (clock_id)
+    {
+#ifdef SYSDEP_GETTIME64
+      SYSDEP_GETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      {
+	struct timeval tv;
+	retval = gettimeofday (&tv, NULL);
+	if (retval == 0)
+	  TIMEVAL_TO_TIMESPEC (&tv, tp);
+      }
+      break;
+#endif
+
+    default:
+#ifdef SYSDEP_GETTIME64_CPU
+      SYSDEP_GETTIME64_CPU (clock_id, tp);
+#endif
+#if HP_TIMING_AVAIL
+      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+	  == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_gettime (clock_id, tp);
+      else
+#endif
+	__set_errno (EINVAL);
+      break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+    case CLOCK_PROCESS_CPUTIME_ID:
+      retval = hp_timing_gettime (clock_id, tp);
+      break;
+#endif
+    }
+
+  return retval;
+}
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index f7feda3650..a2655d6262 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -27,5 +27,8 @@ libc {
     __localtime64; __localtime64_r;
     __mktime64; __timelocal64_r;
     __timegm64;
+    __clock_gettime64;
+    __vdso_clock_gettime64;
+    __y2038_kernel_support;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/arm/init-first.c b/sysdeps/unix/sysv/linux/arm/init-first.c
index 3c289c2a25..61c01a56a7 100644
--- a/sysdeps/unix/sysv/linux/arm/init-first.c
+++ b/sysdeps/unix/sysv/linux/arm/init-first.c
@@ -23,6 +23,14 @@
 
 int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *) attribute_hidden;
 int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
+
+int __y2038_linux_support;
+
+int __y2038_kernel_support (void)
+{
+  return __y2038_linux_support;
+}
 
 static inline void
 _libc_vdso_platform_setup (void)
@@ -36,6 +44,13 @@ _libc_vdso_platform_setup (void)
   p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux26);
   PTR_MANGLE (p);
   VDSO_SYMBOL (clock_gettime) = p;
+
+  /* (aaribaud) TODO: map to version where clock_gettime64 officially appears */
+  p = _dl_vdso_vsym ("__vdso_clock_gettime64", NULL);
+  PTR_MANGLE (p);
+  VDSO_SYMBOL (clock_gettime64) = p;
+
+  __y2038_linux_support = (p != NULL) ? 1 : 0;
 }
 
 # define VDSO_SETUP _libc_vdso_platform_setup
diff --git a/sysdeps/unix/sysv/linux/arm/libc-vdso.h b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
index ae37b574e1..ee0e5941c0 100644
--- a/sysdeps/unix/sysv/linux/arm/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/arm/libc-vdso.h
@@ -27,6 +27,7 @@
 extern int (*VDSO_SYMBOL(gettimeofday)) (struct timeval *, void *)
    attribute_hidden;
 extern int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *);
+extern long (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *);
 
 #endif
 
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index e232f69a4f..df4e16e6db 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -44,4 +44,48 @@
   break
 #define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */
 
+/* 64-bit versions */
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+   kernel.  */
+#define SYSDEP_GETTIME64 \
+  SYSDEP_GETTIME64_CPUTIME;						      \
+  case CLOCK_REALTIME:							      \
+  case CLOCK_MONOTONIC:							      \
+    if (__y2038_linux_support)						      \
+      {									      \
+        retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);	      \
+      }									      \
+    else								      \
+      {									      \
+        retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);	      \
+        if (retval==0)							      \
+          {								      \
+            tp->tv_sec = ts32.tv_sec;					      \
+            tp->tv_nsec = ts32.tv_nsec;					      \
+            tp->tv_pad = 0;						      \
+          }								      \
+      }									      \
+    break
+
+#define SYSDEP_GETTIME64_CPU(clock_id, tp) \
+  if (__y2038_linux_support)						      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_gettime64, 2, clock_id, tp);	      \
+    }									      \
+  else									      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, &ts32);	      \
+      if (retval==0)							      \
+        {								      \
+          tp->tv_sec = ts32.tv_sec;					      \
+          tp->tv_nsec = ts32.tv_nsec;					      \
+          tp->tv_pad = 0;						      \
+        }								      \
+    }									      \
+  break
+#define SYSDEP_GETTIME64_CPUTIME \
+  struct timespec ts32;							      \
+  extern int __y2038_linux_support;
+
 #include <sysdeps/unix/clock_gettime.c>
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 01/52] Y2038: add type __time64_t
  2017-09-07 22:42 [RFC PATCH 00/52] Make GLIBC Y2038-proof Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:42 ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:42   ` [RFC PATCH 02/52] Y2038: add function __difftime64 Albert ARIBAUD (3ADEV)
  2017-09-07 23:21 ` [RFC PATCH 00/52] Make GLIBC Y2038-proof Joseph Myers
  2017-09-08  4:23 ` Albert ARIBAUD
  2 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:42 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 bits/typesizes.h   | 1 +
 posix/bits/types.h | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/bits/typesizes.h b/bits/typesizes.h
index d407bf4067..a916cc1d0d 100644
--- a/bits/typesizes.h
+++ b/bits/typesizes.h
@@ -48,6 +48,7 @@
 #define	__ID_T_TYPE		__U32_TYPE
 #define __CLOCK_T_TYPE		__SLONGWORD_TYPE
 #define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __TIME64_T_TYPE		__SQUAD_TYPE
 #define __USECONDS_T_TYPE	__U32_TYPE
 #define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
 #define __DADDR_T_TYPE		__S32_TYPE
diff --git a/posix/bits/types.h b/posix/bits/types.h
index e2f73a89e4..26f1e4542f 100644
--- a/posix/bits/types.h
+++ b/posix/bits/types.h
@@ -145,7 +145,8 @@ __STD_TYPE __CLOCK_T_TYPE __clock_t;	/* Type of CPU usage counts.  */
 __STD_TYPE __RLIM_T_TYPE __rlim_t;	/* Type for resource measurement.  */
 __STD_TYPE __RLIM64_T_TYPE __rlim64_t;	/* Type for resource measurement (LFS).  */
 __STD_TYPE __ID_T_TYPE __id_t;		/* General type for IDs.  */
-__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch.  */
+__STD_TYPE __TIME_T_TYPE __time_t;	/* Seconds since the Epoch, Y2038-unsafe.  */
+__STD_TYPE __TIME64_T_TYPE __time64_t;	/* Seconds since the Epoch, Y2038-safe.  */
 __STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds.  */
 __STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds.  */
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 13/52] Y2038: add function __utimensat64
  2017-09-07 22:43                       ` [RFC PATCH 12/52] Y2038: add function __futimens64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                         ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                           ` [RFC PATCH 14/52] Y2038: add function __sigtimedwait64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 io/utimensat.c                       |  9 +++++++++
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 sysdeps/unix/sysv/linux/utimensat.c  | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/io/utimensat.c b/io/utimensat.c
index f45eb73b93..6b9cf43d4b 100644
--- a/io/utimensat.c
+++ b/io/utimensat.c
@@ -30,3 +30,12 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
   return -1;
 }
 stub_warning (utimensat)
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utimensat64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 08dfae2b61..2620d81fdc 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -34,5 +34,6 @@ libc {
     __clock_getres64;
     __clock_nanosleep64;
     __futimens64;
+    __utimensat64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/utimensat.c b/sysdeps/unix/sysv/linux/utimensat.c
index 87f1ef04e0..baa718686e 100644
--- a/sysdeps/unix/sysv/linux/utimensat.c
+++ b/sysdeps/unix/sysv/linux/utimensat.c
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <sysdep.h>
+#include <stdio.h>
 
 
 /* Change the access time of FILE to TSP[0] and
@@ -34,3 +35,38 @@ utimensat (int fd, const char *file, const struct timespec tsp[2],
   /* Avoid implicit array coercion in syscall macros.  */
   return INLINE_SYSCALL (utimensat, 4, fd, file, &tsp[0], flags);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__utimensat64 (int fd, const char *file, const struct __timespec64 tsp[2],
+	   int flags)
+{
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (file == NULL)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+  if (!tsp)
+    return INLINE_SYSCALL (utimensat64, 4, fd, file, NULL, flags);
+
+  if (__y2038_linux_support)
+    {
+      ts64[0].tv_sec = tsp[0].tv_sec;
+      ts64[0].tv_nsec = tsp[0].tv_nsec;
+      ts64[0].tv_pad = 0;
+      ts64[1].tv_sec = tsp[1].tv_sec;
+      ts64[1].tv_nsec = tsp[1].tv_nsec;
+      ts64[1].tv_pad = 0;
+      return INLINE_SYSCALL (utimensat64, 4, fd, file, &ts64, flags);
+    }
+
+  ts32[0].tv_sec = tsp[0].tv_sec;
+  ts32[0].tv_nsec = tsp[0].tv_nsec;
+  ts32[1].tv_sec = tsp[1].tv_sec;
+  ts32[1].tv_nsec = tsp[1].tv_nsec;
+  return INLINE_SYSCALL (utimensat, 4, fd, file, &ts32, flags);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 17/52] Y2038: add function __lutimes64
  2017-09-07 22:43                               ` [RFC PATCH 16/52] Y2038: add function __futimes64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                                 ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                                   ` [RFC PATCH 18/52] Y2038: add struct __itimerspec64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 misc/lutimes.c                       |  8 ++++++
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 sysdeps/unix/sysv/linux/lutimes.c    | 53 ++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)

diff --git a/misc/lutimes.c b/misc/lutimes.c
index c4cce8f3b6..e01b5c996a 100644
--- a/misc/lutimes.c
+++ b/misc/lutimes.c
@@ -31,3 +31,11 @@ __lutimes (const char *file, const struct timeval tvp[2])
 weak_alias (__lutimes, lutimes)
 
 stub_warning (lutimes)
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__lutimes64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 155b7889eb..edac9cf007 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -37,5 +37,6 @@ libc {
     __utimensat64;
     __sigtimedwait64;
     __futimes64;
+    __lutimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/lutimes.c b/sysdeps/unix/sysv/linux/lutimes.c
index 433fb06701..c94273abf5 100644
--- a/sysdeps/unix/sysv/linux/lutimes.c
+++ b/sysdeps/unix/sysv/linux/lutimes.c
@@ -42,3 +42,56 @@ lutimes (const char *file, const struct timeval tvp[2])
   return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, tvp ? ts : NULL,
 			 AT_SYMLINK_NOFOLLOW);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__lutimes64 (const char *file, const struct __timeval64 tvp[2])
+{
+  /* The system call expects timespec, not timeval.  */
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (__y2038_linux_support)
+    {
+      if (tvp != NULL)
+        {
+          if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+              || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+  	    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+        
+          ts64[0].tv_sec = tvp[0].tv_sec;
+          ts64[0].tv_nsec = tvp[0].tv_usec * 1000;
+          ts64[0].tv_pad = 0;
+          ts64[1].tv_sec = tvp[1].tv_sec;
+          ts64[1].tv_nsec = tvp[1].tv_usec * 1000;
+          ts64[1].tv_pad = 0;
+        
+          return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, &ts64,
+  	  		     AT_SYMLINK_NOFOLLOW);
+        }
+    
+      return INLINE_SYSCALL (utimensat64, 4, AT_FDCWD, file, NULL,
+  			   AT_SYMLINK_NOFOLLOW);
+    }
+
+  if (tvp != NULL)
+    {
+      if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+          || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+    
+      ts32[0].tv_sec = tvp[0].tv_sec;
+      ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+      ts32[1].tv_sec = tvp[1].tv_sec;
+      ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+    
+      return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, &ts32,
+                             AT_SYMLINK_NOFOLLOW);
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, AT_FDCWD, file, NULL,
+                         AT_SYMLINK_NOFOLLOW);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 15/52] Y2038: add struct __timeval64
  2017-09-07 22:43                           ` [RFC PATCH 14/52] Y2038: add function __sigtimedwait64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                             ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                               ` [RFC PATCH 16/52] Y2038: add function __futimes64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/time.h b/include/time.h
index 90c1385d13..648cef2786 100644
--- a/include/time.h
+++ b/include/time.h
@@ -41,6 +41,12 @@ struct __timespec64
 };
 #endif
 
+struct __timeval64
+{
+  __time64_t tv_sec;		/* Seconds */
+  __int64_t tv_usec;		/* Microseconds */
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 08/52] Y2038: add function __clock_settime64
  2017-09-07 22:42             ` [RFC PATCH 07/52] Y2038: add function __clock_gettime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43               ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                 ` [RFC PATCH 09/52] Y2038: add function __clock_getres64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                          |  2 ++
 sysdeps/unix/clock_settime.c            | 56 ++++++++++++++++++++++++++++++++-
 sysdeps/unix/sysv/linux/arm/Versions    |  1 +
 sysdeps/unix/sysv/linux/clock_settime.c | 23 ++++++++++++++
 4 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index eeefbb4e98..63237e23f4 100644
--- a/include/time.h
+++ b/include/time.h
@@ -50,6 +50,8 @@ extern __typeof (clock_getcpuclockid) __clock_getcpuclockid;
 
 extern int __clock_gettime64 (clockid_t __clock_id,
 			      struct __timespec64 *__tp) __THROW;
+extern int __clock_settime64 (clockid_t __clock_id,
+			       const struct __timespec64 *__tp) __THROW;
 
 /* Now define the internal interfaces.  */
 struct tm;
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index e744cae6a9..8d7de2a310 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -68,8 +68,62 @@ hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
 }
 #endif
 
+/* Set CLOCK to value TP, 64-bit Y2038-safe version.  */
+int
+__clock_settime64 (clockid_t clock_id, const struct __timespec64 *tp)
+{
+  int retval = EOVERFLOW;
+
+  /* Make sure the time cvalue is OK.  */
+  if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  switch (clock_id)
+    {
+#define HANDLE_REALTIME \
+      do {								      \
+	struct timeval tv;						      \
+	TIMESPEC_TO_TIMEVAL (&tv, tp);					      \
+									      \
+	retval = settimeofday (&tv, NULL);				      \
+      } while (0)
+
+#ifdef SYSDEP_SETTIME64
+      SYSDEP_SETTIME64;
+#endif
+
+#ifndef HANDLED_REALTIME
+    case CLOCK_REALTIME:
+      HANDLE_REALTIME;
+      break;
+#endif
+
+    default:
+#ifdef SYSDEP_SETTIME64_CPU
+      SYSDEP_SETTIME64_CPU;
+#endif
+#ifndef HANDLED_CPUTIME
+# if HP_TIMING_AVAIL
+      if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
+	  || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_settime (clock_id, tp);
+      else
+# endif
+	{
+	  __set_errno (EINVAL);
+	  retval = -1;
+	}
+#endif
+      break;
+    }
+
+  return retval;
+}
 
-/* Set CLOCK to value TP.  */
+/* Set CLOCK to value TP, 64-bit Y2038-unsafe version.  */
 int
 __clock_settime (clockid_t clock_id, const struct timespec *tp)
 {
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index a2655d6262..553cdd7543 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -30,5 +30,6 @@ libc {
     __clock_gettime64;
     __vdso_clock_gettime64;
     __y2038_kernel_support;
+    __clock_settime64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 058c518e5a..40760ff494 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -35,4 +35,27 @@
 #define SYSDEP_SETTIME_CPU \
   retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
 
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+#define SYSDEP_SETTIME64 \
+  case CLOCK_REALTIME:							      \
+    if (__y2038_linux_support)						      \
+      {									      \
+        struct __timespec64 ts64;					      \
+        ts64.tv_sec = tp->tv_sec;					      \
+        ts64.tv_nsec = tp->tv_nsec;					      \
+        ts64.tv_pad = 0;						      \
+        retval = INLINE_SYSCALL (clock_settime64, 2, clock_id, &ts64);	      \
+      }									      \
+    else if (tp->tv_sec <= INT_MAX)					      \
+      {									      \
+        struct timespec ts32;						      \
+        ts32.tv_sec = tp->tv_sec;					      \
+        ts32.tv_nsec = tp->tv_nsec;					      \
+        retval = INLINE_SYSCALL (clock_settime, 2, clock_id, &ts32);	      \
+      }									      \
+    break
+
 #include <sysdeps/unix/clock_settime.c>
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 09/52] Y2038: add function __clock_getres64
  2017-09-07 22:43               ` [RFC PATCH 08/52] Y2038: add function __clock_settime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                 ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                   ` [RFC PATCH 10/52] Y2038: add function __clock_nanosleep64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                         |  2 +
 sysdeps/posix/clock_getres.c           | 87 +++++++++++++++++++++++++++++++++-
 sysdeps/unix/sysv/linux/arm/Versions   |  1 +
 sysdeps/unix/sysv/linux/clock_getres.c | 40 ++++++++++++++++
 4 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 63237e23f4..00bdb2853a 100644
--- a/include/time.h
+++ b/include/time.h
@@ -52,6 +52,8 @@ extern int __clock_gettime64 (clockid_t __clock_id,
 			      struct __timespec64 *__tp) __THROW;
 extern int __clock_settime64 (clockid_t __clock_id,
 			       const struct __timespec64 *__tp) __THROW;
+extern int __clock_getres64 (clockid_t __clock_id,
+			      struct __timespec64 *__res) __THROW;
 
 /* Now define the internal interfaces.  */
 struct tm;
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index b6248bef2c..3b74014d41 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -23,7 +23,6 @@
 #include <sys/param.h>
 #include <libc-internal.h>
 
-
 #if HP_TIMING_AVAIL
 static long int nsec;		/* Clock frequency of the processor.  */
 
@@ -53,6 +52,33 @@ hp_timing_getres (struct timespec *res)
 
   return 0;
 }
+
+static int
+hp_timing_getres64 (struct __timespec64 *res)
+{
+  if (__glibc_unlikely (nsec == 0))
+    {
+      hp_timing_t freq;
+
+      /* This can only happen if we haven't initialized the `nsec'
+	 variable yet.  Do this now.  We don't have to protect this
+	 code against multiple execution since all of them should
+	 lead to the same result.  */
+      freq = __get_clockfreq ();
+      if (__glibc_unlikely (freq == 0))
+	/* Something went wrong.  */
+	return -1;
+
+      nsec = MAX (UINT64_C (1000000000) / freq, 1);
+    }
+
+  /* Fill in the values.
+     The seconds are always zero (unless we have a 1Hz machine).  */
+  res->tv_sec = 0;
+  res->tv_nsec = nsec;
+
+  return 0;
+}
 #endif
 
 static inline int
@@ -73,6 +99,24 @@ realtime_getres (struct timespec *res)
   return -1;
 }
 
+static inline int
+realtime_getres64 (struct __timespec64 *res)
+{
+  long int clk_tck = sysconf (_SC_CLK_TCK);
+
+  if (__glibc_likely (clk_tck != -1))
+    {
+      /* This implementation assumes that the realtime clock has a
+	 resolution higher than 1 second.  This is the case for any
+	 reasonable implementation.  */
+      res->tv_sec = 0;
+      res->tv_nsec = 1000000000 / clk_tck;
+      return 0;
+    }
+
+  return -1;
+}
+
 
 /* Get resolution of clock.  */
 int
@@ -116,3 +160,44 @@ __clock_getres (clockid_t clock_id, struct timespec *res)
   return retval;
 }
 weak_alias (__clock_getres, clock_getres)
+
+int
+__clock_getres64 (clockid_t clock_id, struct __timespec64 *res)
+{
+  int retval = -1;
+
+  switch (clock_id)
+    {
+#ifdef SYSDEP_GETRES64
+      SYSDEP_GETRES64;
+#endif
+
+#ifndef HANDLED_REALTIME64
+    case CLOCK_REALTIME64:
+      retval = realtime_getres64 (res);
+      break;
+#endif	/* handled REALTIME */
+
+    default:
+#ifdef SYSDEP_GETRES_CPU64
+      SYSDEP_GETRES_CPU64;
+#endif
+#if HP_TIMING_AVAIL
+      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
+	  == CLOCK_THREAD_CPUTIME_ID)
+	retval = hp_timing_getres64 (res);
+      else
+#endif
+	__set_errno (EINVAL);
+      break;
+
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
+    case CLOCK_PROCESS_CPUTIME_ID:
+    case CLOCK_THREAD_CPUTIME_ID:
+      retval = hp_timing_getres64 (res);
+      break;
+#endif
+    }
+
+  return retval;
+}
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 553cdd7543..4b03cce526 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -31,5 +31,6 @@ libc {
     __vdso_clock_gettime64;
     __y2038_kernel_support;
     __clock_settime64;
+    __clock_getres64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 2b7bb65e55..095b284b23 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -48,4 +48,44 @@
 #define SYSDEP_GETRES_CPU SYSCALL_GETRES
 #define SYSDEP_GETRES_CPUTIME	/* Default catches them too.  */
 
+/* The 64-bit version */
+
+extern int __y2038_linux_support;
+
+#define SYSCALL_GETRES64 \
+  if (__y2038_linux_support)						      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_getres64, 2, clock_id, res);  	      \
+    }									      \
+  else									      \
+    {									      \
+      retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, &ts32);	      \
+        if (retval==0)							      \
+        {								      \
+          res->tv_sec = ts32.tv_sec;		                	      \
+          res->tv_nsec = ts32.tv_nsec;					      \
+          res->tv_pad = 0;				               	      \
+        }								      \
+    }									      \
+  break
+
+/* The REALTIME and MONOTONIC clock are definitely supported in the
+   kernel.  */
+#define SYSDEP_GETRES64							      \
+  SYSDEP_GETRES_CPUTIME64						      \
+  case CLOCK_REALTIME:							      \
+  case CLOCK_MONOTONIC:							      \
+  case CLOCK_MONOTONIC_RAW:						      \
+  case CLOCK_REALTIME_COARSE:						      \
+  case CLOCK_MONOTONIC_COARSE:						      \
+    SYSCALL_GETRES64
+
+/* We handled the REALTIME clock here.  */
+#define HANDLED_REALTIME64	1
+#define HANDLED_CPUTIME64	1
+
+#define SYSDEP_GETRES_CPU64 SYSCALL_GETRES64
+#define SYSDEP_GETRES_CPUTIME64 \
+  struct timespec ts32;
+ 
 #include <sysdeps/posix/clock_getres.c>
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 14/52] Y2038: add function __sigtimedwait64
  2017-09-07 22:43                         ` [RFC PATCH 13/52] Y2038: add function __utimensat64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                           ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                             ` [RFC PATCH 15/52] Y2038: add struct __timeval64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 signal/sigtimedwait.c                  | 10 +++++
 sysdeps/unix/sysv/linux/arm/Versions   |  1 +
 sysdeps/unix/sysv/linux/sigtimedwait.c | 75 ++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/signal/sigtimedwait.c b/signal/sigtimedwait.c
index 3b42003e26..c1e0d4375c 100644
--- a/signal/sigtimedwait.c
+++ b/signal/sigtimedwait.c
@@ -30,3 +30,13 @@ libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
 
 stub_warning (sigtimedwait)
+
+int
+__sigtimedwait64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__sigtimedwait64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 2620d81fdc..630e3f8569 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -35,5 +35,6 @@ libc {
     __clock_nanosleep64;
     __futimens64;
     __utimensat64;
+    __sigtimedwait64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index ab1a84ef1c..f79850dcfe 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+#include <stdint.h>
 
 #include <nptl/pthreadP.h>
 #include <sysdep-cancel.h>
@@ -64,6 +65,80 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
 }
 libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__sigtimedwait64 (const sigset_t *set, siginfo_t *info,
+		const struct __timespec64 *timeout)
+{
+  int result;
+  struct __timespec64 ts64;
+  struct timespec ts32;
+
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+	  ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+
+  if (__y2038_linux_support)
+    {
+      if (timeout)
+        {
+          ts64.tv_sec = timeout->tv_sec;
+          ts64.tv_nsec = timeout->tv_nsec;
+          ts64.tv_pad = 0;
+          result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts64, _NSIG / 8);
+        }
+      else
+        result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+    }
+  else
+    {
+      if (timeout)
+        {
+          if (timeout->tv_sec > INT32_MAX)
+            {
+              errno = EOVERFLOW;
+              return -1;
+            }
+          ts32.tv_sec = timeout->tv_sec;
+          ts32.tv_nsec = timeout->tv_nsec;
+          result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts32, _NSIG / 8);
+        }
+      else
+        result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+    }
+
+  /* The kernel generates a SI_TKILL code in si_code in case tkill is
+     used.  tkill is transparently used in raise().  Since having
+     SI_TKILL as a code is useful in general we fold the results
+     here.  */
+  if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+    info->si_code = SI_USER;
+
+  return result;
+}
 #else
 # include <signal/sigtimedwait.c>
 #endif
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 10/52] Y2038: add function __clock_nanosleep64
  2017-09-07 22:43                 ` [RFC PATCH 09/52] Y2038: add function __clock_getres64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                   ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                     ` [RFC PATCH 11/52] Y2038: add function __timespec_get64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                            |  3 ++
 sysdeps/unix/sysv/linux/arm/Versions      |  1 +
 sysdeps/unix/sysv/linux/clock_nanosleep.c | 87 ++++++++++++++++++++++++++++++-
 3 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/include/time.h b/include/time.h
index 00bdb2853a..90c1385d13 100644
--- a/include/time.h
+++ b/include/time.h
@@ -54,6 +54,9 @@ extern int __clock_settime64 (clockid_t __clock_id,
 			       const struct __timespec64 *__tp) __THROW;
 extern int __clock_getres64 (clockid_t __clock_id,
 			      struct __timespec64 *__res) __THROW;
+extern int __clock_nanosleep64 (clockid_t __clock_id, int __flags,
+				const struct __timespec64 *__req,
+				struct __timespec64 *__rem);
 
 /* Now define the internal interfaces.  */
 struct tm;
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 4b03cce526..fd94c63672 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -32,5 +32,6 @@ libc {
     __y2038_kernel_support;
     __clock_settime64;
     __clock_getres64;
+    __clock_nanosleep64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 93bc4cf47e..7d00176c3e 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -21,7 +21,6 @@
 #include <sysdep-cancel.h>
 #include "kernel-posix-cpu-timers.h"
 
-
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
 int
@@ -52,3 +51,89 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
 	  ? INTERNAL_SYSCALL_ERRNO (r, err) : 0);
 }
 weak_alias (__clock_nanosleep, clock_nanosleep)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__clock_nanosleep64 (clockid_t clock_id, int flags,
+		   const struct __timespec64 *req,
+                   struct __timespec64 *rem)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  int r;
+  struct __timespec64 req64;
+  struct timespec req32, rem32;
+
+  if (clock_id == CLOCK_THREAD_CPUTIME_ID)
+    return EINVAL;
+  if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
+    clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
+
+  if (SINGLE_THREAD_P)
+    {
+      if (__y2038_linux_support)
+        {
+          req64.tv_sec = req->tv_sec;
+          req64.tv_nsec = req->tv_nsec;
+          req64.tv_pad = 0;
+          r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+                                &req64, rem);
+        }
+      else if (req->tv_sec > INT_MAX)
+        r = EOVERFLOW;
+      else
+        {
+          req32.tv_sec = req->tv_sec;
+          req32.tv_nsec = req->tv_nsec;
+          r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+                                &req32, &rem32);
+          if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+            {
+              rem->tv_sec = rem32.tv_sec;
+              rem->tv_nsec = rem32.tv_nsec;
+              rem->tv_pad = 0;
+            }
+        }
+    }
+  else
+    {
+      int oldstate = LIBC_CANCEL_ASYNC ();
+
+      if (__y2038_linux_support)
+        {
+          req64.tv_sec = req->tv_sec;
+          req64.tv_nsec = req->tv_nsec;
+          req64.tv_pad = 0;
+          r = INTERNAL_SYSCALL (clock_nanosleep64, err, 4, clock_id, flags,
+                                &req64, rem);
+        }
+      else if (req->tv_sec > INT_MAX)
+        r = EOVERFLOW;
+      else
+        {
+          req32.tv_sec = req->tv_sec;
+          req32.tv_nsec = req->tv_nsec;
+          r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags,
+                                &req32, &rem32);
+          if (r == EINTR && rem != NULL && flags != TIMER_ABSTIME)
+            {
+              rem->tv_sec = rem32.tv_sec;
+              rem->tv_nsec = rem32.tv_nsec;
+              rem->tv_pad = 0;
+            }
+        }
+      
+      LIBC_CANCEL_RESET (oldstate);
+    }
+
+  if (INTERNAL_SYSCALL_ERROR_P (r, err))
+    {
+      return INTERNAL_SYSCALL_ERRNO (r, err);
+    }
+  else
+    {
+      return 0;
+    }
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 18/52] Y2038: add struct __itimerspec64
  2017-09-07 22:43                                 ` [RFC PATCH 17/52] Y2038: add function __lutimes64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                                   ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                                     ` [RFC PATCH 19/52] Y2038: add function __timer_gettime64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/time.h b/include/time.h
index 648cef2786..1d585184d8 100644
--- a/include/time.h
+++ b/include/time.h
@@ -47,6 +47,12 @@ struct __timeval64
   __int64_t tv_usec;		/* Microseconds */
 };
 
+struct __itimerspec64
+{
+  struct __timespec64 it_interval;
+  struct __timespec64 it_value;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 19/52] Y2038: add function __timer_gettime64
  2017-09-07 22:43                                   ` [RFC PATCH 18/52] Y2038: add struct __itimerspec64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                                     ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                                       ` [RFC PATCH 20/52] Y2038: add function __timer_settime64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 rt/Versions                             |  7 +++++++
 sysdeps/unix/sysv/linux/timer_gettime.c | 24 ++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/rt/Versions b/rt/Versions
index 91e3fd2a20..f07c8e2b18 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -37,4 +37,11 @@ librt {
   GLIBC_2.7 {
    __mq_open_2;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __timer_gettime64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c
index 849c56a30a..09aa6e5abf 100644
--- a/sysdeps/unix/sysv/linux/timer_gettime.c
+++ b/sysdeps/unix/sysv/linux/timer_gettime.c
@@ -39,3 +39,27 @@ timer_gettime (timer_t timerid, struct itimerspec *value)
 
   return res;
 }
+
+/* 64-bit time version */
+
+int
+__timer_gettime64 (timer_t timerid, struct __itimerspec64 *value)
+{
+  struct itimerspec value32;
+  struct timer *kt = (struct timer *) timerid;
+
+  if (__y2038_kernel_support())
+    return INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value);
+
+  int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, &value32);
+
+  if (res == 0)
+    {
+      value->it_value.tv_sec = value32.it_value.tv_sec;
+      value->it_value.tv_nsec = value32.it_value.tv_nsec;
+      value->it_interval.tv_sec = value32.it_interval.tv_sec;
+      value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+    }
+
+  return res;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 12/52] Y2038: add function __futimens64
  2017-09-07 22:43                     ` [RFC PATCH 11/52] Y2038: add function __timespec_get64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                       ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                         ` [RFC PATCH 13/52] Y2038: add function __utimensat64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 io/futimens.c                        |  9 +++++++++
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 sysdeps/unix/sysv/linux/futimens.c   | 38 ++++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+)

diff --git a/io/futimens.c b/io/futimens.c
index 27fc1ae6ef..516e64efde 100644
--- a/io/futimens.c
+++ b/io/futimens.c
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <time.h>
 #include <sysdep.h>
+#include <kernel_timespec.h>
 
 
 /* Change the access time of the file associated with FD to TSP[0] and
@@ -32,3 +33,11 @@ futimens (int fd, const struct timespec tsp[2])
   return -1;
 }
 stub_warning (futimens)
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__futimens64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index fd94c63672..08dfae2b61 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -33,5 +33,6 @@ libc {
     __clock_settime64;
     __clock_getres64;
     __clock_nanosleep64;
+    __futimens64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/futimens.c b/sysdeps/unix/sysv/linux/futimens.c
index b4985e034c..64f1a35663 100644
--- a/sysdeps/unix/sysv/linux/futimens.c
+++ b/sysdeps/unix/sysv/linux/futimens.c
@@ -36,3 +36,41 @@ futimens (int fd, const struct timespec tsp[2])
   /* Avoid implicit array coercion in syscall macros.  */
   return INLINE_SYSCALL (utimensat, 4, fd, NULL, &tsp[0], 0);
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__futimens64 (int fd, const struct __timespec64 tsp[2])
+{
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (fd < 0)
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+
+  if (__y2038_linux_support)
+    {
+      if (fd < 0)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EBADF);
+      ts64[0].tv_sec = tsp[0].tv_sec;
+      ts64[0].tv_nsec = tsp[0].tv_nsec;
+      ts64[0].tv_pad = 0;
+      ts64[1].tv_sec = tsp[1].tv_sec;
+      ts64[1].tv_nsec = tsp[1].tv_nsec;
+      ts64[1].tv_pad = 0;
+      return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64[0], 0);
+    }
+
+  if (tsp[0].tv_sec > INT_MAX || tsp[1].tv_sec > INT_MAX)
+    {
+      return EOVERFLOW;
+    }
+
+  ts32[0].tv_sec = tsp[0].tv_sec;
+  ts32[0].tv_nsec = tsp[0].tv_nsec;
+  ts32[1].tv_sec = tsp[1].tv_sec;
+  ts32[1].tv_nsec = tsp[1].tv_nsec;
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32[0], 0);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 11/52] Y2038: add function __timespec_get64
  2017-09-07 22:43                   ` [RFC PATCH 10/52] Y2038: add function __clock_nanosleep64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                     ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                       ` [RFC PATCH 12/52] Y2038: add function __futimens64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/timespec_get.c | 35 ++++++++++++++++++++++++++++++++++
 time/Versions                          |  7 +++++++
 2 files changed, 42 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index 1f63e57e39..b43b5aec7b 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -44,3 +44,38 @@ timespec_get (struct timespec *ts, int base)
 
   return base;
 }
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__timespec_get64 (struct __timespec64 *ts, int base)
+{
+  switch (base)
+    {
+      int res;
+      INTERNAL_SYSCALL_DECL (err);
+    case TIME_UTC:
+      if (__y2038_linux_support)
+      {
+        res = INTERNAL_VSYSCALL (clock_gettime64, err, 2, CLOCK_REALTIME, ts);
+      }
+      else
+      {
+        struct timespec ts32;
+        res = INTERNAL_VSYSCALL (clock_gettime, err, 2, CLOCK_REALTIME, &ts32);
+        if (INTERNAL_SYSCALL_ERROR_P (res, err))
+	  return 0;
+        ts->tv_sec = ts32.tv_sec;
+        ts->tv_nsec = ts32.tv_nsec;
+        ts->tv_pad = 0;
+      }
+      break;
+
+    default:
+      return 0;
+    }
+
+  return base;
+}
diff --git a/time/Versions b/time/Versions
index fd838181e4..3fe860862a 100644
--- a/time/Versions
+++ b/time/Versions
@@ -65,4 +65,11 @@ libc {
   GLIBC_2.16 {
     timespec_get;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __timespec_get64;
+  }
 }
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 21/52] Y2038: add function __timerfd_gettime64
  2017-09-07 22:43                                       ` [RFC PATCH 20/52] Y2038: add function __timer_settime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                                         ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                           ` [RFC PATCH 22/52] Y2038: add function __timerfd_settime64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Note: this tests the return value of function __y2038_kernel_support()
rather than the value of variable __y2038_linux_upport, because the
latter cannot be accessed from librt while the former can.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 rt/Makefile                                 |  3 +-
 rt/Versions                                 |  1 +
 rt/timerfd_gettime64.c                      | 28 ++++++++++++++++++
 sysdeps/unix/sysv/linux/timerfd_gettime64.c | 44 +++++++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 rt/timerfd_gettime64.c
 create mode 100644 sysdeps/unix/sysv/linux/timerfd_gettime64.c

diff --git a/rt/Makefile b/rt/Makefile
index 9740dc2ad8..56bfb856ae 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -32,7 +32,8 @@ clock-routines := get_clockfreq clock_getcpuclockid			\
 		  clock_getres clock_gettime clock_settime		\
 		  clock_nanosleep
 timer-routines := timer_create timer_delete timer_getoverr		\
-		  timer_gettime timer_settime
+		  timer_gettime timer_settime                           \
+		  timerfd_gettime64
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
diff --git a/rt/Versions b/rt/Versions
index 4933197aa5..254e36dd2d 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -44,5 +44,6 @@ librt {
   GLIBC_Y2038 {
     __timer_gettime64;
     __timer_settime64;
+    __timerfd_gettime64;
   }
 }
diff --git a/rt/timerfd_gettime64.c b/rt/timerfd_gettime64.c
new file mode 100644
index 0000000000..9496fcaef0
--- /dev/null
+++ b/rt/timerfd_gettime64.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+/* Get current value of timer TIMERID and store it in VLAUE.  */
+int
+__timerfd_gettime64 (int fd, struct itimerspec *value)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_gettime64)
diff --git a/sysdeps/unix/sysv/linux/timerfd_gettime64.c b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
new file mode 100644
index 0000000000..5843e23c8b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_gettime64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_gettime64 (int fd, struct __itimerspec64 *value)
+{
+  struct itimerspec value32;
+
+  if (__y2038_kernel_support())
+    return INLINE_SYSCALL (timerfd_gettime64, 2, fd, value);
+
+  int res = INLINE_SYSCALL (timerfd_gettime, 2, fd, &value32);
+
+  if (res == 0)
+    {
+      value->it_value.tv_sec = value32.it_value.tv_sec;
+      value->it_value.tv_nsec = value32.it_value.tv_nsec;
+      value->it_interval.tv_sec = value32.it_interval.tv_sec;
+      value->it_interval.tv_nsec = value32.it_interval.tv_nsec;
+    }
+
+  return res;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 16/52] Y2038: add function __futimes64
  2017-09-07 22:43                             ` [RFC PATCH 15/52] Y2038: add struct __timeval64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                               ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                                 ` [RFC PATCH 17/52] Y2038: add function __lutimes64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 misc/futimes.c                       |  9 +++++++
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 sysdeps/unix/sysv/linux/futimes.c    | 52 ++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)

diff --git a/misc/futimes.c b/misc/futimes.c
index 6dad9996fa..e4c9ee2239 100644
--- a/misc/futimes.c
+++ b/misc/futimes.c
@@ -30,3 +30,12 @@ __futimes (int fd, const struct timeval tvp[2])
 weak_alias (__futimes, futimes)
 
 stub_warning (futimes)
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__futimes64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index 630e3f8569..155b7889eb 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -36,5 +36,6 @@ libc {
     __futimens64;
     __utimensat64;
     __sigtimedwait64;
+    __futimes64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index af79cb1508..f30e6ad7a0 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -49,3 +49,55 @@ __futimes (int fd, const struct timeval tvp[2])
   return INLINE_SYSCALL (utimensat, 4, fd, NULL, tvp ? &ts : NULL, 0);
 }
 weak_alias (__futimes, futimes)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__futimes64 (int fd, const struct __timeval64 tvp[2])
+{
+  /* The utimensat system call expects timespec not timeval.  */
+  struct __timespec64 ts64[2];
+  struct timespec ts32[2];
+
+  if (__y2038_linux_support)
+    {
+      if (tvp != NULL)
+        {
+          if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+              || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+  	    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+        
+          ts64[0].tv_sec = tvp[0].tv_sec;
+          ts64[0].tv_nsec = tvp[0].tv_usec * 1000;
+          ts64[0].tv_pad = 0;
+          ts64[1].tv_sec = tvp[1].tv_sec;
+          ts64[1].tv_nsec = tvp[1].tv_usec * 1000;
+          ts64[1].tv_pad = 0;
+        
+          return INLINE_SYSCALL (utimensat64, 4, fd, NULL, &ts64, 0);
+        }
+    
+      return INLINE_SYSCALL (utimensat64, 4, fd, NULL, NULL, 0);
+    }
+
+  if (tvp != NULL)
+    {
+      if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000
+          || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+    
+      if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+        return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
+    
+      ts32[0].tv_sec = tvp[0].tv_sec;
+      ts32[0].tv_nsec = tvp[0].tv_usec * 1000;
+      ts32[1].tv_sec = tvp[1].tv_sec;
+      ts32[1].tv_nsec = tvp[1].tv_usec * 1000;
+    
+      return INLINE_SYSCALL (utimensat, 4, fd, NULL, &ts32, 0);
+    }
+
+  return INLINE_SYSCALL (utimensat, 4, fd, NULL, NULL, 0);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 20/52] Y2038: add function __timer_settime64
  2017-09-07 22:43                                     ` [RFC PATCH 19/52] Y2038: add function __timer_gettime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:43                                       ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:43                                         ` [RFC PATCH 21/52] Y2038: add function __timerfd_gettime64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:43 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 rt/Versions                             |  1 +
 sysdeps/unix/sysv/linux/timer_settime.c | 49 +++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/rt/Versions b/rt/Versions
index f07c8e2b18..4933197aa5 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -43,5 +43,6 @@ librt {
 
   GLIBC_Y2038 {
     __timer_gettime64;
+    __timer_settime64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index ba35036355..d75b24ada8 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -41,3 +41,52 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
 
   return res;
 }
+
+/* 64-bit time version */
+
+int
+__timer_settime64 (timer_t timerid, int flags, const struct itimerspec *value,
+                   struct itimerspec *ovalue)
+{
+  struct timer *kt = (struct timer *) timerid;
+  struct __itimerspec64 value64;
+  struct itimerspec value32, ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+  if (__y2038_kernel_support())
+    {
+      value64.it_value.tv_sec = value->it_value.tv_sec;
+      value64.it_value.tv_nsec = value->it_value.tv_nsec;
+      value64.it_value.tv_pad = 0;
+      value64.it_interval.tv_sec = value->it_interval.tv_sec;
+      value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+      value64.it_interval.tv_pad = 0;
+    
+      return INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags,
+  			    &value64, ovalue);
+    }
+
+  if (value->it_value.tv_sec > INT_MAX
+      || value->it_interval.tv_sec > INT_MAX)
+    return EOVERFLOW;
+
+  value32.it_value.tv_sec = value->it_value.tv_sec;
+  value32.it_value.tv_nsec = value->it_value.tv_nsec;
+  value32.it_interval.tv_sec = value->it_interval.tv_sec;
+  value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+  int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
+        &value32, &ovalue32);
+
+  if (res == 0 && ovalue != NULL)
+    {
+      ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+      ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+      ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+      ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+    }
+
+  return res;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 31/52] Y2038: add function __gettimeofday_t64
  2017-09-07 22:44                                                           ` [RFC PATCH 30/52] Y2038: add function __utimes_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                             ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                               ` [RFC PATCH 32/52] Y2038: add function __settimeofday_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Implementing a 64-bit settimeofday requires adding a new
file to build under time/ and we cannot name that new file
'settimeofday.c' or it will break the 32-bit settimeofday
symbol, so we call it 'settimeofday64.c'.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/gettimeofday.c | 26 ++++++++++++++++++++++++++
 time/Versions                          |  1 +
 time/gettimeofday.c                    | 10 ++++++++++
 3 files changed, 37 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/gettimeofday.c b/sysdeps/unix/sysv/linux/gettimeofday.c
index 6afa407ac4..5ebbddef4f 100644
--- a/sysdeps/unix/sysv/linux/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/gettimeofday.c
@@ -37,3 +37,29 @@ __gettimeofday (struct timeval *tv, struct timezone *tz)
 libc_hidden_def (__gettimeofday)
 weak_alias (__gettimeofday, gettimeofday)
 libc_hidden_weak (gettimeofday)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__gettimeofday_t64 (struct __timeval64 *tv, struct timezone *tz)
+{
+  struct timeval tv32;
+  int result;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: implement using 64-bit time syscall */
+    }
+
+  result = INLINE_VSYSCALL (gettimeofday, 2, &tv32, tz);
+
+  if (result == 0)
+    {
+      tv->tv_sec = tv32.tv_sec;
+      tv->tv_usec = tv32.tv_usec;
+    }
+
+  return result;
+}
diff --git a/time/Versions b/time/Versions
index 3dca51abcb..7daf158a8b 100644
--- a/time/Versions
+++ b/time/Versions
@@ -73,5 +73,6 @@ libc {
     __timespec_get64;
     __time_t64;
     __stime_t64;
+    __gettimeofday_t64;
   }
 }
diff --git a/time/gettimeofday.c b/time/gettimeofday.c
index 1d675b6b23..b21d7d4b71 100644
--- a/time/gettimeofday.c
+++ b/time/gettimeofday.c
@@ -32,3 +32,13 @@ weak_alias (__gettimeofday, gettimeofday)
 libc_hidden_weak (gettimeofday)
 
 stub_warning (gettimeofday)
+
+/* 64-bit time version */
+
+int
+__gettimeofday_t64 (struct timeval *tv, struct timezone *tz)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__gettimeofday_t64)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 28/52] Y2038: add function __time_t64
  2017-09-07 22:44                                                     ` [RFC PATCH 27/52] Y2038: add function __fstatat64_t64 (and __fxstatat_t64) Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                       ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                         ` [RFC PATCH 29/52] Y2038: add function __stime_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

These implementations use only 32-bit time kernel syscalls.

Therefore, stime() will always set errno to EOVERFLOW and return -1 for dates beyond Y2038.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/posix/time.c           | 26 ++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/time.c | 22 ++++++++++++++++++++++
 time/Versions                  |  1 +
 time/time.c                    | 13 +++++++++++++
 4 files changed, 62 insertions(+)

diff --git a/sysdeps/posix/time.c b/sysdeps/posix/time.c
index 32ca177514..a4c4a03c55 100644
--- a/sysdeps/posix/time.c
+++ b/sysdeps/posix/time.c
@@ -38,3 +38,29 @@ time (time_t *t)
   return result;
 }
 libc_hidden_def (time)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+__time64_t
+__time_t64 (__time64_t *t)
+{
+  struct timeval tv32;
+  __time64_t result;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using 64-bit time syscall */
+  }
+
+  if (__gettimeofday (&tv32, (struct timezone *) NULL))
+    result = (__time64_t) -1;
+  else
+    result = (__time64_t) tv32.tv_sec;
+
+  if (t != NULL)
+    *t = result;
+
+  return result;
+}
diff --git a/sysdeps/unix/sysv/linux/time.c b/sysdeps/unix/sysv/linux/time.c
index 72d4040cbc..b6c7e61844 100644
--- a/sysdeps/unix/sysv/linux/time.c
+++ b/sysdeps/unix/sysv/linux/time.c
@@ -34,6 +34,28 @@ time (time_t *t)
 }
 libc_hidden_def (time)
 
+/* 64-BIT TIME VERSION */
+
+extern int __y2038_linux_support;
+
+__time64_t
+__time_t64 (__time64_t *t)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  __time64_t res;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: implement using 64-bit time syscall */
+    }
+
+  res = INTERNAL_SYSCALL (time, err, 1, NULL);
+  /* There cannot be any error.  */
+  if (t != NULL)
+    *t = res;
+  return res;
+}
+
 #else
 
 # include <sysdeps/posix/time.c>
diff --git a/time/Versions b/time/Versions
index 3fe860862a..02dc8d6146 100644
--- a/time/Versions
+++ b/time/Versions
@@ -71,5 +71,6 @@ libc {
 
   GLIBC_Y2038 {
     __timespec_get64;
+    __time_t64;
   }
 }
diff --git a/time/time.c b/time/time.c
index e375035265..a487068468 100644
--- a/time/time.c
+++ b/time/time.c
@@ -31,3 +31,16 @@ time (time_t *timer)
 libc_hidden_def (time)
 
 stub_warning (time)
+
+/* 64-bit time version */
+
+__time64_t
+__time_t64 (__time64_ *timer)
+{
+  __set_errno (ENOSYS);
+
+  if (timer != NULL)
+    *timer = (__time64_t) -1;
+  return (__time64_t) -1;
+}
+libc_hidden_def (__time_t64)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 24/52] Y2038: add function __fstat64_t64 (and __fxstat64_t64)
  2017-09-07 22:44                                             ` [RFC PATCH 23/52] Y2038: add struct __stat64_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                               ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                 ` [RFC PATCH 25/52] Y2038: add function __stat64_t64 (and __xstat64_t64) Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/stat.h                 |  2 ++
 io/Versions                        |  7 ++++++
 io/fstat64.c                       |  7 ++++++
 sysdeps/unix/sysv/linux/fxstat64.c | 50 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 300cf8bbc4..2961849e35 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -37,6 +37,8 @@ extern __mode_t __umask (__mode_t __mask);
 extern int __mkdir (const char *__path, __mode_t __mode);
 extern int __mknod (const char *__path,
 		    __mode_t __mode, __dev_t __dev);
+extern int __fxstat64_t64 (int __ver, int __fildes,
+                           struct __stat64_t64 *__stat_buf);
 #if IS_IN (libc) || IS_IN (rtld)
 hidden_proto (__fxstat)
 hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index 64316cd025..747ae5d9d6 100644
--- a/io/Versions
+++ b/io/Versions
@@ -125,4 +125,11 @@ libc {
   GLIBC_2.23 {
     fts64_children; fts64_close; fts64_open; fts64_read; fts64_set;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __fxstat64_t64;
+  }
 }
diff --git a/io/fstat64.c b/io/fstat64.c
index 69c80e5e45..a972304c0a 100644
--- a/io/fstat64.c
+++ b/io/fstat64.c
@@ -50,3 +50,10 @@ fstat64 (int fd, struct stat64 *buf)
 {
   return __fxstat64 (_STAT_VER, fd, buf);
 }
+
+int
+attribute_hidden
+__fstat64_t64 (int fd, struct __stat64_t64 *buf)
+{
+  return __fxstat64_t64 (_STAT_VER, fd, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c
index 8a59d86d31..6097257b2a 100644
--- a/sysdeps/unix/sysv/linux/fxstat64.c
+++ b/sysdeps/unix/sysv/linux/fxstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file FD in BUF.  */
@@ -51,3 +53,51 @@ hidden_ver (___fxstat64, __fxstat64)
 strong_alias (___fxstat64, __fxstat64)
 hidden_def (__fxstat64)
 #endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__fxstat64_t64 (int vers, int fd, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscalls when they become available
+    }
+
+  result = INLINE_SYSCALL (fstat64, 2, fd, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+      buf->__pad1		     = st64.__pad1;
+    
+      buf->__st_ino        = st64.__st_ino;
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->__pad2          = st64.__pad2;
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 26/52] Y2038: add function __lstat64_t64 (and __lxstat64_t64)
  2017-09-07 22:44                                                 ` [RFC PATCH 25/52] Y2038: add function __stat64_t64 (and __xstat64_t64) Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                   ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                     ` [RFC PATCH 27/52] Y2038: add function __fstatat64_t64 (and __fxstatat_t64) Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/stat.h                 |  2 ++
 io/Versions                        |  1 +
 io/lstat64.c                       |  7 ++++++
 sysdeps/unix/sysv/linux/lxstat64.c | 50 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 8cd3fbedae..9b0782a9a4 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -41,6 +41,8 @@ extern int __fxstat64_t64 (int __ver, int __fildes,
                            struct __stat64_t64 *__stat_buf);
 extern int __xstat64_t64 (int __ver, const char *__filename,
                           struct __stat64_t64 *__stat_buf);
+extern int __lxstat64_t64 (int __ver, const char *__filename,
+		           struct __stat64_t64 *__stat_buf);
 #if IS_IN (libc) || IS_IN (rtld)
 hidden_proto (__fxstat)
 hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index e2befdbdf7..fcd1b71f80 100644
--- a/io/Versions
+++ b/io/Versions
@@ -132,5 +132,6 @@ libc {
   GLIBC_Y2038 {
     __fxstat64_t64;
     __xstat64_t64;
+    __lxstat64_t64;
   }
 }
diff --git a/io/lstat64.c b/io/lstat64.c
index c29492aa9f..50bf7df493 100644
--- a/io/lstat64.c
+++ b/io/lstat64.c
@@ -50,3 +50,10 @@ lstat64 (const char *file, struct stat64 *buf)
 {
   return __lxstat64 (_STAT_VER, file, buf);
 }
+
+int
+attribute_hidden
+__lstat64_t64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __lxstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/lxstat64.c b/sysdeps/unix/sysv/linux/lxstat64.c
index 9bc548f91c..dbea8a7654 100644
--- a/sysdeps/unix/sysv/linux/lxstat64.c
+++ b/sysdeps/unix/sysv/linux/lxstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file NAME in BUF.  */
@@ -50,3 +52,51 @@ hidden_ver (___lxstat64, __lxstat64)
 strong_alias (___lxstat64, __lxstat64);
 hidden_def (__lxstat64)
 #endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__lxstat64_t64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscalls when they become available
+    }
+
+  result = INLINE_SYSCALL (lstat64, 2, name, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+      buf->__pad1		     = st64.__pad1;
+    
+      buf->__st_ino        = st64.__st_ino;
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->__pad2          = st64.__pad2;
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 27/52] Y2038: add function __fstatat64_t64 (and __fxstatat_t64)
  2017-09-07 22:44                                                   ` [RFC PATCH 26/52] Y2038: add function __lstat64_t64 (and __lxstat64_t64) Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                     ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                       ` [RFC PATCH 28/52] Y2038: add function __time_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/stat.h                   |  4 +++
 io/Versions                          |  1 +
 io/fstatat64.c                       |  7 +++++
 sysdeps/unix/sysv/linux/fxstatat64.c | 54 ++++++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 9b0782a9a4..71f6d63e3e 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -43,6 +43,10 @@ extern int __xstat64_t64 (int __ver, const char *__filename,
                           struct __stat64_t64 *__stat_buf);
 extern int __lxstat64_t64 (int __ver, const char *__filename,
 		           struct __stat64_t64 *__stat_buf);
+extern int __fxstatat64_t64 (int __ver, int __fildes,
+                             const char *__filename,
+			     struct __stat64_t64 *__stat_buf,
+                             int __flag);
 #if IS_IN (libc) || IS_IN (rtld)
 hidden_proto (__fxstat)
 hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index fcd1b71f80..33629a0d4e 100644
--- a/io/Versions
+++ b/io/Versions
@@ -133,5 +133,6 @@ libc {
     __fxstat64_t64;
     __xstat64_t64;
     __lxstat64_t64;
+    __fxstatat64_t64;
   }
 }
diff --git a/io/fstatat64.c b/io/fstatat64.c
index 13a9ebc870..4e13f072ff 100644
--- a/io/fstatat64.c
+++ b/io/fstatat64.c
@@ -50,3 +50,10 @@ fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
 {
   return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
 }
+
+int
+attribute_hidden
+__fstatat64_t64 (int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  return __fxstatat64_t64 (_STAT_VER, fd, file, buf, flag);
+}
diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c
index ef1e132c11..070ed78861 100644
--- a/sysdeps/unix/sysv/linux/fxstatat64.c
+++ b/sysdeps/unix/sysv/linux/fxstatat64.c
@@ -26,6 +26,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 /* Get information about the file NAME in BUF.  */
 
 int
@@ -45,3 +47,55 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
 								      err));
 }
 libc_hidden_def (__fxstatat64)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__fxstatat64_t64 (int vers, int fd, const char *file, struct __stat64_t64 *buf, int flag)
+{
+  if (__glibc_unlikely (vers != _STAT_VER_LINUX))
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+  int result;
+  struct stat64 st64;
+  INTERNAL_SYSCALL_DECL (err);
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscalls when they become available
+    }
+
+  result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, &st64, flag);
+  if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1))
+    {
+      buf->st_dev          = st64.st_dev;
+      buf->__pad1		     = st64.__pad1;
+    
+      buf->__st_ino        = st64.__st_ino;
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->__pad2          = st64.__pad2;
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_atim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    
+      return 0;
+    }
+  else
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result,
+								      err));
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 33/52] Y2038: add function __mq_timedsend_t64
  2017-09-07 22:44                                                               ` [RFC PATCH 32/52] Y2038: add function __settimeofday_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                                 ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                                   ` [RFC PATCH 34/52] Y2038: add function __mq_timedreceive_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 rt/Makefile              |  3 ++-
 rt/Versions              |  1 +
 rt/mq_timedreceive_t64.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)
 create mode 100644 rt/mq_timedreceive_t64.c

diff --git a/rt/Makefile b/rt/Makefile
index 2a6be1bcbf..0b529233b5 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -37,7 +37,8 @@ timer-routines := timer_create timer_delete timer_getoverr		\
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
-		  mq_timedreceive
+		  mq_timedreceive					\
+		  mq_timedreceive_t64
 
 routines = $(clock-routines)
 
diff --git a/rt/Versions b/rt/Versions
index 761fbb8a4c..cb88f7196c 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -46,5 +46,6 @@ librt {
     __timer_settime64;
     __timerfd_gettime64;
     __timerfd_settime64;
+    __mq_timedreceive_t64;
   }
 }
diff --git a/rt/mq_timedreceive_t64.c b/rt/mq_timedreceive_t64.c
new file mode 100644
index 0000000000..54ba50fe84
--- /dev/null
+++ b/rt/mq_timedreceive_t64.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <mqueue.h>
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+/* Receive the oldest from highest priority messages in message queue
+   MQDES, stop waiting if ABS_TIMEOUT expires.  */
+ssize_t
+__mq_timedreceive_t64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len,
+		 unsigned int *__restrict msg_prio,
+		 const struct timespec *__restrict abs_timeout)
+{
+  struct timespec ts32, *tsp32 = NULL;
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscall */
+    }
+
+  if (abs_timeout)
+    {
+      ts32.tv_sec = abs_timeout->tv_sec;
+      ts32.tv_nsec = abs_timeout->tv_nsec;
+      tsp32 = &ts32;
+    }
+  return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, tsp32);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 22/52] Y2038: add function __timerfd_settime64
  2017-09-07 22:43                                         ` [RFC PATCH 21/52] Y2038: add function __timerfd_gettime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                           ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                             ` [RFC PATCH 23/52] Y2038: add struct __stat64_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Note: this tests the return value of function __y2038_kernel_support()
rather than the value of variable __y2038_linux_upport, because the
latter cannot be accessed from librt while the former can.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 rt/Makefile                                 |  2 +-
 rt/Versions                                 |  1 +
 rt/timerfd_settime64.c                      | 29 ++++++++++++
 sysdeps/unix/sysv/linux/timerfd_settime64.c | 71 +++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 rt/timerfd_settime64.c
 create mode 100644 sysdeps/unix/sysv/linux/timerfd_settime64.c

diff --git a/rt/Makefile b/rt/Makefile
index 56bfb856ae..2a6be1bcbf 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -33,7 +33,7 @@ clock-routines := get_clockfreq clock_getcpuclockid			\
 		  clock_nanosleep
 timer-routines := timer_create timer_delete timer_getoverr		\
 		  timer_gettime timer_settime                           \
-		  timerfd_gettime64
+		  timerfd_gettime64 timerfd_settime64
 shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
diff --git a/rt/Versions b/rt/Versions
index 254e36dd2d..761fbb8a4c 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -45,5 +45,6 @@ librt {
     __timer_gettime64;
     __timer_settime64;
     __timerfd_gettime64;
+    __timerfd_settime64;
   }
 }
diff --git a/rt/timerfd_settime64.c b/rt/timerfd_settime64.c
new file mode 100644
index 0000000000..8551c7adb0
--- /dev/null
+++ b/rt/timerfd_settime64.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1999-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+/* Set timer TIMERID to VALUE, returning old value in OVLAUE.  */
+int
+__timerfd_settime64 (int fd, int flags, const struct itimerspec *value,
+	       struct itimerspec *ovalue)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__timerfd_settime64)
diff --git a/sysdeps/unix/sysv/linux/timerfd_settime64.c b/sysdeps/unix/sysv/linux/timerfd_settime64.c
new file mode 100644
index 0000000000..9701452c0a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/timerfd_settime64.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sysdep.h>
+#include "kernel-posix-timers.h"
+
+int
+__timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
+	             struct __itimerspec64 *ovalue)
+{
+  int res;
+  struct __itimerspec64 value64;
+  struct itimerspec value32;
+  struct itimerspec ovalue32;
+
+  if (value == NULL)
+    return EFAULT;
+
+  if (__y2038_kernel_support())
+    {
+      value64.it_value.tv_sec = value->it_value.tv_sec;
+      value64.it_value.tv_nsec = value->it_value.tv_nsec;
+      value64.it_value.tv_pad = 0;
+      value64.it_interval.tv_sec = value->it_interval.tv_sec;
+      value64.it_interval.tv_nsec = value->it_interval.tv_nsec;
+      value64.it_interval.tv_pad = 0;
+      
+      return INLINE_SYSCALL (timerfd_settime64, 4, fd, flags,
+                             &value64, ovalue);
+    }
+
+  if (value->it_value.tv_sec > INT_MAX
+      || value->it_interval.tv_sec > INT_MAX)
+    return EOVERFLOW;
+
+  value32.it_value.tv_sec = value->it_value.tv_sec;
+  value32.it_value.tv_nsec = value->it_value.tv_nsec;
+  value32.it_interval.tv_sec = value->it_interval.tv_sec;
+  value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+  res = INLINE_SYSCALL (timerfd_settime, 4, fd, flags,
+                        &value32, &ovalue32);
+
+  if (res == 0 && ovalue != NULL)
+    {
+      ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+      ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+      ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+      ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+    }
+
+  return res;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 32/52] Y2038: add function __settimeofday_t64
  2017-09-07 22:44                                                             ` [RFC PATCH 31/52] Y2038: add function __gettimeofday_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                               ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                                 ` [RFC PATCH 33/52] Y2038: add function __mq_timedsend_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Implementing a 64-bit settimeofday requires adding a new
file to build under time/ and we cannot name that new file
'settimeofday.c' or it will break the 32-bit settimeofday
symbol, so we call it 'settimeofday64.c'.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/settimeofday64.c | 44 ++++++++++++++++++++++++++++++++
 time/Makefile                            |  3 ++-
 time/Versions                            |  1 +
 time/settimeofday.c                      |  8 ++++++
 4 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/settimeofday64.c

diff --git a/sysdeps/unix/sysv/linux/settimeofday64.c b/sysdeps/unix/sysv/linux/settimeofday64.c
new file mode 100644
index 0000000000..7aaef1c613
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/settimeofday64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#include <errno.h>
+#include <sys/time.h>
+
+extern int __y2038_linux_support;
+
+int __settimeofday_t64(const struct __timeval64 *tv,
+                       const struct timezone *tz)
+{
+  struct timeval tv32;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscall */
+    }
+
+  if (tv && tv->tv_sec > INT_MAX)
+    {
+      __set_errno(EOVERFLOW);
+      return -1;
+    }
+
+  tv32.tv_sec = tv->tv_sec;
+  tv32.tv_usec = tv->tv_usec;
+
+  return settimeofday(&tv32, tz);
+}
diff --git a/time/Makefile b/time/Makefile
index 317c4d8901..5fb26f6dbf 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -36,7 +36,8 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
-	    timespec_get
+	    timespec_get                                 \
+	    settimeofday64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index 7daf158a8b..d420770af3 100644
--- a/time/Versions
+++ b/time/Versions
@@ -74,5 +74,6 @@ libc {
     __time_t64;
     __stime_t64;
     __gettimeofday_t64;
+    __settimeofday_t64;
   }
 }
diff --git a/time/settimeofday.c b/time/settimeofday.c
index 317c93d35f..65db5ab6e5 100644
--- a/time/settimeofday.c
+++ b/time/settimeofday.c
@@ -29,3 +29,11 @@ __settimeofday (const struct timeval *tv, const struct timezone *tz)
 stub_warning (settimeofday)
 
 weak_alias (__settimeofday, settimeofday)
+
+int
+__settimeofday_t64 (const struct timeval *tv, const struct timezone *tz)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__settimeofday_t64)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 34/52] Y2038: add function __mq_timedreceive_t64
  2017-09-07 22:44                                                                 ` [RFC PATCH 33/52] Y2038: add function __mq_timedsend_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                                   ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                                     ` [RFC PATCH 35/52] Y2038: add function __msgctl_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 rt/Makefile           |  2 +-
 rt/Versions           |  1 +
 rt/mq_timedsend_t64.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 rt/mq_timedsend_t64.c

diff --git a/rt/Makefile b/rt/Makefile
index 0b529233b5..a1dccd048d 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -38,7 +38,7 @@ shm-routines   := shm_open shm_unlink
 mq-routines    := mq_open mq_close mq_unlink mq_getattr mq_setattr	\
 		  mq_notify mq_send mq_receive mq_timedsend		\
 		  mq_timedreceive					\
-		  mq_timedreceive_t64
+		  mq_timedreceive_t64 mq_timedsend_t64
 
 routines = $(clock-routines)
 
diff --git a/rt/Versions b/rt/Versions
index cb88f7196c..1eef2e604f 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -47,5 +47,6 @@ librt {
     __timerfd_gettime64;
     __timerfd_settime64;
     __mq_timedreceive_t64;
+    __mq_timedsend_t64;
   }
 }
diff --git a/rt/mq_timedsend_t64.c b/rt/mq_timedsend_t64.c
new file mode 100644
index 0000000000..27cf166547
--- /dev/null
+++ b/rt/mq_timedsend_t64.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <mqueue.h>
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+/* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
+   on full message queue if ABS_TIMEOUT expires.  */
+int
+__mq_timedsend_t64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
+	      unsigned int msg_prio, const struct __timespec64 *abs_timeout)
+{
+  struct timespec ts32, *tsp32 = NULL;
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscall */
+    }
+
+  if (abs_timeout)
+    {
+      ts32.tv_sec = abs_timeout->tv_sec;
+      ts32.tv_nsec = abs_timeout->tv_nsec;
+      tsp32 = &ts32;
+    }
+  return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, tsp32);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 30/52] Y2038: add function __utimes_t64
  2017-09-07 22:44                                                         ` [RFC PATCH 29/52] Y2038: add function __stime_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                           ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                             ` [RFC PATCH 31/52] Y2038: add function __gettimeofday_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/time.h                   |  6 ++++++
 misc/utimes.c                        | 15 +++++++++++++++
 sysdeps/unix/sysv/linux/arm/Versions |  1 +
 sysdeps/unix/sysv/linux/utimes.c     | 31 +++++++++++++++++++++++++++++++
 4 files changed, 53 insertions(+)

diff --git a/include/sys/time.h b/include/sys/time.h
index 95c431f7b3..b46873f6f4 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -20,6 +20,9 @@
 # include <time/sys/time.h>
 
 # ifndef _ISOMAC
+
+#  include <include/time.h>
+
 extern int __gettimeofday (struct timeval *__tv,
 			   struct timezone *__tz);
 libc_hidden_proto (__gettimeofday)
@@ -39,5 +42,8 @@ extern int __utimes (const char *__file, const struct timeval __tvp[2])
 	attribute_hidden;
 extern int __futimes (int fd, const struct timeval tvp[2]) attribute_hidden;
 
+extern int __utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+	attribute_hidden;
+
 # endif
 #endif
diff --git a/misc/utimes.c b/misc/utimes.c
index 73d91ace1c..5bb1a6f963 100644
--- a/misc/utimes.c
+++ b/misc/utimes.c
@@ -37,3 +37,18 @@ __utimes (const char *file, const struct timeval tvp[2])
 weak_alias (__utimes, utimes)
 
 stub_warning (utimes)
+
+int
+__utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+{
+  if (file == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__utimes_t64)
diff --git a/sysdeps/unix/sysv/linux/arm/Versions b/sysdeps/unix/sysv/linux/arm/Versions
index edac9cf007..68a4cb7384 100644
--- a/sysdeps/unix/sysv/linux/arm/Versions
+++ b/sysdeps/unix/sysv/linux/arm/Versions
@@ -38,5 +38,6 @@ libc {
     __sigtimedwait64;
     __futimes64;
     __lutimes64;
+    __utimes_t64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/utimes.c b/sysdeps/unix/sysv/linux/utimes.c
index 038ff20ba0..91d1ac2b53 100644
--- a/sysdeps/unix/sysv/linux/utimes.c
+++ b/sysdeps/unix/sysv/linux/utimes.c
@@ -34,3 +34,34 @@ __utimes (const char *file, const struct timeval tvp[2])
 }
 
 weak_alias (__utimes, utimes)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__utimes_t64 (const char *file, const struct __timeval64 tvp[2])
+{
+  struct timeval tv32[2], *tvp32 = NULL;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: implement using 64-bit time syscall */
+    }
+
+  if (tvp != NULL)
+    {
+      if (tvp[0].tv_sec > INT_MAX || tvp[1].tv_sec > INT_MAX)
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+      tv32[0].tv_sec = tvp[0].tv_sec;
+      tv32[0].tv_usec = tvp[0].tv_usec;
+      tv32[1].tv_sec = tvp[1].tv_sec;
+      tv32[1].tv_usec = tvp[1].tv_usec;
+      tvp32 = tv32;
+    }
+
+  return INLINE_SYSCALL (utimes, 2, file, tvp32);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 25/52] Y2038: add function __stat64_t64 (and __xstat64_t64)
  2017-09-07 22:44                                               ` [RFC PATCH 24/52] Y2038: add function __fstat64_t64 (and __fxstat64_t64) Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                 ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                   ` [RFC PATCH 26/52] Y2038: add function __lstat64_t64 (and __lxstat64_t64) Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

There is no Y2038-proof linux struct stat for now, so these
implementations just use the existing syscalls and convert from kernel
32-bit-time struct stat64 to GLIBC Y2038-ready struct __stat64_t64.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/stat.h                |  2 ++
 io/Versions                       |  1 +
 io/stat64.c                       |  7 ++++++
 sysdeps/unix/sysv/linux/xstat64.c | 50 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 2961849e35..8cd3fbedae 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -39,6 +39,8 @@ extern int __mknod (const char *__path,
 		    __mode_t __mode, __dev_t __dev);
 extern int __fxstat64_t64 (int __ver, int __fildes,
                            struct __stat64_t64 *__stat_buf);
+extern int __xstat64_t64 (int __ver, const char *__filename,
+                          struct __stat64_t64 *__stat_buf);
 #if IS_IN (libc) || IS_IN (rtld)
 hidden_proto (__fxstat)
 hidden_proto (__fxstat64)
diff --git a/io/Versions b/io/Versions
index 747ae5d9d6..e2befdbdf7 100644
--- a/io/Versions
+++ b/io/Versions
@@ -131,5 +131,6 @@ libc {
 
   GLIBC_Y2038 {
     __fxstat64_t64;
+    __xstat64_t64;
   }
 }
diff --git a/io/stat64.c b/io/stat64.c
index 704cbb34a6..22fc0db13d 100644
--- a/io/stat64.c
+++ b/io/stat64.c
@@ -50,3 +50,10 @@ stat64 (const char *file, struct stat64 *buf)
 {
   return __xstat64 (_STAT_VER, file, buf);
 }
+
+int
+attribute_hidden
+__stat64_t64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __xstat64_t64 (_STAT_VER, file, buf);
+}
diff --git a/sysdeps/unix/sysv/linux/xstat64.c b/sysdeps/unix/sysv/linux/xstat64.c
index b3fbe6a383..325ed36d1d 100644
--- a/sysdeps/unix/sysv/linux/xstat64.c
+++ b/sysdeps/unix/sysv/linux/xstat64.c
@@ -24,6 +24,8 @@
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#include <xstatconv.h>
+
 #include <kernel-features.h>
 
 /* Get information about the file NAME in BUF.  */
@@ -52,3 +54,51 @@ hidden_ver (___xstat64, __xstat64)
 strong_alias (___xstat64, __xstat64)
 hidden_def (__xstat64)
 #endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__xstat64_t64 (int vers, const char *name, struct __stat64_t64 *buf)
+{
+  int result;
+  struct stat64 st64;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscalls when they become available
+    }
+
+  result = INLINE_SYSCALL (stat64, 2, name, &st64);
+#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT
+  if (__builtin_expect (!result, 1) && st64.__st_ino != (__ino_t) st64.st_ino)
+    st64.st_ino = st64.__st_ino;
+#endif
+  if (!result)
+    {
+      buf->st_dev          = st64.st_dev;
+      buf->__pad1		     = st64.__pad1;
+    
+      buf->__st_ino        = st64.__st_ino;
+      buf->st_mode         = st64.st_mode;
+      buf->st_nlink        = st64.st_nlink;
+      buf->st_uid          = st64.st_uid;		 
+      buf->st_gid          = st64.st_gid;		 
+      buf->st_rdev         = st64.st_rdev;		 
+      buf->__pad2          = st64.__pad2;
+      buf->st_size         = st64.st_size;		 
+      buf->st_blksize      = st64.st_blksize;
+    
+      buf->st_blocks       = st64.st_blocks;		
+      buf->st_atim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_atim.tv_nsec = st64.st_atim.tv_nsec;	
+      buf->st_mtim.tv_sec  = st64.st_mtim.tv_sec;	
+      buf->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;	
+      buf->st_ctim.tv_sec  = st64.st_ctim.tv_sec;	
+      buf->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;	
+    
+      buf->st_ino          = st64.st_ino;
+    }
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 35/52] Y2038: add function __msgctl_t64
  2017-09-07 22:44                                                                   ` [RFC PATCH 34/52] Y2038: add function __mq_timedreceive_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                                     ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                       ` [RFC PATCH 36/52] Y2038: add function __sched_rr_get_interval_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/Versions   |  7 ++++
 sysdeps/unix/sysv/linux/bits/msq.h | 20 +++++++++++
 sysdeps/unix/sysv/linux/msgctl.c   | 72 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 202ffccc29..3fcd1c252b 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -172,4 +172,11 @@ libc {
     # functions used by nscd
     __netlink_assert_response;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __msgctl_t64;
+  }
 }
diff --git a/sysdeps/unix/sysv/linux/bits/msq.h b/sysdeps/unix/sysv/linux/bits/msq.h
index 31c4863e7b..ba3f24f720 100644
--- a/sysdeps/unix/sysv/linux/bits/msq.h
+++ b/sysdeps/unix/sysv/linux/bits/msq.h
@@ -35,6 +35,25 @@ typedef unsigned long int msglen_t;
 
 /* Structure of record for one message inside the kernel.
    The type `struct msg' is opaque.  */
+#ifdef __USE_TIME_BITS64
+struct msqid_ds
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved1;
+  __time64_t msg_rtime;		/* time of last msgrcv command */
+  unsigned long int __glibc_reserved2;
+  __time64_t msg_ctime;		/* time of last change */
+  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  unsigned long int __glibc_reserved4;
+  unsigned long int __glibc_reserved5;
+};
+#else
 struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
@@ -52,6 +71,7 @@ struct msqid_ds
   unsigned long int __glibc_reserved4;
   unsigned long int __glibc_reserved5;
 };
+#endif
 
 #ifdef __USE_MISC
 
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index e5ae621420..d62faf71ce 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -69,3 +69,75 @@ __old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf)
 }
 compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0);
 #endif
+
+/* 64-bit time version */
+
+struct __msqid_ds_t64
+{
+  struct ipc_perm msg_perm;	/* structure describing operation permission */
+  __time64_t msg_stime;		/* time of last msgsnd command */
+  unsigned long int __glibc_reserved1;
+  __time64_t msg_rtime;		/* time of last msgrcv command */
+  unsigned long int __glibc_reserved2;
+  __time64_t msg_ctime;		/* time of last change */
+  unsigned long int __glibc_reserved3;
+  unsigned long int __msg_cbytes; /* current number of bytes on queue */
+  msgqnum_t msg_qnum;		/* number of messages currently on queue */
+  msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
+  __pid_t msg_lspid;		/* pid of last msgsnd() */
+  __pid_t msg_lrpid;		/* pid of last msgrcv() */
+  unsigned long int __glibc_reserved4;
+  unsigned long int __glibc_reserved5;
+};
+
+extern int __y2038_linux_support;
+
+int
+__msgctl_t64 (int msqid, int cmd, struct __msqid_ds_t64 *buf)
+{
+  int result;
+  struct msqid_ds buf32, *pbuf32 = NULL;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscalls */
+    }
+
+  if (cmd == IPC_SET && buf != NULL)
+    {
+      buf32.msg_qbytes = buf->msg_qbytes;
+      buf32.msg_perm.uid = buf->msg_perm.uid;
+      buf32.msg_perm.gid = buf->msg_perm.gid;
+      buf32.msg_perm.mode = buf->msg_perm.mode;
+    }
+
+  if (cmd == IPC_SET || cmd == IPC_STAT)
+    pbuf32 = &buf32;
+
+#ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
+  result = INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, pbuf32);
+#else
+  result = INLINE_SYSCALL_CALL (ipc, IPCOP_msgctl, msqid, cmd | __IPC_64,
+                                0, pbuf32);
+#endif
+
+  if (cmd == IPC_STAT && result == 0 && buf != NULL)
+    {
+      buf->msg_perm = buf32.msg_perm;
+      buf->msg_stime = buf32.msg_stime;
+      buf->__glibc_reserved1 = buf32.__glibc_reserved1;
+      buf->msg_rtime = buf32.msg_rtime;
+      buf->__glibc_reserved2 = buf32.__glibc_reserved2;
+      buf->msg_ctime = buf32.msg_ctime;
+      buf->__glibc_reserved3 = buf32.__glibc_reserved3;
+      buf->__msg_cbytes = buf32.__msg_cbytes;
+      buf->msg_qnum = buf32.msg_qnum;
+      buf->msg_qbytes = buf32.msg_qbytes;
+      buf->msg_lspid = buf32.msg_lspid;
+      buf->msg_lrpid = buf32.msg_lrpid;
+      buf->__glibc_reserved4 = buf32.__glibc_reserved4;
+      buf->__glibc_reserved5 = buf32.__glibc_reserved5;
+    }
+
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 29/52] Y2038: add function __stime_t64
  2017-09-07 22:44                                                       ` [RFC PATCH 28/52] Y2038: add function __time_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                                         ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                                           ` [RFC PATCH 30/52] Y2038: add function __utimes_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

These implementations use only 32-bit time kernel syscalls.

Therefore, stime() will always set errno to EOVERFLOW and return -1 for dates beyond Y2038.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/stime.c | 70 +++++++++++++++++++++++++++++++++++++++++
 time/Versions                   |  1 +
 time/stime.c                    | 17 ++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/stime.c

diff --git a/sysdeps/unix/sysv/linux/stime.c b/sysdeps/unix/sysv/linux/stime.c
new file mode 100644
index 0000000000..177c9334ef
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/stime.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 1992-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stddef.h>		/* For NULL.  */
+#include <sys/time.h>
+#include <time.h>
+
+/* Set the system clock to *WHEN.  */
+
+int
+stime (const time_t *when)
+{
+  struct timeval tv;
+
+  if (when == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  tv.tv_sec = *when;
+  tv.tv_usec = 0;
+  return __settimeofday (&tv, (struct timezone *) 0);
+}
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__stime_t64 (const __time64_t *when)
+{
+  struct timeval tv32;
+
+  if (when == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement 64-bit-time syscall case */
+  }
+
+  if (*when > INT_MAX)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  tv32.tv_sec = *when;
+  tv32.tv_usec = 0;
+  return __settimeofday (&tv32, (struct timezone *) 0);
+}
diff --git a/time/Versions b/time/Versions
index 02dc8d6146..3dca51abcb 100644
--- a/time/Versions
+++ b/time/Versions
@@ -72,5 +72,6 @@ libc {
   GLIBC_Y2038 {
     __timespec_get64;
     __time_t64;
+    __stime_t64;
   }
 }
diff --git a/time/stime.c b/time/stime.c
index 723eedacf1..c1c7c4c9b5 100644
--- a/time/stime.c
+++ b/time/stime.c
@@ -35,3 +35,20 @@ stime (const time_t *when)
 }
 
 stub_warning (stime)
+
+/* 64-bit time version */
+
+int
+__stime_t64 (const __time64_t *when)
+{
+  if (when == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__stime_t64)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 23/52] Y2038: add struct __stat64_t64
  2017-09-07 22:44                                           ` [RFC PATCH 22/52] Y2038: add function __timerfd_settime64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:44                                             ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:44                                               ` [RFC PATCH 24/52] Y2038: add function __fstat64_t64 (and __fxstat64_t64) Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:44 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/stat.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 4f31c00eca..300cf8bbc4 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -1,7 +1,32 @@
 #ifndef _SYS_STAT_H
 #include <io/sys/stat.h>
+#include <include/time.h>
 
 #ifndef _ISOMAC
+
+/* Used for 64-bit time implementations */
+struct __stat64_t64
+  {
+    __dev_t st_dev;			/* Device.  */
+    unsigned int __pad1;
+
+    __ino_t __st_ino;			/* 32bit file serial number.	*/
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+    unsigned int __pad2;
+    __off64_t st_size;			/* Size of file, in bytes.  */
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+
+    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
+    struct __timespec64 st_atim;		/* Time of last access.  */
+    struct __timespec64 st_mtim;		/* Time of last modification.  */
+    struct __timespec64 st_ctim;		/* Time of last status change.  */
+    __ino64_t st_ino;			/* File serial number.		*/
+  };
+
 /* Now define the internal interfaces. */
 extern int __stat (const char *__file, struct stat *__buf);
 extern int __fstat (int __fd, struct stat *__buf);
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 41/52] Y2038: add function __getitimer_t64
  2017-09-07 22:45                                                                               ` [RFC PATCH 40/52] Y2038: add struct __itimerval_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                 ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                   ` [RFC PATCH 42/52] Y2038: add function __setitimer_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 time/Makefile      |  3 ++-
 time/Versions      |  1 +
 time/getitimer64.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 1 deletion(-)
 create mode 100644 time/getitimer64.c

diff --git a/time/Makefile b/time/Makefile
index d50c3ddfd8..f2b50626b6 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,8 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
 	    timespec_get                                 \
-	    settimeofday64 nanosleep64
+	    settimeofday64 nanosleep64                   \
+	    getitimer64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index 0f4600f33c..cc05014bd8 100644
--- a/time/Versions
+++ b/time/Versions
@@ -77,5 +77,6 @@ libc {
     __settimeofday_t64;
     __nanosleep_t64;
     __adjtime_t64;
+    __getitimer_t64;
   }
 }
diff --git a/time/getitimer64.c b/time/getitimer64.c
new file mode 100644
index 0000000000..2b19adf953
--- /dev/null
+++ b/time/getitimer64.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+extern int __y2038_linux_support;
+
+/* Set *VALUE to the current setting of timer WHICH.
+   Return 0 on success, -1 on errors.  */
+int
+__getitimer_t64 (enum __itimer_which which,
+                 struct __itimerval_t64 *value)
+{
+  struct itimerval value32, *value32p= NULL;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscall */
+    }
+ 
+  if (value != NULL)
+    value32p = &value32;
+
+  int result = getitimer(which, value32p);
+
+  if (result == 0 && value != NULL)
+    {
+      value->it_interval.tv_sec = value32.it_interval.tv_sec;
+      value->it_interval.tv_usec = value32.it_interval.tv_usec;
+      value->it_value.tv_sec = value32.it_value.tv_sec;
+      value->it_value.tv_usec = value32.it_value.tv_usec;
+    }
+
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 40/52] Y2038: add struct __itimerval_t64
  2017-09-07 22:45                                                                             ` [RFC PATCH 39/52] Y2038: add function __utime_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                               ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                 ` [RFC PATCH 41/52] Y2038: add function __getitimer_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/time.h b/include/time.h
index 1d585184d8..47ec6e67b6 100644
--- a/include/time.h
+++ b/include/time.h
@@ -53,6 +53,12 @@ struct __itimerspec64
   struct __timespec64 it_value;
 };
 
+struct __itimerval_t64
+{
+  struct __timeval64 it_interval;
+  struct __timeval64 it_value;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 43/52] Y2038: add functions using futexes
  2017-09-07 22:45                                                                                   ` [RFC PATCH 42/52] Y2038: add function __setitimer_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                     ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                       ` [RFC PATCH 44/52] Y2038: add function __getrusage_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

This creates 64-bit time versions of the following APIs:
- pthread_rwlock_timedrdlock
- pthread_rwlock_timedwrlock
- pthread_mutex_timedlock
- pthread_cond_timedwait
- sem_timedwait
- aio_suspend

It also creates 64-bit time versions of the following
functions or macros:
- lll_timedlock_elision
- lll_timedlock
- __lll_timedlock_wait
- futex_reltimed_wait_cancelable
- lll_futex_timed_wait
- __pthread_cond_wait_common
- futex_abstimed_wait_cancelable
- lll_futex_timed_wait_bitset
- do_aio_misc_wait
- AIO_MISC_WAIT
- __new_sem_wait_slow
- do_futex_wait
- __pthread_rwlock_wrlock_full
- __pthread_rwlock_rdlock_full
- futex_abstimed_wait

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 nptl/Versions                                |  11 +
 nptl/lll_timedlock_wait.c                    |  37 ++
 nptl/pthread_cond_wait.c                     | 285 +++++++++++++
 nptl/pthread_mutex_timedlock.c               | 616 +++++++++++++++++++++++++++
 nptl/pthread_rwlock_common.c                 | 591 +++++++++++++++++++++++++
 nptl/pthread_rwlock_timedrdlock.c            |  19 +
 nptl/pthread_rwlock_timedwrlock.c            |  19 +
 nptl/sem_timedwait.c                         |  18 +
 nptl/sem_wait.c                              |  24 ++
 nptl/sem_waitcommon.c                        | 172 ++++++++
 rt/Versions                                  |   1 +
 sysdeps/nptl/aio_misc.h                      |  39 ++
 sysdeps/nptl/lowlevellock.h                  |  17 +
 sysdeps/pthread/aio_suspend.c                | 164 +++++++
 sysdeps/unix/sysv/linux/futex-internal.h     | 123 ++++++
 sysdeps/unix/sysv/linux/lowlevellock-futex.h |  22 +
 16 files changed, 2158 insertions(+)

diff --git a/nptl/Versions b/nptl/Versions
index 0ae5def464..9ed0872eab 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -272,4 +272,15 @@ libpthread {
     __pthread_barrier_init; __pthread_barrier_wait;
     __shm_directory;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __pthread_rwlock_rdlock_t64;
+    __pthread_rwlock_wrlock_t64;
+    __pthread_mutex_timedlock_t64;
+    __sem_timedwait_t64;
+    __pthread_cond_timedwait_t64;
+  }
 }
diff --git a/nptl/lll_timedlock_wait.c b/nptl/lll_timedlock_wait.c
index 604953c04c..d757d9d92e 100644
--- a/nptl/lll_timedlock_wait.c
+++ b/nptl/lll_timedlock_wait.c
@@ -57,3 +57,40 @@ __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
 
   return 0;
 }
+
+/* 64-bit time version */
+
+int
+__lll_timedlock_wait_t64 (int *futex, const struct __timespec64 *abstime, int private)
+{
+  /* Reject invalid timeouts.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+
+  /* Try locking.  */
+  while (atomic_exchange_acq (futex, 2) != 0)
+    {
+      struct timeval tv;
+
+      /* Get the current time.  */
+      (void) __gettimeofday (&tv, NULL);
+
+      /* Compute relative timeout.  */
+      struct timespec rt;
+      rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+      rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+      if (rt.tv_nsec < 0)
+        {
+          rt.tv_nsec += 1000000000;
+          --rt.tv_sec;
+        }
+
+      if (rt.tv_sec < 0)
+        return ETIMEDOUT;
+
+      /* If *futex == 2, wait until woken or timeout.  */
+      lll_futex_timed_wait (futex, 2, &rt, private);
+    }
+
+  return 0;
+}
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 7812b94a3a..4246e25aeb 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -647,6 +647,280 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
   return (err != 0) ? err : result;
 }
 
+/* 64-bit time variant */
+
+static __always_inline int
+__pthread_cond_wait_common_t64 (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    const struct __timespec64 *abstime)
+{
+  const int maxspin = 0;
+  int err;
+  int result = 0;
+
+  LIBC_PROBE (cond_wait, 2, cond, mutex);
+
+  /* Acquire a position (SEQ) in the waiter sequence (WSEQ).  We use an
+     atomic operation because signals and broadcasts may update the group
+     switch without acquiring the mutex.  We do not need release MO here
+     because we do not need to establish any happens-before relation with
+     signalers (see __pthread_cond_signal); modification order alone
+     establishes a total order of waiters/signals.  We do need acquire MO
+     to synchronize with group reinitialization in
+     __condvar_quiesce_and_switch_g1.  */
+  uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);
+  /* Find our group's index.  We always go into what was G2 when we acquired
+     our position.  */
+  unsigned int g = wseq & 1;
+  uint64_t seq = wseq >> 1;
+
+  /* Increase the waiter reference count.  Relaxed MO is sufficient because
+     we only need to synchronize when decrementing the reference count.  */
+  unsigned int flags = atomic_fetch_add_relaxed (&cond->__data.__wrefs, 8);
+  int private = __condvar_get_private (flags);
+
+  /* Now that we are registered as a waiter, we can release the mutex.
+     Waiting on the condvar must be atomic with releasing the mutex, so if
+     the mutex is used to establish a happens-before relation with any
+     signaler, the waiter must be visible to the latter; thus, we release the
+     mutex after registering as waiter.
+     If releasing the mutex fails, we just cancel our registration as a
+     waiter and confirm that we have woken up.  */
+  err = __pthread_mutex_unlock_usercnt (mutex, 0);
+  if (__glibc_unlikely (err != 0))
+    {
+      __condvar_cancel_waiting (cond, seq, g, private);
+      __condvar_confirm_wakeup (cond, private);
+      return err;
+    }
+
+  /* Now wait until a signal is available in our group or it is closed.
+     Acquire MO so that if we observe a value of zero written after group
+     switching in __condvar_quiesce_and_switch_g1, we synchronize with that
+     store and will see the prior update of __g1_start done while switching
+     groups too.  */
+  unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
+
+  do
+    {
+      while (1)
+	{
+	  /* Spin-wait first.
+	     Note that spinning first without checking whether a timeout
+	     passed might lead to what looks like a spurious wake-up even
+	     though we should return ETIMEDOUT (e.g., if the caller provides
+	     an absolute timeout that is clearly in the past).  However,
+	     (1) spurious wake-ups are allowed, (2) it seems unlikely that a
+	     user will (ab)use pthread_cond_wait as a check for whether a
+	     point in time is in the past, and (3) spinning first without
+	     having to compare against the current time seems to be the right
+	     choice from a performance perspective for most use cases.  */
+	  unsigned int spin = maxspin;
+	  while (signals == 0 && spin > 0)
+	    {
+	      /* Check that we are not spinning on a group that's already
+		 closed.  */
+	      if (seq < (__condvar_load_g1_start_relaxed (cond) >> 1))
+		goto done;
+
+	      /* TODO Back off.  */
+
+	      /* Reload signals.  See above for MO.  */
+	      signals = atomic_load_acquire (cond->__data.__g_signals + g);
+	      spin--;
+	    }
+
+	  /* If our group will be closed as indicated by the flag on signals,
+	     don't bother grabbing a signal.  */
+	  if (signals & 1)
+	    goto done;
+
+	  /* If there is an available signal, don't block.  */
+	  if (signals != 0)
+	    break;
+
+	  /* No signals available after spinning, so prepare to block.
+	     We first acquire a group reference and use acquire MO for that so
+	     that we synchronize with the dummy read-modify-write in
+	     __condvar_quiesce_and_switch_g1 if we read from that.  In turn,
+	     in this case this will make us see the closed flag on __g_signals
+	     that designates a concurrent attempt to reuse the group's slot.
+	     We use acquire MO for the __g_signals check to make the
+	     __g1_start check work (see spinning above).
+	     Note that the group reference acquisition will not mask the
+	     release MO when decrementing the reference count because we use
+	     an atomic read-modify-write operation and thus extend the release
+	     sequence.  */
+	  atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
+	  if (((atomic_load_acquire (cond->__data.__g_signals + g) & 1) != 0)
+	      || (seq < (__condvar_load_g1_start_relaxed (cond) >> 1)))
+	    {
+	      /* Our group is closed.  Wake up any signalers that might be
+		 waiting.  */
+	      __condvar_dec_grefs (cond, g, private);
+	      goto done;
+	    }
+
+	  // Now block.
+	  struct _pthread_cleanup_buffer buffer;
+	  struct _condvar_cleanup_buffer cbuffer;
+	  cbuffer.wseq = wseq;
+	  cbuffer.cond = cond;
+	  cbuffer.mutex = mutex;
+	  cbuffer.private = private;
+	  __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
+
+	  if (abstime == NULL)
+	    {
+	      /* Block without a timeout.  */
+	      err = futex_wait_cancelable (
+		  cond->__data.__g_signals + g, 0, private);
+	    }
+	  else
+	    {
+	      /* Block, but with a timeout.
+		 Work around the fact that the kernel rejects negative timeout
+		 values despite them being valid.  */
+	      if (__glibc_unlikely (abstime->tv_sec < 0))
+	        err = ETIMEDOUT;
+
+	      else if ((flags & __PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0)
+		{
+		  /* CLOCK_MONOTONIC is requested.  */
+		  struct timespec rt;
+		  struct __timespec64 rt64;
+		  if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0)
+		    __libc_fatal ("clock_gettime does not support "
+				  "CLOCK_MONOTONIC");
+		  /* Convert the absolute timeout value to a relative
+		     timeout.  */
+		  rt64.tv_sec = abstime->tv_sec - rt.tv_sec;
+		  rt64.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
+		  if (rt64.tv_nsec < 0)
+		    {
+		      rt64.tv_nsec += 1000000000;
+		      --rt64.tv_sec;
+		    }
+		  /* Did we already time out?  */
+		  if (__glibc_unlikely (rt64.tv_sec < 0))
+		    err = ETIMEDOUT;
+		  else
+		    err = futex_reltimed_wait_cancelable_t64
+			(cond->__data.__g_signals + g, 0, &rt64, private);
+		}
+	      else
+		{
+		  /* Use CLOCK_REALTIME.  */
+		  err = futex_abstimed_wait_cancelable_t64
+		      (cond->__data.__g_signals + g, 0, abstime, private);
+		}
+	    }
+
+	  __pthread_cleanup_pop (&buffer, 0);
+
+	  if (__glibc_unlikely (err == ETIMEDOUT))
+	    {
+	      __condvar_dec_grefs (cond, g, private);
+	      /* If we timed out, we effectively cancel waiting.  Note that
+		 we have decremented __g_refs before cancellation, so that a
+		 deadlock between waiting for quiescence of our group in
+		 __condvar_quiesce_and_switch_g1 and us trying to acquire
+		 the lock during cancellation is not possible.  */
+	      __condvar_cancel_waiting (cond, seq, g, private);
+	      result = ETIMEDOUT;
+	      goto done;
+	    }
+	  else
+	    __condvar_dec_grefs (cond, g, private);
+
+	  /* Reload signals.  See above for MO.  */
+	  signals = atomic_load_acquire (cond->__data.__g_signals + g);
+	}
+
+    }
+  /* Try to grab a signal.  Use acquire MO so that we see an up-to-date value
+     of __g1_start below (see spinning above for a similar case).  In
+     particular, if we steal from a more recent group, we will also see a
+     more recent __g1_start below.  */
+  while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
+						&signals, signals - 2));
+
+  /* We consumed a signal but we could have consumed from a more recent group
+     that aliased with ours due to being in the same group slot.  If this
+     might be the case our group must be closed as visible through
+     __g1_start.  */
+  uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
+  if (seq < (g1_start >> 1))
+    {
+      /* We potentially stole a signal from a more recent group but we do not
+	 know which group we really consumed from.
+	 We do not care about groups older than current G1 because they are
+	 closed; we could have stolen from these, but then we just add a
+	 spurious wake-up for the current groups.
+	 We will never steal a signal from current G2 that was really intended
+	 for G2 because G2 never receives signals (until it becomes G1).  We
+	 could have stolen a signal from G2 that was conservatively added by a
+	 previous waiter that also thought it stole a signal -- but given that
+	 that signal was added unnecessarily, it's not a problem if we steal
+	 it.
+	 Thus, the remaining case is that we could have stolen from the current
+	 G1, where "current" means the __g1_start value we observed.  However,
+	 if the current G1 does not have the same slot index as we do, we did
+	 not steal from it and do not need to undo that.  This is the reason
+	 for putting a bit with G2's index into__g1_start as well.  */
+      if (((g1_start & 1) ^ 1) == g)
+	{
+	  /* We have to conservatively undo our potential mistake of stealing
+	     a signal.  We can stop trying to do that when the current G1
+	     changes because other spinning waiters will notice this too and
+	     __condvar_quiesce_and_switch_g1 has checked that there are no
+	     futex waiters anymore before switching G1.
+	     Relaxed MO is fine for the __g1_start load because we need to
+	     merely be able to observe this fact and not have to observe
+	     something else as well.
+	     ??? Would it help to spin for a little while to see whether the
+	     current G1 gets closed?  This might be worthwhile if the group is
+	     small or close to being closed.  */
+	  unsigned int s = atomic_load_relaxed (cond->__data.__g_signals + g);
+	  while (__condvar_load_g1_start_relaxed (cond) == g1_start)
+	    {
+	      /* Try to add a signal.  We don't need to acquire the lock
+		 because at worst we can cause a spurious wake-up.  If the
+		 group is in the process of being closed (LSB is true), this
+		 has an effect similar to us adding a signal.  */
+	      if (((s & 1) != 0)
+		  || atomic_compare_exchange_weak_relaxed
+		       (cond->__data.__g_signals + g, &s, s + 2))
+		{
+		  /* If we added a signal, we also need to add a wake-up on
+		     the futex.  We also need to do that if we skipped adding
+		     a signal because the group is being closed because
+		     while __condvar_quiesce_and_switch_g1 could have closed
+		     the group, it might stil be waiting for futex waiters to
+		     leave (and one of those waiters might be the one we stole
+		     the signal from, which cause it to block using the
+		     futex).  */
+		  futex_wake (cond->__data.__g_signals + g, 1, private);
+		  break;
+		}
+	      /* TODO Back off.  */
+	    }
+	}
+    }
+
+ done:
+
+  /* Confirm that we have been woken.  We do that before acquiring the mutex
+     to allow for execution of pthread_cond_destroy while having acquired the
+     mutex.  */
+  __condvar_confirm_wakeup (cond, private);
+
+  /* Woken up; now re-acquire the mutex.  If this doesn't fail, return RESULT,
+     which is set to ETIMEDOUT if a timeout occured, or zero otherwise.  */
+  err = __pthread_mutex_cond_lock (mutex);
+  /* XXX Abort on errors that are disallowed by POSIX?  */
+  return (err != 0) ? err : result;
+}
+
 
 /* See __pthread_cond_wait_common.  */
 int
@@ -667,6 +941,17 @@ __pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
   return __pthread_cond_wait_common (cond, mutex, abstime);
 }
 
+int
+__pthread_cond_timedwait_t64 (pthread_cond_t *cond, pthread_mutex_t *mutex,
+    const struct __timespec64 *abstime)
+{
+  /* Check parameter validity.  This should also tell the compiler that
+     it can assume that abstime is not NULL.  */
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    return EINVAL;
+  return __pthread_cond_wait_common_t64 (cond, mutex, abstime);
+}
+
 versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
 		  GLIBC_2_3_2);
 versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index d5ec3141f3..6cad951129 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -32,6 +32,10 @@
 #define lll_timedlock_elision(a,dummy,b,c) lll_timedlock(a, b, c)
 #endif
 
+#ifndef lll_timedlock_elision_t64
+#define lll_timedlock_elision_t64(a,dummy,b,c) lll_timedlock_t64(a, b, c)
+#endif
+
 #ifndef lll_trylock_elision
 #define lll_trylock_elision(a,t) lll_trylock(a)
 #endif
@@ -638,3 +642,615 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex,
   return result;
 }
 weak_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock)
+
+/* 64-bit time version */
+
+int
+pthread_mutex_timedlock_t64 (pthread_mutex_t *mutex,
+			 const struct __timespec64 *abstime)
+{
+  int oldval;
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+  int result = 0;
+
+  LIBC_PROBE (mutex_timedlock_entry, 2, mutex, abstime);
+
+  /* We must not check ABSTIME here.  If the thread does not block
+     abstime must not be checked for a valid value.  */
+
+  switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex),
+			    PTHREAD_MUTEX_TIMED_NP))
+    {
+      /* Recursive mutex.  */
+    case PTHREAD_MUTEX_RECURSIVE_NP|PTHREAD_MUTEX_ELISION_NP:
+    case PTHREAD_MUTEX_RECURSIVE_NP:
+      /* Check whether we already hold the mutex.  */
+      if (mutex->__data.__owner == id)
+	{
+	  /* Just bump the counter.  */
+	  if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+	    /* Overflow of the counter.  */
+	    return EAGAIN;
+
+	  ++mutex->__data.__count;
+
+	  goto out;
+	}
+
+      /* We have to get the mutex.  */
+      result = lll_timedlock_t64 (mutex->__data.__lock, abstime,
+			          PTHREAD_MUTEX_PSHARED (mutex));
+
+      if (result != 0)
+	goto out;
+
+      /* Only locked once so far.  */
+      mutex->__data.__count = 1;
+      break;
+
+      /* Error checking mutex.  */
+    case PTHREAD_MUTEX_ERRORCHECK_NP:
+      /* Check whether we already hold the mutex.  */
+      if (__glibc_unlikely (mutex->__data.__owner == id))
+	return EDEADLK;
+
+      /* Don't do lock elision on an error checking mutex.  */
+      goto simple;
+
+    case PTHREAD_MUTEX_TIMED_NP:
+      FORCE_ELISION (mutex, goto elision);
+    simple:
+      /* Normal mutex.  */
+      result = lll_timedlock_t64 (mutex->__data.__lock, abstime,
+			          PTHREAD_MUTEX_PSHARED (mutex));
+      break;
+
+    case PTHREAD_MUTEX_TIMED_ELISION_NP:
+    elision: __attribute__((unused))
+      /* Don't record ownership */
+      return lll_timedlock_elision_t64 (mutex->__data.__lock,
+				    mutex->__data.__spins,
+				    abstime,
+				    PTHREAD_MUTEX_PSHARED (mutex));
+
+
+    case PTHREAD_MUTEX_ADAPTIVE_NP:
+      if (! __is_smp)
+	goto simple;
+
+      if (lll_trylock (mutex->__data.__lock) != 0)
+	{
+	  int cnt = 0;
+	  int max_cnt = MIN (MAX_ADAPTIVE_COUNT,
+			     mutex->__data.__spins * 2 + 10);
+	  do
+	    {
+	      if (cnt++ >= max_cnt)
+		{
+		  result = lll_timedlock_t64 (mutex->__data.__lock, abstime,
+					      PTHREAD_MUTEX_PSHARED (mutex));
+		  break;
+		}
+	      atomic_spin_nop ();
+	    }
+	  while (lll_trylock (mutex->__data.__lock) != 0);
+
+	  mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
+	}
+      break;
+
+    case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
+    case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
+    case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
+      THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+		     &mutex->__data.__list.__next);
+      /* We need to set op_pending before starting the operation.  Also
+	 see comments at ENQUEUE_MUTEX.  */
+      __asm ("" ::: "memory");
+
+      oldval = mutex->__data.__lock;
+      /* This is set to FUTEX_WAITERS iff we might have shared the
+	 FUTEX_WAITERS flag with other threads, and therefore need to keep it
+	 set to avoid lost wake-ups.  We have the same requirement in the
+	 simple mutex algorithm.  */
+      unsigned int assume_other_futex_waiters = 0;
+      while (1)
+	{
+	  /* Try to acquire the lock through a CAS from 0 (not acquired) to
+	     our TID | assume_other_futex_waiters.  */
+	  if (__glibc_likely (oldval == 0))
+	    {
+	      oldval
+	        = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+	            id | assume_other_futex_waiters, 0);
+	      if (__glibc_likely (oldval == 0))
+		break;
+	    }
+
+	  if ((oldval & FUTEX_OWNER_DIED) != 0)
+	    {
+	      /* The previous owner died.  Try locking the mutex.  */
+	      int newval = id | (oldval & FUTEX_WAITERS)
+		  | assume_other_futex_waiters;
+
+	      newval
+		= atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+						       newval, oldval);
+	      if (newval != oldval)
+		{
+		  oldval = newval;
+		  continue;
+		}
+
+	      /* We got the mutex.  */
+	      mutex->__data.__count = 1;
+	      /* But it is inconsistent unless marked otherwise.  */
+	      mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+	      /* We must not enqueue the mutex before we have acquired it.
+		 Also see comments at ENQUEUE_MUTEX.  */
+	      __asm ("" ::: "memory");
+	      ENQUEUE_MUTEX (mutex);
+	      /* We need to clear op_pending after we enqueue the mutex.  */
+	      __asm ("" ::: "memory");
+	      THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+	      /* Note that we deliberately exit here.  If we fall
+		 through to the end of the function __nusers would be
+		 incremented which is not correct because the old
+		 owner has to be discounted.  */
+	      return EOWNERDEAD;
+	    }
+
+	  /* Check whether we already hold the mutex.  */
+	  if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+	    {
+	      int kind = PTHREAD_MUTEX_TYPE (mutex);
+	      if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
+		{
+		  /* We do not need to ensure ordering wrt another memory
+		     access.  Also see comments at ENQUEUE_MUTEX. */
+		  THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+				 NULL);
+		  return EDEADLK;
+		}
+
+	      if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
+		{
+		  /* We do not need to ensure ordering wrt another memory
+		     access.  */
+		  THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+				 NULL);
+
+		  /* Just bump the counter.  */
+		  if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+		    /* Overflow of the counter.  */
+		    return EAGAIN;
+
+		  ++mutex->__data.__count;
+
+		  LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+		  return 0;
+		}
+	    }
+
+	  /* We are about to block; check whether the timeout is invalid.  */
+	  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+	    return EINVAL;
+	  /* Work around the fact that the kernel rejects negative timeout
+	     values despite them being valid.  */
+	  if (__glibc_unlikely (abstime->tv_sec < 0))
+	    return ETIMEDOUT;
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+     || !defined lll_futex_timed_wait_bitset)
+	  struct timeval tv;
+	  struct timespec rt;
+
+	  /* Get the current time.  */
+	  (void) __gettimeofday (&tv, NULL);
+
+	  /* Compute relative timeout.  */
+	  rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+	  rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+	  if (rt.tv_nsec < 0)
+	    {
+	      rt.tv_nsec += 1000000000;
+	      --rt.tv_sec;
+	    }
+
+	  /* Already timed out?  */
+	  if (rt.tv_sec < 0)
+	    return ETIMEDOUT;
+#endif
+
+	  /* We cannot acquire the mutex nor has its owner died.  Thus, try
+	     to block using futexes.  Set FUTEX_WAITERS if necessary so that
+	     other threads are aware that there are potentially threads
+	     blocked on the futex.  Restart if oldval changed in the
+	     meantime.  */
+	  if ((oldval & FUTEX_WAITERS) == 0)
+	    {
+	      if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
+							oldval | FUTEX_WAITERS,
+							oldval)
+		  != 0)
+		{
+		  oldval = mutex->__data.__lock;
+		  continue;
+		}
+	      oldval |= FUTEX_WAITERS;
+	    }
+
+	  /* It is now possible that we share the FUTEX_WAITERS flag with
+	     another thread; therefore, update assume_other_futex_waiters so
+	     that we do not forget about this when handling other cases
+	     above and thus do not cause lost wake-ups.  */
+	  assume_other_futex_waiters |= FUTEX_WAITERS;
+
+	  /* Block using the futex.  */
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+     || !defined lll_futex_timed_wait_bitset)
+	  lll_futex_timed wait_64 (&mutex->__data.__lock, oldval,
+				&rt, PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
+#else
+	  int err = lll_futex_timed_wait_bitset_t64 (&mutex->__data.__lock,
+	      oldval, abstime, FUTEX_CLOCK_REALTIME,
+	      PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
+	  /* The futex call timed out.  */
+	  if (err == -ETIMEDOUT)
+	    return -err;
+#endif
+	  /* Reload current lock value.  */
+	  oldval = mutex->__data.__lock;
+	}
+
+      /* We have acquired the mutex; check if it is still consistent.  */
+      if (__builtin_expect (mutex->__data.__owner
+			    == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+	{
+	  /* This mutex is now not recoverable.  */
+	  mutex->__data.__count = 0;
+	  int private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
+	  lll_unlock (mutex->__data.__lock, private);
+	  /* FIXME This violates the mutex destruction requirements.  See
+	     __pthread_mutex_unlock_full.  */
+	  THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+	  return ENOTRECOVERABLE;
+	}
+
+      mutex->__data.__count = 1;
+      /* We must not enqueue the mutex before we have acquired it.
+	 Also see comments at ENQUEUE_MUTEX.  */
+      __asm ("" ::: "memory");
+      ENQUEUE_MUTEX (mutex);
+      /* We need to clear op_pending after we enqueue the mutex.  */
+      __asm ("" ::: "memory");
+      THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+      break;
+
+    /* The PI support requires the Linux futex system call.  If that's not
+       available, pthread_mutex_init should never have allowed the type to
+       be set.  So it will get the default case for an invalid type.  */
+#ifdef __NR_futex
+    case PTHREAD_MUTEX_PI_RECURSIVE_NP:
+    case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_PI_NORMAL_NP:
+    case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
+    case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
+    case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
+    case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
+      {
+	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+	int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
+
+	if (robust)
+	  {
+	    /* Note: robust PI futexes are signaled by setting bit 0.  */
+	    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+			   (void *) (((uintptr_t) &mutex->__data.__list.__next)
+				     | 1));
+	    /* We need to set op_pending before starting the operation.  Also
+	       see comments at ENQUEUE_MUTEX.  */
+	    __asm ("" ::: "memory");
+	  }
+
+	oldval = mutex->__data.__lock;
+
+	/* Check whether we already hold the mutex.  */
+	if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+	  {
+	    if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+	      {
+		/* We do not need to ensure ordering wrt another memory
+		   access.  */
+		THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+		return EDEADLK;
+	      }
+
+	    if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+	      {
+		/* We do not need to ensure ordering wrt another memory
+		   access.  */
+		THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+		/* Just bump the counter.  */
+		if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+		  /* Overflow of the counter.  */
+		  return EAGAIN;
+
+		++mutex->__data.__count;
+
+		LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+		return 0;
+	      }
+	  }
+
+	oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+						      id, 0);
+
+	if (oldval != 0)
+	  {
+	    /* The mutex is locked.  The kernel will now take care of
+	       everything.  The timeout value must be a relative value.
+	       Convert it.  */
+	    int private = (robust
+			   ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
+			   : PTHREAD_MUTEX_PSHARED (mutex));
+	    INTERNAL_SYSCALL_DECL (__err);
+
+	    int e;
+	    
+	    if (abstime->tv_sec > INT_MAX)
+	    {
+	      e = EOVERFLOW;
+	    }
+	    else
+	    {
+	      struct timespec ts;
+	      ts.tv_sec = abstime->tv_sec;
+	      ts.tv_nsec = abstime->tv_nsec;
+	      e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
+				      __lll_private_flag (FUTEX_LOCK_PI,
+							  private), 1,
+				      &ts);
+	    }
+	    if (INTERNAL_SYSCALL_ERROR_P (e, __err))
+	      {
+		if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT)
+		  return ETIMEDOUT;
+
+		if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH
+		    || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)
+		  {
+		    assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK
+			    || (kind != PTHREAD_MUTEX_ERRORCHECK_NP
+				&& kind != PTHREAD_MUTEX_RECURSIVE_NP));
+		    /* ESRCH can happen only for non-robust PI mutexes where
+		       the owner of the lock died.  */
+		    assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH
+			    || !robust);
+
+		    /* Delay the thread until the timeout is reached.
+		       Then return ETIMEDOUT.  */
+		    struct timespec reltime;
+		    struct __timespec64 now;
+
+		    INTERNAL_SYSCALL (clock_gettime64, __err, 2, CLOCK_REALTIME,
+				      &now);
+		    reltime.tv_sec = abstime->tv_sec - now.tv_sec;
+		    reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec;
+		    if (reltime.tv_nsec < 0)
+		      {
+			reltime.tv_nsec += 1000000000;
+			--reltime.tv_sec;
+		      }
+		    if (reltime.tv_sec >= 0)
+		      while (nanosleep_not_cancel (&reltime, &reltime) != 0)
+			continue;
+
+		    return ETIMEDOUT;
+		  }
+
+		return INTERNAL_SYSCALL_ERRNO (e, __err);
+	      }
+
+	    oldval = mutex->__data.__lock;
+
+	    assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
+	  }
+
+	if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
+	  {
+	    atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
+
+	    /* We got the mutex.  */
+	    mutex->__data.__count = 1;
+	    /* But it is inconsistent unless marked otherwise.  */
+	    mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+	    /* We must not enqueue the mutex before we have acquired it.
+	       Also see comments at ENQUEUE_MUTEX.  */
+	    __asm ("" ::: "memory");
+	    ENQUEUE_MUTEX_PI (mutex);
+	    /* We need to clear op_pending after we enqueue the mutex.  */
+	    __asm ("" ::: "memory");
+	    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+	    /* Note that we deliberately exit here.  If we fall
+	       through to the end of the function __nusers would be
+	       incremented which is not correct because the old owner
+	       has to be discounted.  */
+	    return EOWNERDEAD;
+	  }
+
+	if (robust
+	    && __builtin_expect (mutex->__data.__owner
+				 == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+	  {
+	    /* This mutex is now not recoverable.  */
+	    mutex->__data.__count = 0;
+
+	    INTERNAL_SYSCALL_DECL (__err);
+	    INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
+			      __lll_private_flag (FUTEX_UNLOCK_PI,
+						  PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
+			      0, 0);
+
+	    /* To the kernel, this will be visible after the kernel has
+	       acquired the mutex in the syscall.  */
+	    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+	    return ENOTRECOVERABLE;
+	  }
+
+	mutex->__data.__count = 1;
+	if (robust)
+	  {
+	    /* We must not enqueue the mutex before we have acquired it.
+	       Also see comments at ENQUEUE_MUTEX.  */
+	    __asm ("" ::: "memory");
+	    ENQUEUE_MUTEX_PI (mutex);
+	    /* We need to clear op_pending after we enqueue the mutex.  */
+	    __asm ("" ::: "memory");
+	    THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+	  }
+	}
+      break;
+#endif  /* __NR_futex.  */
+
+    case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+    case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_PP_NORMAL_NP:
+    case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+      {
+	int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+
+	oldval = mutex->__data.__lock;
+
+	/* Check whether we already hold the mutex.  */
+	if (mutex->__data.__owner == id)
+	  {
+	    if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+	      return EDEADLK;
+
+	    if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+	      {
+		/* Just bump the counter.  */
+		if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+		  /* Overflow of the counter.  */
+		  return EAGAIN;
+
+		++mutex->__data.__count;
+
+		LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+		return 0;
+	      }
+	  }
+
+	int oldprio = -1, ceilval;
+	do
+	  {
+	    int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+			  >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+	    if (__pthread_current_priority () > ceiling)
+	      {
+		result = EINVAL;
+	      failpp:
+		if (oldprio != -1)
+		  __pthread_tpp_change_priority (oldprio, -1);
+		return result;
+	      }
+
+	    result = __pthread_tpp_change_priority (oldprio, ceiling);
+	    if (result)
+	      return result;
+
+	    ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+	    oldprio = ceiling;
+
+	    oldval
+	      = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+						     ceilval | 1, ceilval);
+
+	    if (oldval == ceilval)
+	      break;
+
+	    do
+	      {
+		oldval
+		  = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+							 ceilval | 2,
+							 ceilval | 1);
+
+		if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+		  break;
+
+		if (oldval != ceilval)
+		  {
+		    /* Reject invalid timeouts.  */
+		    if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+		      {
+			result = EINVAL;
+			goto failpp;
+		      }
+
+		    struct timeval tv;
+		    struct timespec rt;
+
+		    /* Get the current time.  */
+		    (void) __gettimeofday (&tv, NULL);
+
+		    /* Compute relative timeout.  */
+		    rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+		    rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+		    if (rt.tv_nsec < 0)
+		      {
+			rt.tv_nsec += 1000000000;
+			--rt.tv_sec;
+		      }
+
+		    /* Already timed out?  */
+		    if (rt.tv_sec < 0)
+		      {
+			result = ETIMEDOUT;
+			goto failpp;
+		      }
+
+		    lll_futex_timed_wait (&mutex->__data.__lock,
+					  ceilval | 2, &rt,
+					  PTHREAD_MUTEX_PSHARED (mutex));
+		  }
+	      }
+	    while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+							ceilval | 2, ceilval)
+		   != ceilval);
+	  }
+	while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
+
+	assert (mutex->__data.__owner == 0);
+	mutex->__data.__count = 1;
+      }
+      break;
+
+    default:
+      /* Correct code cannot set any other type.  */
+      return EINVAL;
+    }
+
+  if (result == 0)
+    {
+      /* Record the ownership.  */
+      mutex->__data.__owner = id;
+      ++mutex->__data.__nusers;
+
+      LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+    }
+
+ out:
+  return result;
+}
diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c
index 846687e1cf..b07f86342d 100644
--- a/nptl/pthread_rwlock_common.c
+++ b/nptl/pthread_rwlock_common.c
@@ -507,6 +507,240 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock,
   return 0;
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+__pthread_rwlock_rdlock_full_t64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  unsigned int r;
+
+  /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
+     situation we recognize and report.  */
+  if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
+      == THREAD_GETMEM (THREAD_SELF, tid)))
+    return EDEADLK;
+
+  /* If we prefer writers, recursive rdlock is disallowed, we are in a read
+     phase, and there are other readers present, we try to wait without
+     extending the read phase.  We will be unblocked by either one of the
+     other active readers, or if the writer gives up WRLOCKED (e.g., on
+     timeout).
+     If there are no other readers, we simply race with any existing primary
+     writer; it would have been a race anyway, and changing the odds slightly
+     will likely not make a big difference.  */
+  if (rwlock->__data.__flags == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
+    {
+      r = atomic_load_relaxed (&rwlock->__data.__readers);
+      while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+	      && ((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
+	      && ((r >> PTHREAD_RWLOCK_READER_SHIFT) > 0))
+	{
+	  /* TODO Spin first.  */
+	  /* Try setting the flag signaling that we are waiting without having
+	     incremented the number of readers.  Relaxed MO is fine because
+	     this is just about waiting for a state change in __readers.  */
+	  if (atomic_compare_exchange_weak_relaxed
+	      (&rwlock->__data.__readers, &r, r | PTHREAD_RWLOCK_RWAITING))
+	    {
+	      /* Wait for as long as the flag is set.  An ABA situation is
+		 harmless because the flag is just about the state of
+		 __readers, and all threads set the flag under the same
+		 conditions.  */
+	      while ((atomic_load_relaxed (&rwlock->__data.__readers)
+		  & PTHREAD_RWLOCK_RWAITING) != 0)
+		{
+		  int private = __pthread_rwlock_get_private (rwlock);
+		  int err = futex_abstimed_wait_t64 (&rwlock->__data.__readers,
+		      r, abstime, private);
+		  /* We ignore EAGAIN and EINTR.  On time-outs, we can just
+		     return because we don't need to clean up anything.  */
+		  if (err == ETIMEDOUT)
+		    return err;
+		}
+	      /* It makes sense to not break out of the outer loop here
+		 because we might be in the same situation again.  */
+	    }
+	  else
+	    {
+	      /* TODO Back-off.  */
+	    }
+	}
+    }
+  /* Register as a reader, using an add-and-fetch so that R can be used as
+     expected value for future operations.  Acquire MO so we synchronize with
+     prior writers as well as the last reader of the previous read phase (see
+     below).  */
+  r = atomic_fetch_add_acquire (&rwlock->__data.__readers,
+      (1 << PTHREAD_RWLOCK_READER_SHIFT)) + (1 << PTHREAD_RWLOCK_READER_SHIFT);
+
+  /* Check whether there is an overflow in the number of readers.  We assume
+     that the total number of threads is less than half the maximum number
+     of readers that we have bits for in __readers (i.e., with 32-bit int and
+     PTHREAD_RWLOCK_READER_SHIFT of 3, we assume there are less than
+     1 << (32-3-1) concurrent threads).
+     If there is an overflow, we use a CAS to try to decrement the number of
+     readers if there still is an overflow situation.  If so, we return
+     EAGAIN; if not, we are not a thread causing an overflow situation, and so
+     we just continue.  Using a fetch-add instead of the CAS isn't possible
+     because other readers might release the lock concurrently, which could
+     make us the last reader and thus responsible for handing ownership over
+     to writers (which requires a CAS too to make the decrement and ownership
+     transfer indivisible).  */
+  while (__glibc_unlikely (r >= PTHREAD_RWLOCK_READER_OVERFLOW))
+    {
+      /* Relaxed MO is okay because we just want to undo our registration and
+	 cannot have changed the rwlock state substantially if the CAS
+	 succeeds.  */
+      if (atomic_compare_exchange_weak_relaxed (&rwlock->__data.__readers, &r,
+	  r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
+	return EAGAIN;
+    }
+
+  /* We have registered as a reader, so if we are in a read phase, we have
+     acquired a read lock.  This is also the reader--reader fast-path.
+     Even if there is a primary writer, we just return.  If writers are to
+     be preferred and we are the only active reader, we could try to enter a
+     write phase to let the writer proceed.  This would be okay because we
+     cannot have acquired the lock previously as a reader (which could result
+     in deadlock if we would wait for the primary writer to run).  However,
+     this seems to be a corner case and handling it specially not be worth the
+     complexity.  */
+  if (__glibc_likely ((r & PTHREAD_RWLOCK_WRPHASE) == 0))
+    return 0;
+
+  /* If there is no primary writer but we are in a write phase, we can try
+     to install a read phase ourself.  */
+  while (((r & PTHREAD_RWLOCK_WRPHASE) != 0)
+      && ((r & PTHREAD_RWLOCK_WRLOCKED) == 0))
+    {
+       /* Try to enter a read phase: If the CAS below succeeds, we have
+	 ownership; if it fails, we will simply retry and reassess the
+	 situation.
+	 Acquire MO so we synchronize with prior writers.  */
+      if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
+	  r ^ PTHREAD_RWLOCK_WRPHASE))
+	{
+	  /* We started the read phase, so we are also responsible for
+	     updating the write-phase futex.  Relaxed MO is sufficient.
+	     Note that there can be no other reader that we have to wake
+	     because all other readers will see the read phase started by us
+	     (or they will try to start it themselves); if a writer started
+	     the read phase, we cannot have started it.  Furthermore, we
+	     cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
+	     overwrite the value set by the most recent writer (or the readers
+	     before it in case of explicit hand-over) and we know that there
+	     are no waiting readers.  */
+	  atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
+	  return 0;
+	}
+      else
+	{
+	  /* TODO Back off before retrying.  Also see above.  */
+	}
+    }
+
+  if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
+    {
+      /* We are in a write phase, and there must be a primary writer because
+	 of the previous loop.  Block until the primary writer gives up the
+	 write phase.  This case requires explicit hand-over using
+	 __wrphase_futex.
+	 However, __wrphase_futex might not have been set to 1 yet (either
+	 because explicit hand-over to the writer is still ongoing, or because
+	 the writer has started the write phase but does not yet have updated
+	 __wrphase_futex).  The least recent value of __wrphase_futex we can
+	 read from here is the modification of the last read phase (because
+	 we synchronize with the last reader in this read phase through
+	 __readers; see the use of acquire MO on the fetch_add above).
+	 Therefore, if we observe a value of 0 for __wrphase_futex, we need
+	 to subsequently check that __readers now indicates a read phase; we
+	 need to use acquire MO for this so that if we observe a read phase,
+	 we will also see the modification of __wrphase_futex by the previous
+	 writer.  We then need to load __wrphase_futex again and continue to
+	 wait if it is not 0, so that we do not skip explicit hand-over.
+	 Relaxed MO is sufficient for the load from __wrphase_futex because
+	 we just use it as an indicator for when we can proceed; we use
+	 __readers and the acquire MO accesses to it to eventually read from
+	 the proper stores to __wrphase_futex.  */
+      unsigned int wpf;
+      bool ready = false;
+      for (;;)
+	{
+	  while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
+	      | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
+	    {
+	      int private = __pthread_rwlock_get_private (rwlock);
+	      if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
+		  && !atomic_compare_exchange_weak_relaxed
+		      (&rwlock->__data.__wrphase_futex,
+		       &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))
+		continue;
+	      int err = futex_abstimed_wait_t64 (&rwlock->__data.__wrphase_futex,
+		  1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+	      if (err == ETIMEDOUT)
+		{
+		  /* If we timed out, we need to unregister.  If no read phase
+		     has been installed while we waited, we can just decrement
+		     the number of readers.  Otherwise, we just acquire the
+		     lock, which is allowed because we give no precise timing
+		     guarantees, and because the timeout is only required to
+		     be in effect if we would have had to wait for other
+		     threads (e.g., if futex_wait would time-out immediately
+		     because the given absolute time is in the past).  */
+		  r = atomic_load_relaxed (&rwlock->__data.__readers);
+		  while ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
+		    {
+		      /* We don't need to make anything else visible to
+			 others besides unregistering, so relaxed MO is
+			 sufficient.  */
+		      if (atomic_compare_exchange_weak_relaxed
+			  (&rwlock->__data.__readers, &r,
+			   r - (1 << PTHREAD_RWLOCK_READER_SHIFT)))
+			return ETIMEDOUT;
+		      /* TODO Back-off.  */
+		    }
+		  /* Use the acquire MO fence to mirror the steps taken in the
+		     non-timeout case.  Note that the read can happen both
+		     in the atomic_load above as well as in the failure case
+		     of the CAS operation.  */
+		  atomic_thread_fence_acquire ();
+		  /* We still need to wait for explicit hand-over, but we must
+		     not use futex_wait anymore because we would just time out
+		     in this case and thus make the spin-waiting we need
+		     unnecessarily expensive.  */
+		  while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex)
+		      | PTHREAD_RWLOCK_FUTEX_USED)
+		      == (1 | PTHREAD_RWLOCK_FUTEX_USED))
+		    {
+		      /* TODO Back-off?  */
+		    }
+		  ready = true;
+		  break;
+		}
+	      /* If we got interrupted (EINTR) or the futex word does not have the
+		 expected value (EAGAIN), retry.  */
+	    }
+	  if (ready)
+	    /* See below.  */
+	    break;
+	  /* We need acquire MO here so that we synchronize with the lock
+	     release of the writer, and so that we observe a recent value of
+	     __wrphase_futex (see below).  */
+	  if ((atomic_load_acquire (&rwlock->__data.__readers)
+	      & PTHREAD_RWLOCK_WRPHASE) == 0)
+	    /* We are in a read phase now, so the least recent modification of
+	       __wrphase_futex we can read from is the store by the writer
+	       with value 1.  Thus, only now we can assume that if we observe
+	       a value of 0, explicit hand-over is finished. Retry the loop
+	       above one more time.  */
+	    ready = true;
+	}
+    }
+
+  return 0;
+}
+
 
 static __always_inline void
 __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock)
@@ -924,3 +1158,360 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock,
       THREAD_GETMEM (THREAD_SELF, tid));
   return 0;
 }
+
+/* 64-bit time version */
+
+static __always_inline int
+__pthread_rwlock_wrlock_full_t64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  /* Make sure we are not holding the rwlock as a writer.  This is a deadlock
+     situation we recognize and report.  */
+  if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer)
+      == THREAD_GETMEM (THREAD_SELF, tid)))
+    return EDEADLK;
+
+  /* First we try to acquire the role of primary writer by setting WRLOCKED;
+     if it was set before, there already is a primary writer.  Acquire MO so
+     that we synchronize with previous primary writers.
+
+     We do not try to change to a write phase right away using a fetch_or
+     because we would have to reset it again and wake readers if there are
+     readers present (some readers could try to acquire the lock more than
+     once, so setting a write phase in the middle of this could cause
+     deadlock).  Changing to a write phase eagerly would only speed up the
+     transition from a read phase to a write phase in the uncontended case,
+     but it would slow down the contended case if readers are preferred (which
+     is the default).
+     We could try to CAS from a state with no readers to a write phase, but
+     this could be less scalable if readers arrive and leave frequently.  */
+  bool may_share_futex_used_flag = false;
+  unsigned int r = atomic_fetch_or_acquire (&rwlock->__data.__readers,
+      PTHREAD_RWLOCK_WRLOCKED);
+  if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRLOCKED) != 0))
+    {
+      /* There is another primary writer.  */
+      bool prefer_writer =
+	  (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP);
+      if (prefer_writer)
+	{
+	  /* We register as a waiting writer, so that we can make use of
+	     writer--writer hand-over.  Relaxed MO is fine because we just
+	     want to register.  We assume that the maximum number of threads
+	     is less than the capacity in __writers.  */
+	  atomic_fetch_add_relaxed (&rwlock->__data.__writers, 1);
+	}
+      for (;;)
+	{
+	  /* TODO Spin until WRLOCKED is 0 before trying the CAS below.
+	     But pay attention to not delay trying writer--writer hand-over
+	     for too long (which we must try eventually anyway).  */
+	  if ((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
+	    {
+	      /* Try to become the primary writer or retry.  Acquire MO as in
+		 the fetch_or above.  */
+	      if (atomic_compare_exchange_weak_acquire
+		  (&rwlock->__data.__readers, &r,
+		      r | PTHREAD_RWLOCK_WRLOCKED))
+		{
+		  if (prefer_writer)
+		    {
+		      /* Unregister as a waiting writer.  Note that because we
+			 acquired WRLOCKED, WRHANDOVER will not be set.
+			 Acquire MO on the CAS above ensures that
+			 unregistering happens after the previous writer;
+			 this sorts the accesses to __writers by all
+			 primary writers in a useful way (e.g., any other
+			 primary writer acquiring after us or getting it from
+			 us through WRHANDOVER will see both our changes to
+			 __writers).
+			 ??? Perhaps this is not strictly necessary for
+			 reasons we do not yet know of.  */
+		      atomic_fetch_add_relaxed (&rwlock->__data.__writers,
+			  -1);
+		    }
+		  break;
+		}
+	      /* Retry if the CAS fails (r will have been updated).  */
+	      continue;
+	    }
+	  /* If writer--writer hand-over is available, try to become the
+	     primary writer this way by grabbing the WRHANDOVER token.  If we
+	     succeed, we own WRLOCKED.  */
+	  if (prefer_writer)
+	    {
+	      unsigned int w = atomic_load_relaxed
+		  (&rwlock->__data.__writers);
+	      if ((w & PTHREAD_RWLOCK_WRHANDOVER) != 0)
+		{
+		  /* Acquire MO is required here so that we synchronize with
+		     the writer that handed over WRLOCKED.  We also need this
+		     for the reload of __readers below because our view of
+		     __readers must be at least as recent as the view of the
+		     writer that handed over WRLOCKED; we must avoid an ABA
+		     through WRHANDOVER, which could, for example, lead to us
+		     assuming we are still in a write phase when in fact we
+		     are not.  */
+		  if (atomic_compare_exchange_weak_acquire
+		      (&rwlock->__data.__writers,
+		       &w, (w - PTHREAD_RWLOCK_WRHANDOVER - 1)))
+		    {
+		      /* Reload so our view is consistent with the view of
+			 the previous owner of WRLOCKED.  See above.  */
+		      r = atomic_load_relaxed (&rwlock->__data.__readers);
+		      break;
+		    }
+		  /* We do not need to reload __readers here.  We should try
+		     to perform writer--writer hand-over if possible; if it
+		     is not possible anymore, we will reload __readers
+		     elsewhere in this loop.  */
+		  continue;
+		}
+	    }
+	  /* We did not acquire WRLOCKED nor were able to use writer--writer
+	     hand-over, so we block on __writers_futex.  */
+	  int private = __pthread_rwlock_get_private (rwlock);
+	  unsigned int wf = atomic_load_relaxed
+	      (&rwlock->__data.__writers_futex);
+	  if (((wf & ~(unsigned int) PTHREAD_RWLOCK_FUTEX_USED) != 1)
+	      || ((wf != (1 | PTHREAD_RWLOCK_FUTEX_USED))
+		  && !atomic_compare_exchange_weak_relaxed
+		      (&rwlock->__data.__writers_futex, &wf,
+		       1 | PTHREAD_RWLOCK_FUTEX_USED)))
+	    {
+	      /* If we cannot block on __writers_futex because there is no
+		 primary writer, or we cannot set PTHREAD_RWLOCK_FUTEX_USED,
+		 we retry.  We must reload __readers here in case we cannot
+		 block on __writers_futex so that we can become the primary
+		 writer and are not stuck in a loop that just continuously
+		 fails to block on __writers_futex.  */
+	      r = atomic_load_relaxed (&rwlock->__data.__readers);
+	      continue;
+	    }
+	  /* We set the flag that signals that the futex is used, or we could
+	     have set it if we had been faster than other waiters.  As a
+	     result, we may share the flag with an unknown number of other
+	     writers.  Therefore, we must keep this flag set when we acquire
+	     the lock.  We do not need to do this when we do not reach this
+	     point here because then we are not part of the group that may
+	     share the flag, and another writer will wake one of the writers
+	     in this group.  */
+	  may_share_futex_used_flag = true;
+	  int err = futex_abstimed_wait_t64 (&rwlock->__data.__writers_futex,
+	      1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+	  if (err == ETIMEDOUT)
+	    {
+	      if (prefer_writer)
+		{
+		  /* We need to unregister as a waiting writer.  If we are the
+		     last writer and writer--writer hand-over is available,
+		     we must make use of it because nobody else will reset
+		     WRLOCKED otherwise.  (If we use it, we simply pretend
+		     that this happened before the timeout; see
+		     pthread_rwlock_rdlock_full for the full reasoning.)
+		     Also see the similar code above.  */
+		  unsigned int w = atomic_load_relaxed
+		      (&rwlock->__data.__writers);
+		  while (!atomic_compare_exchange_weak_acquire
+		      (&rwlock->__data.__writers, &w,
+			  (w == PTHREAD_RWLOCK_WRHANDOVER + 1 ? 0 : w - 1)))
+		    {
+		      /* TODO Back-off.  */
+		    }
+		  if (w == PTHREAD_RWLOCK_WRHANDOVER + 1)
+		    {
+		      /* We must continue as primary writer.  See above.  */
+		      r = atomic_load_relaxed (&rwlock->__data.__readers);
+		      break;
+		    }
+		}
+	      /* We cleaned up and cannot have stolen another waiting writer's
+		 futex wake-up, so just return.  */
+	      return ETIMEDOUT;
+	    }
+	  /* If we got interrupted (EINTR) or the futex word does not have the
+	     expected value (EAGAIN), retry after reloading __readers.  */
+	  r = atomic_load_relaxed (&rwlock->__data.__readers);
+	}
+      /* Our snapshot of __readers is up-to-date at this point because we
+	 either set WRLOCKED using a CAS or were handed over WRLOCKED from
+	 another writer whose snapshot of __readers we inherit.  */
+    }
+
+  /* If we are in a read phase and there are no readers, try to start a write
+     phase.  */
+  while (((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+      && ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0))
+    {
+      /* Acquire MO so that we synchronize with prior writers and do
+	 not interfere with their updates to __writers_futex, as well
+	 as regarding prior readers and their updates to __wrphase_futex,
+	 respectively.  */
+      if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
+	  &r, r | PTHREAD_RWLOCK_WRPHASE))
+	{
+	  /* We have started a write phase, so need to enable readers to wait.
+	     See the similar case in__pthread_rwlock_rdlock_full.  */
+	  atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
+	  /* Make sure we fall through to the end of the function.  */
+	  r |= PTHREAD_RWLOCK_WRPHASE;
+	  break;
+	}
+      /* TODO Back-off.  */
+    }
+
+  /* We are the primary writer; enable blocking on __writers_futex.  Relaxed
+     MO is sufficient for futex words; acquire MO on the previous
+     modifications of __readers ensures that this store happens after the
+     store of value 0 by the previous primary writer.  */
+  atomic_store_relaxed (&rwlock->__data.__writers_futex,
+      1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0));
+
+  if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRPHASE) == 0))
+    {
+      /* We are not in a read phase and there are readers (because of the
+	 previous loop).  Thus, we have to wait for explicit hand-over from
+	 one of these readers.
+	 We basically do the same steps as for the similar case in
+	 __pthread_rwlock_rdlock_full, except that we additionally might try
+	 to directly hand over to another writer and need to wake up
+	 other writers or waiting readers (i.e., PTHREAD_RWLOCK_RWAITING).  */
+      unsigned int wpf;
+      bool ready = false;
+      for (;;)
+	{
+	  while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
+	      | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED)
+	    {
+	      int private = __pthread_rwlock_get_private (rwlock);
+	      if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
+		  && !atomic_compare_exchange_weak_relaxed
+		      (&rwlock->__data.__wrphase_futex, &wpf,
+		       PTHREAD_RWLOCK_FUTEX_USED))
+		continue;
+	      int err = futex_abstimed_wait_t64 (&rwlock->__data.__wrphase_futex,
+		  PTHREAD_RWLOCK_FUTEX_USED, abstime, private);
+	      if (err == ETIMEDOUT)
+		{
+		  if (rwlock->__data.__flags
+		      != PTHREAD_RWLOCK_PREFER_READER_NP)
+		    {
+		      /* We try writer--writer hand-over.  */
+		      unsigned int w = atomic_load_relaxed
+			  (&rwlock->__data.__writers);
+		      if (w != 0)
+			{
+			  /* We are about to hand over WRLOCKED, so we must
+			     release __writers_futex too; otherwise, we'd have
+			     a pending store, which could at least prevent
+			     other threads from waiting using the futex
+			     because it could interleave with the stores
+			     by subsequent writers.  In turn, this means that
+			     we have to clean up when we do not hand over
+			     WRLOCKED.
+			     Release MO so that another writer that gets
+			     WRLOCKED from us can take over our view of
+			     __readers.  */
+			  unsigned int wf = atomic_exchange_relaxed
+			      (&rwlock->__data.__writers_futex, 0);
+			  while (w != 0)
+			    {
+			      if (atomic_compare_exchange_weak_release
+				  (&rwlock->__data.__writers, &w,
+				      w | PTHREAD_RWLOCK_WRHANDOVER))
+				{
+				  /* Wake other writers.  */
+				  if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
+				    futex_wake
+					(&rwlock->__data.__writers_futex, 1,
+					 private);
+				  return ETIMEDOUT;
+				}
+			      /* TODO Back-off.  */
+			    }
+			  /* We still own WRLOCKED and someone else might set
+			     a write phase concurrently, so enable waiting
+			     again.  Make sure we don't loose the flag that
+			     signals whether there are threads waiting on
+			     this futex.  */
+			  atomic_store_relaxed
+			      (&rwlock->__data.__writers_futex, wf);
+			}
+		    }
+		  /* If we timed out and we are not in a write phase, we can
+		     just stop being a primary writer.  Otherwise, we just
+		     acquire the lock.  */
+		  r = atomic_load_relaxed (&rwlock->__data.__readers);
+		  if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+		    {
+		      /* We are about to release WRLOCKED, so we must release
+			 __writers_futex too; see the handling of
+			 writer--writer hand-over above.  */
+		      unsigned int wf = atomic_exchange_relaxed
+			  (&rwlock->__data.__writers_futex, 0);
+		      while ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
+			{
+			  /* While we don't need to make anything from a
+			     caller's critical section visible to other
+			     threads, we need to ensure that our changes to
+			     __writers_futex are properly ordered.
+			     Therefore, use release MO to synchronize with
+			     subsequent primary writers.  Also wake up any
+			     waiting readers as they are waiting because of
+			     us.  */
+			  if (atomic_compare_exchange_weak_release
+			      (&rwlock->__data.__readers, &r,
+			       (r ^ PTHREAD_RWLOCK_WRLOCKED)
+			       & ~(unsigned int) PTHREAD_RWLOCK_RWAITING))
+			    {
+			      /* Wake other writers.  */
+			      if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0)
+				futex_wake (&rwlock->__data.__writers_futex,
+				    1, private);
+			      /* Wake waiting readers.  */
+			      if ((r & PTHREAD_RWLOCK_RWAITING) != 0)
+				futex_wake (&rwlock->__data.__readers,
+				    INT_MAX, private);
+			      return ETIMEDOUT;
+			    }
+			}
+		      /* We still own WRLOCKED and someone else might set a
+			 write phase concurrently, so enable waiting again.
+			 Make sure we don't loose the flag that signals
+			 whether there are threads waiting on this futex.  */
+		      atomic_store_relaxed (&rwlock->__data.__writers_futex,
+			  wf);
+		    }
+		  /* Use the acquire MO fence to mirror the steps taken in the
+		     non-timeout case.  Note that the read can happen both
+		     in the atomic_load above as well as in the failure case
+		     of the CAS operation.  */
+		  atomic_thread_fence_acquire ();
+		  /* We still need to wait for explicit hand-over, but we must
+		     not use futex_wait anymore.  */
+		  while ((atomic_load_relaxed
+		      (&rwlock->__data.__wrphase_futex)
+		       | PTHREAD_RWLOCK_FUTEX_USED)
+		      == PTHREAD_RWLOCK_FUTEX_USED)
+		    {
+		      /* TODO Back-off.  */
+		    }
+		  ready = true;
+		  break;
+		}
+	      /* If we got interrupted (EINTR) or the futex word does not have
+		 the expected value (EAGAIN), retry.  */
+	    }
+	  /* See pthread_rwlock_rdlock_full.  */
+	  if (ready)
+	    break;
+	  if ((atomic_load_acquire (&rwlock->__data.__readers)
+	      & PTHREAD_RWLOCK_WRPHASE) != 0)
+	    ready = true;
+	}
+    }
+
+  atomic_store_relaxed (&rwlock->__data.__cur_writer,
+      THREAD_GETMEM (THREAD_SELF, tid));
+  return 0;
+}
diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c
index 9f084f8c34..174ddf11cd 100644
--- a/nptl/pthread_rwlock_timedrdlock.c
+++ b/nptl/pthread_rwlock_timedrdlock.c
@@ -35,3 +35,22 @@ pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
 
   return __pthread_rwlock_rdlock_full (rwlock, abstime);
 }
+
+/* 64-bit time version */
+
+int
+pthread_rwlock_timedrdlock_t64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  /* Make sure the passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  /* ??? Just move this to __pthread_rwlock_rdlock_full?  */
+  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
+  return __pthread_rwlock_rdlock_full_t64 (rwlock, abstime);
+}
diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c
index 5626505d2c..7b954d4a12 100644
--- a/nptl/pthread_rwlock_timedwrlock.c
+++ b/nptl/pthread_rwlock_timedwrlock.c
@@ -35,3 +35,22 @@ pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
 
   return __pthread_rwlock_wrlock_full (rwlock, abstime);
 }
+
+/* 64-bit time version */
+
+int
+pthread_rwlock_timedwrlock_t64 (pthread_rwlock_t *rwlock,
+    const struct __timespec64 *abstime)
+{
+  /* Make sure the passed in timeout value is valid.  Note that the previous
+     implementation assumed that this check *must* not be performed if there
+     would in fact be no blocking; however, POSIX only requires that "the
+     validity of the abstime parameter need not be checked if the lock can be
+     immediately acquired" (i.e., we need not but may check it).  */
+  /* ??? Just move this to __pthread_rwlock_wrlock_full?  */
+  if (__glibc_unlikely (abstime->tv_nsec >= 1000000000
+      || abstime->tv_nsec < 0))
+    return EINVAL;
+
+  return __pthread_rwlock_wrlock_full_t64 (rwlock, abstime);
+}
diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c
index 22b0778cc2..893954a969 100644
--- a/nptl/sem_timedwait.c
+++ b/nptl/sem_timedwait.c
@@ -38,3 +38,21 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
   else
     return __new_sem_wait_slow((struct new_sem *) sem, abstime);
 }
+
+int
+sem_timedwait_t64 (sem_t *sem, const struct __timespec64 *abstime)
+{
+  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  /* Check sem_wait.c for a more detailed explanation why it is required.  */
+  __pthread_testcancel ();
+
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow_t64 ((struct new_sem *) sem, abstime);
+}
diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c
index 625bf08c83..b9f37f49bf 100644
--- a/nptl/sem_wait.c
+++ b/nptl/sem_wait.c
@@ -43,6 +43,30 @@ __new_sem_wait (sem_t *sem)
 }
 versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
 
+/* 64-bit time version */
+
+int
+__new_sem_wait_t64 (sem_t *sem)
+{
+  /* We need to check whether we need to act upon a cancellation request here
+     because POSIX specifies that cancellation points "shall occur" in
+     sem_wait and sem_timedwait, which also means that they need to check
+     this regardless whether they block or not (unlike "may occur"
+     functions).  See the POSIX Rationale for this requirement: Section
+     "Thread Cancellation Overview" [1] and austin group issue #1076 [2]
+     for thoughs on why this may be a suboptimal design.
+
+     [1] http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html
+     [2] http://austingroupbugs.net/view.php?id=1076 for thoughts on why this
+   */
+  __pthread_testcancel ();
+
+  if (__new_sem_wait_fast ((struct new_sem *) sem, 0) == 0)
+    return 0;
+  else
+    return __new_sem_wait_slow_t64 ((struct new_sem *) sem, NULL);
+}
+
 #if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
 int
 attribute_compat_text_section
diff --git a/nptl/sem_waitcommon.c b/nptl/sem_waitcommon.c
index a3412a0d35..d5bfe04aeb 100644
--- a/nptl/sem_waitcommon.c
+++ b/nptl/sem_waitcommon.c
@@ -119,6 +119,24 @@ do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
   return err;
 }
 
+static int
+__attribute__ ((noinline))
+do_futex_wait_t64 (struct new_sem *sem, const struct __timespec64 *abstime)
+{
+  int err;
+
+#if __HAVE_64B_ATOMICS
+  err = futex_abstimed_wait_cancelable_t64 (
+      (unsigned int *) &sem->data + SEM_VALUE_OFFSET, 0, abstime,
+      sem->private);
+#else
+  err = futex_abstimed_wait_cancelable_t64 (&sem->value, SEM_NWAITERS_MASK,
+					abstime, sem->private);
+#endif
+
+  return err;
+}
+
 /* Fast path: Try to grab a token without blocking.  */
 static int
 __new_sem_wait_fast (struct new_sem *sem, int definitive_result)
@@ -310,6 +328,160 @@ error:
   return err;
 }
 
+/* 64-bit time version */
+
+static int
+__attribute__ ((noinline))
+__new_sem_wait_slow_t64 (struct new_sem *sem, const struct __timespec64 *abstime)
+{
+  int err = 0;
+
+#if __HAVE_64B_ATOMICS
+  /* Add a waiter.  Relaxed MO is sufficient because we can rely on the
+     ordering provided by the RMW operations we use.  */
+  uint64_t d = atomic_fetch_add_relaxed (&sem->data,
+      (uint64_t) 1 << SEM_NWAITERS_SHIFT);
+
+  pthread_cleanup_push (__sem_wait_cleanup, sem);
+
+  /* Wait for a token to be available.  Retry until we can grab one.  */
+  for (;;)
+    {
+      /* If there is no token available, sleep until there is.  */
+      if ((d & SEM_VALUE_MASK) == 0)
+	{
+	  err = do_futex_wait_t64 (sem, abstime);
+	  /* A futex return value of 0 or EAGAIN is due to a real or spurious
+	     wake-up, or due to a change in the number of tokens.  We retry in
+	     these cases.
+	     If we timed out, forward this to the caller.
+	     EINTR is returned if we are interrupted by a signal; we
+	     forward this to the caller.  (See futex_wait and related
+	     documentation.  Before Linux 2.6.22, EINTR was also returned on
+	     spurious wake-ups; we only support more recent Linux versions,
+	     so do not need to consider this here.)  */
+	  if (err == ETIMEDOUT || err == EINTR)
+	    {
+	      __set_errno (err);
+	      err = -1;
+	      /* Stop being registered as a waiter.  */
+	      atomic_fetch_add_relaxed (&sem->data,
+		  -((uint64_t) 1 << SEM_NWAITERS_SHIFT));
+	      break;
+	    }
+	  /* Relaxed MO is sufficient; see below.  */
+	  d = atomic_load_relaxed (&sem->data);
+	}
+      else
+	{
+	  /* Try to grab both a token and stop being a waiter.  We need
+	     acquire MO so this synchronizes with all token providers (i.e.,
+	     the RMW operation we read from or all those before it in
+	     modification order; also see sem_post).  On the failure path,
+	     relaxed MO is sufficient because we only eventually need the
+	     up-to-date value; the futex_wait or the CAS perform the real
+	     work.  */
+	  if (atomic_compare_exchange_weak_acquire (&sem->data,
+	      &d, d - 1 - ((uint64_t) 1 << SEM_NWAITERS_SHIFT)))
+	    {
+	      err = 0;
+	      break;
+	    }
+	}
+    }
+
+  pthread_cleanup_pop (0);
+#else
+  /* The main difference to the 64b-atomics implementation is that we need to
+     access value and nwaiters in separate steps, and that the nwaiters bit
+     in the value can temporarily not be set even if nwaiters is nonzero.
+     We work around incorrectly unsetting the nwaiters bit by letting sem_wait
+     set the bit again and waking the number of waiters that could grab a
+     token.  There are two additional properties we need to ensure:
+     (1) We make sure that whenever unsetting the bit, we see the increment of
+     nwaiters by the other thread that set the bit.  IOW, we will notice if
+     we make a mistake.
+     (2) When setting the nwaiters bit, we make sure that we see the unsetting
+     of the bit by another waiter that happened before us.  This avoids having
+     to blindly set the bit whenever we need to block on it.  We set/unset
+     the bit while having incremented nwaiters (i.e., are a registered
+     waiter), and the problematic case only happens when one waiter indeed
+     followed another (i.e., nwaiters was never larger than 1); thus, this
+     works similarly as with a critical section using nwaiters (see the MOs
+     and related comments below).
+
+     An alternative approach would be to unset the bit after decrementing
+     nwaiters; however, that would result in needing Dekker-like
+     synchronization and thus full memory barriers.  We also would not be able
+     to prevent misspeculation, so this alternative scheme does not seem
+     beneficial.  */
+  unsigned int v;
+
+  /* Add a waiter.  We need acquire MO so this synchronizes with the release
+     MO we use when decrementing nwaiters below; it ensures that if another
+     waiter unset the bit before us, we see that and set it again.  Also see
+     property (2) above.  */
+  atomic_fetch_add_acquire (&sem->nwaiters, 1);
+
+  pthread_cleanup_push (__sem_wait_cleanup, sem);
+
+  /* Wait for a token to be available.  Retry until we can grab one.  */
+  /* We do not need any ordering wrt. to this load's reads-from, so relaxed
+     MO is sufficient.  The acquire MO above ensures that in the problematic
+     case, we do see the unsetting of the bit by another waiter.  */
+  v = atomic_load_relaxed (&sem->value);
+  do
+    {
+      do
+	{
+	  /* We are about to block, so make sure that the nwaiters bit is
+	     set.  We need release MO on the CAS to ensure that when another
+	     waiter unsets the nwaiters bit, it will also observe that we
+	     incremented nwaiters in the meantime (also see the unsetting of
+	     the bit below).  Relaxed MO on CAS failure is sufficient (see
+	     above).  */
+	  do
+	    {
+	      if ((v & SEM_NWAITERS_MASK) != 0)
+		break;
+	    }
+	  while (!atomic_compare_exchange_weak_release (&sem->value,
+	      &v, v | SEM_NWAITERS_MASK));
+	  /* If there is no token, wait.  */
+	  if ((v >> SEM_VALUE_SHIFT) == 0)
+	    {
+	      /* See __HAVE_64B_ATOMICS variant.  */
+	      err = do_futex_wait_t64 (sem, abstime);
+	      if (err == ETIMEDOUT || err == EINTR)
+		{
+		  __set_errno (err);
+		  err = -1;
+		  goto error;
+		}
+	      err = 0;
+	      /* We blocked, so there might be a token now.  Relaxed MO is
+		 sufficient (see above).  */
+	      v = atomic_load_relaxed (&sem->value);
+	    }
+	}
+      /* If there is no token, we must not try to grab one.  */
+      while ((v >> SEM_VALUE_SHIFT) == 0);
+    }
+  /* Try to grab a token.  We need acquire MO so this synchronizes with
+     all token providers (i.e., the RMW operation we read from or all those
+     before it in modification order; also see sem_post).  */
+  while (!atomic_compare_exchange_weak_acquire (&sem->value,
+      &v, v - (1 << SEM_VALUE_SHIFT)));
+
+error:
+  pthread_cleanup_pop (0);
+
+  __sem_wait_32_finish (sem);
+#endif
+
+  return err;
+}
+
 /* Stop being a registered waiter (non-64b-atomics code only).  */
 #if !__HAVE_64B_ATOMICS
 static void
diff --git a/rt/Versions b/rt/Versions
index 1eef2e604f..a1c98a8576 100644
--- a/rt/Versions
+++ b/rt/Versions
@@ -48,5 +48,6 @@ librt {
     __timerfd_settime64;
     __mq_timedreceive_t64;
     __mq_timedsend_t64;
+    __aio_suspend_t64;
   }
 }
diff --git a/sysdeps/nptl/aio_misc.h b/sysdeps/nptl/aio_misc.h
index 47b1a36479..3c74f8484c 100644
--- a/sysdeps/nptl/aio_misc.h
+++ b/sysdeps/nptl/aio_misc.h
@@ -71,4 +71,43 @@
       }									      \
   } while (0)
 
+#define AIO_MISC_WAIT_T64(result, futex, timeout, cancel)		      \
+  do {									      \
+    volatile unsigned int *futexaddr = &futex;				      \
+    unsigned int oldval = futex;					      \
+									      \
+    if (oldval != 0)							      \
+      {									      \
+	pthread_mutex_unlock (&__aio_requests_mutex);			      \
+									      \
+	int oldtype;							      \
+	if (cancel)							      \
+	  oldtype = LIBC_CANCEL_ASYNC ();				      \
+									      \
+	int status;							      \
+	do								      \
+	  {								      \
+	    status = futex_reltimed_wait_t64 ((unsigned int *) futexaddr,     \
+					      oldval, timeout, FUTEX_PRIVATE);\
+	    if (status != EAGAIN)					      \
+	      break;							      \
+									      \
+	    oldval = *futexaddr;					      \
+	  }								      \
+	while (oldval != 0);						      \
+									      \
+	if (cancel)							      \
+	  LIBC_CANCEL_RESET (oldtype);					      \
+									      \
+	if (status == EINTR)						      \
+	  result = EINTR;						      \
+	else if (status == ETIMEDOUT)					      \
+	  result = EAGAIN;						      \
+	else								      \
+	  assert (status == 0 || status == EAGAIN);			      \
+									      \
+	pthread_mutex_lock (&__aio_requests_mutex);			      \
+      }									      \
+  } while (0)
+
 #include_next <aio_misc.h>
diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h
index 54e3c28b0b..cedc9daa05 100644
--- a/sysdeps/nptl/lowlevellock.h
+++ b/sysdeps/nptl/lowlevellock.h
@@ -122,6 +122,10 @@ extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
 				 int private) attribute_hidden;
 
+extern int __lll_timedlock_wait_t64 (int *futex,
+                                     const struct __timespec64 *,
+				     int private) attribute_hidden;
+
 
 /* As __lll_lock, but with a timeout.  If the timeout occurs then return
    ETIMEDOUT.  If ABSTIME is invalid, return EINVAL.  */
@@ -138,6 +142,19 @@ extern int __lll_timedlock_wait (int *futex, const struct timespec *,
 #define lll_timedlock(futex, abstime, private)  \
   __lll_timedlock (&(futex), abstime, private)
 
+#define __lll_timedlock_t64(futex, abstime, private)                \
+  ({                                                                \
+    int *__futex = (futex);                                         \
+    int __val = 0;                                                  \
+                                                                    \
+    if (__glibc_unlikely                                            \
+        (atomic_compare_and_exchange_bool_acq (__futex, 1, 0)))     \
+      __val = __lll_timedlock_wait_t64 (__futex, abstime, private); \
+    __val;                                                          \
+  })
+#define lll_timedlock_t64(futex, abstime, private)  \
+  __lll_timedlock_t64 (&(futex), abstime, private)
+
 
 /* This is an expression rather than a statement even though its value is
    void, so that it can be used in a comma expression or as an expression
diff --git a/sysdeps/pthread/aio_suspend.c b/sysdeps/pthread/aio_suspend.c
index c739285c6a..8a38754a12 100644
--- a/sysdeps/pthread/aio_suspend.c
+++ b/sysdeps/pthread/aio_suspend.c
@@ -254,3 +254,167 @@ aio_suspend (const struct aiocb *const list[], int nent,
 }
 
 weak_alias (aio_suspend, aio_suspend64)
+
+#ifdef DONT_NEED_AIO_MISC_COND
+static int
+__attribute__ ((noinline))
+do_aio_misc_wait_t64 (unsigned int *cntr, 
+		      const struct __timespec64 *timeout)
+{
+  int result = 0;
+
+  AIO_MISC_WAIT_T64 (result, *cntr, timeout, 1);
+
+  return result;
+}
+#endif
+
+int
+aio_suspend_t64 (const struct aiocb *const list[], int nent,
+	         const struct __timespec64 *timeout)
+{
+  if (__glibc_unlikely (nent < 0))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  struct waitlist waitlist[nent];
+  struct requestlist *requestlist[nent];
+#ifndef DONT_NEED_AIO_MISC_COND
+  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+#endif
+  int cnt;
+  bool any = false;
+  int result = 0;
+  unsigned int cntr = 1;
+
+  /* Request the mutex.  */
+  pthread_mutex_lock (&__aio_requests_mutex);
+
+  /* There is not yet a finished request.  Signal the request that
+     we are working for it.  */
+  for (cnt = 0; cnt < nent; ++cnt)
+    if (list[cnt] != NULL)
+      {
+	if (list[cnt]->__error_code == EINPROGRESS)
+	  {
+	    requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]);
+
+	    if (requestlist[cnt] != NULL)
+	      {
+#ifndef DONT_NEED_AIO_MISC_COND
+		waitlist[cnt].cond = &cond;
+#endif
+		waitlist[cnt].result = NULL;
+		waitlist[cnt].next = requestlist[cnt]->waiting;
+		waitlist[cnt].counterp = &cntr;
+		waitlist[cnt].sigevp = NULL;
+#ifdef BROKEN_THREAD_SIGNALS
+		waitlist[cnt].caller_pid = 0;	/* Not needed.  */
+#endif
+		requestlist[cnt]->waiting = &waitlist[cnt];
+		any = true;
+	      }
+	    else
+	      /* We will never suspend.  */
+	      break;
+	  }
+	else
+	  /* We will never suspend.  */
+	  break;
+      }
+
+
+  /* Only if none of the entries is NULL or finished to be wait.  */
+  if (cnt == nent && any)
+    {
+      struct clparam clparam =
+	{
+	  .list = list,
+	  .waitlist = waitlist,
+	  .requestlist = requestlist,
+#ifndef DONT_NEED_AIO_MISC_COND
+	  .cond = &cond,
+#endif
+	  .nent = nent
+	};
+
+      pthread_cleanup_push (cleanup, &clparam);
+
+#ifdef DONT_NEED_AIO_MISC_COND
+      result = do_aio_misc_wait_t64 (&cntr, timeout);
+#else
+      if (timeout == NULL)
+	result = pthread_cond_wait (&cond, &__aio_requests_mutex);
+      else
+	{
+	  /* We have to convert the relative timeout value into an
+	     absolute time value with pthread_cond_timedwait expects.  */
+	  struct timeval now;
+	  struct timespec abstime;
+
+	  __gettimeofday (&now, NULL);
+	  abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000;
+	  abstime.tv_sec = timeout->tv_sec + now.tv_sec;
+	  if (abstime.tv_nsec >= 1000000000)
+	    {
+	      abstime.tv_nsec -= 1000000000;
+	      abstime.tv_sec += 1;
+	    }
+
+	  result = __pthread_cond_timedwait_t64 (&cond,
+					       &__aio_requests_mutex,
+					       &abstime);
+	}
+#endif
+
+      pthread_cleanup_pop (0);
+    }
+
+  /* Now remove the entry in the waiting list for all requests
+     which didn't terminate.  */
+  while (cnt-- > 0)
+    if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS)
+      {
+	struct waitlist **listp;
+
+	assert (requestlist[cnt] != NULL);
+
+	/* There is the chance that we cannot find our entry anymore. This
+	   could happen if the request terminated and restarted again.  */
+	listp = &requestlist[cnt]->waiting;
+	while (*listp != NULL && *listp != &waitlist[cnt])
+	  listp = &(*listp)->next;
+
+	if (*listp != NULL)
+	  *listp = (*listp)->next;
+      }
+
+#ifndef DONT_NEED_AIO_MISC_COND
+  /* Release the conditional variable.  */
+  if (__glibc_unlikely (pthread_cond_destroy (&cond) != 0))
+    /* This must never happen.  */
+    abort ();
+#endif
+
+  if (result != 0)
+    {
+#ifndef DONT_NEED_AIO_MISC_COND
+      /* An error occurred.  Possibly it's ETIMEDOUT.  We have to translate
+	 the timeout error report of `pthread_cond_timedwait' to the
+	 form expected from `aio_suspend'.  */
+      if (result == ETIMEDOUT)
+	__set_errno (EAGAIN);
+      else
+#endif
+	__set_errno (result);
+
+      result = -1;
+    }
+
+  /* Release the mutex.  */
+  pthread_mutex_unlock (&__aio_requests_mutex);
+
+  return result;
+}
diff --git a/sysdeps/unix/sysv/linux/futex-internal.h b/sysdeps/unix/sysv/linux/futex-internal.h
index 1386807f5b..ceffa906c1 100644
--- a/sysdeps/unix/sysv/linux/futex-internal.h
+++ b/sysdeps/unix/sysv/linux/futex-internal.h
@@ -131,6 +131,32 @@ futex_reltimed_wait (unsigned int *futex_word, unsigned int expected,
     }
 }
 
+/* 64-bit time version */
+static __always_inline int
+futex_reltimed_wait_t64 (unsigned int *futex_word, unsigned int expected,
+		         const struct __timespec64 *reltime, int private)
+{
+  int err = lll_futex_timed_wait_t64 (futex_word, expected, reltime,
+                                      private);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
 futex_reltimed_wait_cancelable (unsigned int *futex_word,
@@ -160,6 +186,37 @@ futex_reltimed_wait_cancelable (unsigned int *futex_word,
     }
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+futex_reltimed_wait_cancelable_t64 (unsigned int *futex_word,
+				    unsigned int expected,
+			            const struct __timespec64 *reltime,
+                                    int private)
+{
+  int oldtype;
+  oldtype = __pthread_enable_asynccancel ();
+  int err = lll_futex_timed_wait_t64 (futex_word, expected, reltime, private);
+  __pthread_disable_asynccancel (oldtype);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
 futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
@@ -190,6 +247,36 @@ futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
     }
 }
 
+/* 64-bit time version */
+static __always_inline int
+futex_abstimed_wait_t64 (unsigned int *futex_word, unsigned int expected,
+		         const struct __timespec64 *abstime, int private)
+{
+  /* Work around the fact that the kernel rejects negative timeout values
+     despite them being valid.  */
+  if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
+    return ETIMEDOUT;
+  int err = lll_futex_timed_wait_bitset_t64 (futex_word, expected, abstime,
+					     FUTEX_CLOCK_REALTIME, private);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline int
 futex_abstimed_wait_cancelable (unsigned int *futex_word,
@@ -224,6 +311,42 @@ futex_abstimed_wait_cancelable (unsigned int *futex_word,
     }
 }
 
+/* 64-bit time version */
+
+static __always_inline int
+futex_abstimed_wait_cancelable_t64 (unsigned int *futex_word,
+				    unsigned int expected,
+			            const struct __timespec64 *abstime,
+                                    int private)
+{
+  /* Work around the fact that the kernel rejects negative timeout values
+     despite them being valid.  */
+  if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
+    return ETIMEDOUT;
+  int oldtype;
+  oldtype = __pthread_enable_asynccancel ();
+  int err = lll_futex_timed_wait_bitset_t64 (futex_word, expected, abstime,
+					     FUTEX_CLOCK_REALTIME, private);
+  __pthread_disable_asynccancel (oldtype);
+  switch (err)
+    {
+    case 0:
+    case -EAGAIN:
+    case -EINTR:
+    case -ETIMEDOUT:
+      return -err;
+
+    case -EFAULT: /* Must have been caused by a glibc or application bug.  */
+    case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+		     being normalized.  Must have been caused by a glibc or
+		     application bug.  */
+    case -ENOSYS: /* Must have been caused by a glibc bug.  */
+    /* No other errors are documented at this time.  */
+    default:
+      futex_fatal_error ();
+    }
+}
+
 /* See sysdeps/nptl/futex-internal.h for details.  */
 static __always_inline void
 futex_wake (unsigned int *futex_word, int processes_to_wake, int private)
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index bb4fbae13b..e1cad10544 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -97,6 +97,16 @@
 		     __lll_private_flag (FUTEX_WAIT, private),  \
 		     val, timeout)
 
+#define lll_futex_timed_wait_t64(futexp, val, timeout, private)     \
+  ({                                                                       \
+    struct timespec ts;                                                    \
+    ts.tv_sec = timeout->tv_sec;                                           \
+    ts.tv_nsec = timeout->tv_nsec;                                         \
+    lll_futex_syscall (4, futexp,                                 	   \
+		       __lll_private_flag (FUTEX_WAIT, private),  	   \
+		       val, &ts);					   \
+  })
+
 #define lll_futex_timed_wait_bitset(futexp, val, timeout, clockbit, private) \
   lll_futex_syscall (6, futexp,                                         \
 		     __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
@@ -104,6 +114,18 @@
 		     val, timeout, NULL /* Unused.  */,                 \
 		     FUTEX_BITSET_MATCH_ANY)
 
+#define lll_futex_timed_wait_bitset_t64(futexp, val, timeout, clockbit, private) \
+  ({                                                                       \
+    struct timespec ts;                                                    \
+    ts.tv_sec = timeout->tv_sec;                                           \
+    ts.tv_nsec = timeout->tv_nsec;                                         \
+    lll_futex_syscall (6, futexp,                                          \
+		       __lll_private_flag (FUTEX_WAIT_BITSET | (clockbit), \
+		                           private),                       \
+		       val, &ts, NULL /* Unused.  */,                      \
+		       FUTEX_BITSET_MATCH_ANY);                            \
+  })
+
 #define lll_futex_wake(futexp, nr, private)                             \
   lll_futex_syscall (4, futexp,                                         \
 		     __lll_private_flag (FUTEX_WAKE, private), nr, 0)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 37/52] Y2038: add function __nanosleep64_t64
  2017-09-07 22:45                                                                       ` [RFC PATCH 36/52] Y2038: add function __sched_rr_get_interval_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                         ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                           ` [RFC PATCH 38/52] Y2038: add function __adjtime_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 time/Makefile      |  2 +-
 time/Versions      |  1 +
 time/nanosleep64.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 time/nanosleep64.c

diff --git a/time/Makefile b/time/Makefile
index 5fb26f6dbf..d50c3ddfd8 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -37,7 +37,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
 	    timespec_get                                 \
-	    settimeofday64
+	    settimeofday64 nanosleep64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index d420770af3..e6812240e9 100644
--- a/time/Versions
+++ b/time/Versions
@@ -75,5 +75,6 @@ libc {
     __stime_t64;
     __gettimeofday_t64;
     __settimeofday_t64;
+    __nanosleep_t64;
   }
 }
diff --git a/time/nanosleep64.c b/time/nanosleep64.c
new file mode 100644
index 0000000000..b43b7595eb
--- /dev/null
+++ b/time/nanosleep64.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <time.h>
+
+extern int __y2038_linux_support;
+
+/* Pause execution for a number of nanoseconds.  */
+int
+__nanosleep_t64 (const struct __timespec64 *requested_time,
+	         struct __timespec64 *remaining)
+{
+  struct timespec treq32, *treqp32 = NULL;
+  struct timespec trem32, *tremp32 = NULL;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit time syscalls */
+    }
+
+  if (requested_time)
+    {
+      if (requested_time->tv_sec > INT_MAX)
+        {
+          __set_errno(EOVERFLOW);
+          return -1;
+        }
+      treq32.tv_sec = requested_time->tv_sec;
+      treq32.tv_nsec = requested_time->tv_nsec;
+      treqp32 = & treq32;
+    }
+
+  if (remaining)
+    tremp32 = &trem32;
+
+  int result = nanosleep(treqp32, tremp32);
+
+  if (result == 1 && errno == EINTR && remaining)
+    {
+      remaining->tv_sec = trem32.tv_sec;
+      remaining->tv_nsec = trem32.tv_nsec;
+      remaining->tv_pad = 0;
+    }
+
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 46/52] Y2038: add function __ntp_gettime_t64
  2017-09-07 22:45                                                                                         ` [RFC PATCH 45/52] Y2038: add struct __ntp_timeval_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                           ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                             ` [RFC PATCH 47/52] Y2038: add function __ntp_gettimex_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/Versions      |  1 +
 sysdeps/unix/sysv/linux/ntp_gettime.c | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 3fcd1c252b..38739b062a 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -178,5 +178,6 @@ libc {
 
   GLIBC_Y2038 {
     __msgctl_t64;
+    __ntp_gettime_t64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/ntp_gettime.c b/sysdeps/unix/sysv/linux/ntp_gettime.c
index 915b099dc5..3d6a52c8b9 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettime.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettime.c
@@ -18,6 +18,7 @@
 #define ntp_gettime ntp_gettime_redirect
 
 #include <sys/timex.h>
+#include <include/time.h>
 
 #undef ntp_gettime
 
@@ -39,3 +40,27 @@ ntp_gettime (struct ntptimeval *ntv)
   ntv->esterror = tntx.esterror;
   return result;
 }
+
+/* The 64-bit-time version */
+
+extern int __y2038_linux_support;
+
+int
+__ntp_gettime_t64 (struct __ntptimeval_t64 *ntv)
+{
+  struct timex tntx;
+  int result;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscall if possible
+    }
+
+  tntx.modes = 0;
+  result = __adjtimex (&tntx);
+  ntv->time.tv_sec = tntx.time.tv_sec;
+  ntv->time.tv_usec = tntx.time.tv_usec;
+  ntv->maxerror = tntx.maxerror;
+  ntv->esterror = tntx.esterror;
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 42/52] Y2038: add function __setitimer_t64
  2017-09-07 22:45                                                                                 ` [RFC PATCH 41/52] Y2038: add function __getitimer_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                   ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                     ` [RFC PATCH 43/52] Y2038: add functions using futexes Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 time/Makefile      |  2 +-
 time/Versions      |  1 +
 time/setitimer64.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 time/setitimer64.c

diff --git a/time/Makefile b/time/Makefile
index f2b50626b6..5a36d1274b 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -38,7 +38,7 @@ routines := offtime asctime clock ctime ctime_r difftime \
 	    strftime wcsftime strftime_l wcsftime_l	 \
 	    timespec_get                                 \
 	    settimeofday64 nanosleep64                   \
-	    getitimer64
+	    getitimer64 setitimer64
 aux :=	    era alt_digit lc-time-cleanup
 
 tests	:= test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
diff --git a/time/Versions b/time/Versions
index cc05014bd8..b847718757 100644
--- a/time/Versions
+++ b/time/Versions
@@ -78,5 +78,6 @@ libc {
     __nanosleep_t64;
     __adjtime_t64;
     __getitimer_t64;
+    __setitimer_t64;
   }
 }
diff --git a/time/setitimer64.c b/time/setitimer64.c
new file mode 100644
index 0000000000..79cd1ef486
--- /dev/null
+++ b/time/setitimer64.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+
+extern int __y2038_linux_support;
+
+/* Set the timer WHICH to *NEW.  If OLD is not NULL,
+   set *OLD to the old value of timer WHICH.
+   Returns 0 on success, -1 on errors.  */
+int
+__setitimer_t64 (enum __itimer_which which,
+                 const struct __itimerval_t64 *new,
+                 struct __itimerval_t64 *old)
+{
+  struct itimerval new32, *new32p = NULL;
+  struct itimerval old32, *old32p = NULL;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscall */
+    }
+
+  if (new != NULL)
+    {
+      if (new->it_interval.tv_sec > INT_MAX ||
+          new->it_value.tv_sec > INT_MAX)
+        {
+          __set_errno (EOVERFLOW);
+          return -1;
+        }
+      new32.it_interval.tv_sec = new->it_interval.tv_sec;
+      new32.it_interval.tv_usec = new->it_interval.tv_usec;
+      new32.it_value.tv_sec = new->it_value.tv_sec;
+      new32.it_value.tv_usec = new->it_value.tv_usec;
+      new32p = &new32;
+    }
+
+  if (old != NULL)
+    old32p = &old32;
+
+  int result = setitimer(which, new32p, old32p);
+
+  if (old)
+    {
+      old->it_interval.tv_sec = old32.it_interval.tv_sec;
+      old->it_interval.tv_usec = old32.it_interval.tv_usec;
+      old->it_value.tv_sec = old32.it_value.tv_sec;
+      old->it_value.tv_usec = old32.it_value.tv_usec;
+    }
+
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 38/52] Y2038: add function __adjtime_t64
  2017-09-07 22:45                                                                         ` [RFC PATCH 37/52] Y2038: add function __nanosleep64_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                           ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                             ` [RFC PATCH 39/52] Y2038: add function __utime_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/adjtime.c | 43 +++++++++++++++++++++++++++++++++++++++
 time/Versions                     |  1 +
 time/adjtime.c                    | 10 +++++++++
 3 files changed, 54 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index d98d77064e..28a75a2e40 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -90,3 +90,46 @@ ADJTIME (const struct TIMEVAL *itv, struct TIMEVAL *otv)
 #ifdef NO_LOCAL_ADJTIME
 weak_alias (__adjtime, adjtime)
 #endif
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int __adjtime_t64 (const struct __timeval64 *itv,
+                 struct __timeval64 *otv)
+{
+  struct TIMEX tntx;
+
+  if (itv)
+    {
+      struct TIMEVAL tmp;
+
+      /* We will do some check here. */
+      tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L;
+      tmp.tv_usec = itv->tv_usec % 1000000L;
+      if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC)
+	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+      tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L;
+      tntx.modes = ADJ_OFFSET_SINGLESHOT;
+    }
+  else
+    tntx.modes = ADJ_OFFSET_SS_READ;
+
+  if (__glibc_unlikely (ADJTIMEX (&tntx) < 0))
+    return -1;
+
+  if (otv)
+    {
+      if (tntx.offset < 0)
+	{
+	  otv->tv_usec = -(-tntx.offset % 1000000);
+	  otv->tv_sec  = -(-tntx.offset / 1000000);
+	}
+      else
+	{
+	  otv->tv_usec = tntx.offset % 1000000;
+	  otv->tv_sec  = tntx.offset / 1000000;
+	}
+    }
+  return 0;
+}
diff --git a/time/Versions b/time/Versions
index e6812240e9..0f4600f33c 100644
--- a/time/Versions
+++ b/time/Versions
@@ -76,5 +76,6 @@ libc {
     __gettimeofday_t64;
     __settimeofday_t64;
     __nanosleep_t64;
+    __adjtime_t64;
   }
 }
diff --git a/time/adjtime.c b/time/adjtime.c
index 180bf48e13..8c01bd0787 100644
--- a/time/adjtime.c
+++ b/time/adjtime.c
@@ -31,3 +31,13 @@ __adjtime (const struct timeval *delta, struct timeval *olddelta)
 stub_warning (adjtime)
 
 weak_alias (__adjtime, adjtime)
+
+/* 64-bit time version */
+
+int
+__adjtime_t64 (const struct __timeval64 *delta, struct __timeval64 *olddelta)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__adjtime_t64)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 47/52] Y2038: add function __ntp_gettimex_t64
  2017-09-07 22:45                                                                                           ` [RFC PATCH 46/52] Y2038: add function __ntp_gettime_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                             ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                               ` [RFC PATCH 48/52] Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64) Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sysdeps/unix/sysv/linux/Versions       |  1 +
 sysdeps/unix/sysv/linux/ntp_gettimex.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 38739b062a..5f9a7ab08d 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -179,5 +179,6 @@ libc {
   GLIBC_Y2038 {
     __msgctl_t64;
     __ntp_gettime_t64;
+    __ntp_gettimex_t64;
   }
 }
diff --git a/sysdeps/unix/sysv/linux/ntp_gettimex.c b/sysdeps/unix/sysv/linux/ntp_gettimex.c
index 8ac180163d..c47da4daff 100644
--- a/sysdeps/unix/sysv/linux/ntp_gettimex.c
+++ b/sysdeps/unix/sysv/linux/ntp_gettimex.c
@@ -16,6 +16,7 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <sys/timex.h>
+#include <include/time.h>
 
 #ifndef MOD_OFFSET
 # define modes mode
@@ -40,3 +41,33 @@ ntp_gettimex (struct ntptimeval *ntv)
   ntv->__glibc_reserved4 = 0;
   return result;
 }
+
+/* The 64-bit-time version */
+
+extern int __y2038_linux_support;
+
+int
+__ntp_gettimex_t64 (struct __ntptimeval_t64 *ntv)
+{
+  struct timex tntx;
+  int result;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit syscall if possible
+    }
+
+  tntx.modes = 0;
+  result = __adjtimex (&tntx);
+  ntv->time.tv_sec = tntx.time.tv_sec;
+  ntv->time.tv_usec = tntx.time.tv_usec;
+  ntv->maxerror = tntx.maxerror;
+  ntv->maxerror = tntx.maxerror;
+  ntv->esterror = tntx.esterror;
+  ntv->tai = tntx.tai;
+  ntv->__glibc_reserved1 = 0;
+  ntv->__glibc_reserved2 = 0;
+  ntv->__glibc_reserved3 = 0;
+  ntv->__glibc_reserved4 = 0;
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 36/52] Y2038: add function __sched_rr_get_interval_t64
  2017-09-07 22:44                                                                     ` [RFC PATCH 35/52] Y2038: add function __msgctl_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                       ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                         ` [RFC PATCH 37/52] Y2038: add function __nanosleep64_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 posix/Makefile        |  3 ++-
 posix/Versions        |  7 +++++++
 posix/sched_rr_gi64.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 posix/sched_rr_gi64.c

diff --git a/posix/Makefile b/posix/Makefile
index 33abcaed7a..e5b8fd28f3 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -61,7 +61,8 @@ routines :=								      \
 	spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
 	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
 	posix_madvise							      \
-	get_child_max sched_cpucount sched_cpualloc sched_cpufree
+	get_child_max sched_cpucount sched_cpualloc sched_cpufree	      \
+	sched_rr_gi64
 
 aux		:= init-posix environ
 tests		:= test-errno tstgetopt testfnm runtests runptests \
diff --git a/posix/Versions b/posix/Versions
index bb481a505b..dd6d8340d5 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -137,4 +137,11 @@ libc {
   GLIBC_PRIVATE {
     __libc_fork; __libc_pread; __libc_pwrite;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __sched_rr_get_interval_t64;
+  }
 }
diff --git a/posix/sched_rr_gi64.c b/posix/sched_rr_gi64.c
new file mode 100644
index 0000000000..7f4f5cf729
--- /dev/null
+++ b/posix/sched_rr_gi64.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sched.h>
+#include <sys/types.h>
+
+extern int __y2038_linux_support;
+
+/* Get the SCHED_RR interval for the named process.  */
+
+int
+__sched_rr_get_interval_t64 (pid_t pid, struct __timespec64 *t)
+{
+  struct timespec ts32;
+  int result;
+
+  if (t == NULL)
+    {
+      __set_errno(EINVAL);
+      return -1;
+    }
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: use 64-bit syscall */
+    }
+
+  result = sched_rr_get_interval(pid, &ts32);
+  if (result == 0)
+    {
+      t->tv_sec = ts32.tv_sec;
+      t->tv_nsec = ts32.tv_nsec;
+      t->tv_pad = 0;
+    }
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 48/52] Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64)
  2017-09-07 22:45                                                                                             ` [RFC PATCH 47/52] Y2038: add function __ntp_gettimex_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                               ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:46                                                                                                 ` [RFC PATCH 49/52] Y2038: add function pselect Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                    | 31 +++++++++++++++
 sysdeps/unix/sysv/linux/adjtime.c | 81 +++++++++++++++++++++++++++++++++++++++
 time/Versions                     |  1 +
 3 files changed, 113 insertions(+)

diff --git a/include/time.h b/include/time.h
index 5db1d44470..1914c20a75 100644
--- a/include/time.h
+++ b/include/time.h
@@ -72,6 +72,37 @@ struct __ntptimeval_t64
   long int __glibc_reserved4;
 };
 
+/* 64-bit time version of the current struct timex */
+struct __timex_t64
+{
+  unsigned int modes;		/* mode selector */
+  __syscall_slong_t offset;	/* time offset (usec) */
+  __syscall_slong_t freq;	/* frequency offset (scaled ppm) */
+  __syscall_slong_t maxerror;	/* maximum error (usec) */
+  __syscall_slong_t esterror;	/* estimated error (usec) */
+  int status;			/* clock command/status */
+  __syscall_slong_t constant;	/* pll time constant */
+  __syscall_slong_t precision;	/* clock precision (usec) (ro) */
+  __syscall_slong_t tolerance;	/* clock frequency tolerance (ppm) (ro) */
+  struct __timeval64 time;	/* (read only, except for ADJ_SETOFFSET) */
+  __syscall_slong_t tick;	/* (modified) usecs between clock ticks */
+  __syscall_slong_t ppsfreq;	/* pps frequency (scaled ppm) (ro) */
+  __syscall_slong_t jitter;	/* pps jitter (us) (ro) */
+  int shift;			/* interval duration (s) (shift) (ro) */
+  __syscall_slong_t stabil;	/* pps stability (scaled ppm) (ro) */
+  __syscall_slong_t jitcnt;	/* jitter limit exceeded (ro) */
+  __syscall_slong_t calcnt;	/* calibration intervals (ro) */
+  __syscall_slong_t errcnt;	/* calibration errors (ro) */
+  __syscall_slong_t stbcnt;	/* stability limit exceeded (ro) */
+
+  int tai;			/* TAI offset (ro) */
+
+  /* ??? */
+  int  :32; int  :32; int  :32; int  :32;
+  int  :32; int  :32; int  :32; int  :32;
+  int  :32; int  :32; int  :32;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index 28a75a2e40..60211a5223 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -19,6 +19,7 @@
 #include <limits.h>
 #include <sys/time.h>
 #include <sys/timex.h>
+#include <include/time.h>
 
 #define MAX_SEC	(INT_MAX / 1000000L - 2)
 #define MIN_SEC	(INT_MIN / 1000000L + 2)
@@ -133,3 +134,83 @@ int __adjtime_t64 (const struct __timeval64 *itv,
     }
   return 0;
 }
+
+int
+__adjtimex_t64(struct __timex_t64 *tx)
+{
+  struct timex tx32;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: implement with a 64-bit time syscall */
+    }
+
+  if (tx == NULL)
+    {
+      __set_errno (EFAULT);
+      return -1;
+    }
+
+  if ((tx->modes & ADJ_SETOFFSET) != 0 && tx->time.tv_sec > INT_MAX)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  /* Implement with existing 32-bit time syscall */
+
+  /* Just copy everything */
+  tx32.modes = tx->modes;
+  tx32.offset = tx->offset;
+  tx32.freq = tx->freq;
+  tx32.maxerror = tx->maxerror;
+  tx32.esterror = tx->esterror;
+  tx32.status = tx->status;
+  tx32.constant = tx->constant;
+  tx32.precision = tx->precision;
+  tx32.tolerance = tx->tolerance;
+  tx32.time.tv_sec = tx->time.tv_sec;
+  tx32.time.tv_usec = tx->time.tv_usec;
+  tx32.tick = tx->tick;
+  tx32.ppsfreq = tx->ppsfreq;
+  tx32.jitter = tx->jitter;
+  tx32.shift = tx->shift;
+  tx32.stabil = tx->stabil;
+  tx32.jitcnt = tx->jitcnt;
+  tx32.calcnt = tx->calcnt;
+  tx32.errcnt = tx->errcnt;
+  tx32.stbcnt = tx->stbcnt;
+
+  tx32.tai = tx->tai;
+  /* WARNING -- anonymous fields after TAI are not copied. */
+
+  int result = ADJTIMEX(&tx32);
+
+  if (result == 0)
+    {
+      /* Just copy back everything */
+      tx->modes = tx32.modes;
+      tx->offset = tx32.offset;
+      tx->freq = tx32.freq;
+      tx->maxerror = tx32.maxerror;
+      tx->esterror = tx32.esterror;
+      tx->status = tx32.status;
+      tx->constant = tx32.constant;
+      tx->precision = tx32.precision;
+      tx->tolerance = tx32.tolerance;
+      tx->time.tv_sec = tx32.time.tv_sec;
+      tx->time.tv_usec = tx32.time.tv_usec;
+      tx->tick = tx32.tick;
+      tx->ppsfreq = tx32.ppsfreq;
+      tx->jitter = tx32.jitter;
+      tx->shift = tx32.shift;
+      tx->stabil = tx32.stabil;
+      tx->jitcnt = tx32.jitcnt;
+      tx->calcnt = tx32.calcnt;
+      tx->errcnt = tx32.errcnt;
+      tx->stbcnt = tx32.stbcnt;
+    }
+
+  return result;
+}
+weak_alias (__adjtimex_t64, __ntp_adjtime_t64);
diff --git a/time/Versions b/time/Versions
index b847718757..9e23793cfb 100644
--- a/time/Versions
+++ b/time/Versions
@@ -79,5 +79,6 @@ libc {
     __adjtime_t64;
     __getitimer_t64;
     __setitimer_t64;
+    __adjtimex_t64;
   }
 }
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 44/52] Y2038: add function __getrusage_t64
  2017-09-07 22:45                                                                                     ` [RFC PATCH 43/52] Y2038: add functions using futexes Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                       ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                         ` [RFC PATCH 45/52] Y2038: add struct __ntp_timeval_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 resource/Makefile      |   2 +-
 resource/Versions      |   7 ++
 resource/getrusage64.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 193 insertions(+), 1 deletion(-)
 create mode 100644 resource/getrusage64.c

diff --git a/resource/Makefile b/resource/Makefile
index 06bc7a2fb2..81a865105b 100644
--- a/resource/Makefile
+++ b/resource/Makefile
@@ -23,7 +23,7 @@ headers	  := sys/resource.h bits/resource.h sys/vlimit.h sys/vtimes.h	\
 	     ulimit.h bits/types/struct_rusage.h
 
 routines := getrlimit setrlimit getrlimit64 setrlimit64 getrusage ulimit      \
-	    vlimit vtimes getpriority setpriority nice
+	    vlimit vtimes getpriority setpriority nice getrusage64
 
 tests = tst-getrlimit bug-ulimit1
 
diff --git a/resource/Versions b/resource/Versions
index d6c2ccee1b..84f3a79769 100644
--- a/resource/Versions
+++ b/resource/Versions
@@ -25,4 +25,11 @@ libc {
   GLIBC_PRIVATE {
     __getrlimit;
   }
+
+  # Y2038 symbols are given their own version until they can be put in
+  # the right place
+
+  GLIBC_Y2038 {
+    __getrusage_t64;
+  }
 }
diff --git a/resource/getrusage64.c b/resource/getrusage64.c
new file mode 100644
index 0000000000..6c81137a8b
--- /dev/null
+++ b/resource/getrusage64.c
@@ -0,0 +1,185 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/resource.h>
+#include <include/time.h>
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+/* Structure which says how much of each resource has been used.  */
+/* 64-bit time version */
+/* The purpose of all the unions is to have the kernel-compatible layout
+   while keeping the API type as 'long int', and among machines where
+   __syscall_slong_t is not 'long int', this only does the right thing
+   for little-endian ones, like x32.  */
+struct __rusage_t64
+  {
+    /* Total amount of user time used.  */
+    struct __timeval64 ru_utime;
+    /* Total amount of system time used.  */
+    struct __timeval64 ru_stime;
+    /* Maximum resident set size (in kilobytes).  */
+    __extension__ union
+      {
+	long int ru_maxrss;
+	__syscall_slong_t __ru_maxrss_word;
+      };
+    /* Amount of sharing of text segment memory
+       with other processes (kilobyte-seconds).  */
+    /* Maximum resident set size (in kilobytes).  */
+    __extension__ union
+      {
+	long int ru_ixrss;
+	__syscall_slong_t __ru_ixrss_word;
+      };
+    /* Amount of data segment memory used (kilobyte-seconds).  */
+    __extension__ union
+      {
+	long int ru_idrss;
+	__syscall_slong_t __ru_idrss_word;
+      };
+    /* Amount of stack memory used (kilobyte-seconds).  */
+    __extension__ union
+      {
+	long int ru_isrss;
+	 __syscall_slong_t __ru_isrss_word;
+      };
+    /* Number of soft page faults (i.e. those serviced by reclaiming
+       a page from the list of pages awaiting reallocation.  */
+    __extension__ union
+      {
+	long int ru_minflt;
+	__syscall_slong_t __ru_minflt_word;
+      };
+    /* Number of hard page faults (i.e. those that required I/O).  */
+    __extension__ union
+      {
+	long int ru_majflt;
+	__syscall_slong_t __ru_majflt_word;
+      };
+    /* Number of times a process was swapped out of physical memory.  */
+    __extension__ union
+      {
+	long int ru_nswap;
+	__syscall_slong_t __ru_nswap_word;
+      };
+    /* Number of input operations via the file system.  Note: This
+       and `ru_oublock' do not include operations with the cache.  */
+    __extension__ union
+      {
+	long int ru_inblock;
+	__syscall_slong_t __ru_inblock_word;
+      };
+    /* Number of output operations via the file system.  */
+    __extension__ union
+      {
+	long int ru_oublock;
+	__syscall_slong_t __ru_oublock_word;
+      };
+    /* Number of IPC messages sent.  */
+    __extension__ union
+      {
+	long int ru_msgsnd;
+	__syscall_slong_t __ru_msgsnd_word;
+      };
+    /* Number of IPC messages received.  */
+    __extension__ union
+      {
+	long int ru_msgrcv;
+	__syscall_slong_t __ru_msgrcv_word;
+      };
+    /* Number of signals delivered.  */
+    __extension__ union
+      {
+	long int ru_nsignals;
+	__syscall_slong_t __ru_nsignals_word;
+      };
+    /* Number of voluntary context switches, i.e. because the process
+       gave up the process before it had to (usually to wait for some
+       resource to be available).  */
+    __extension__ union
+      {
+	long int ru_nvcsw;
+	__syscall_slong_t __ru_nvcsw_word;
+      };
+    /* Number of involuntary context switches, i.e. a higher priority process
+       became runnable or the current process used up its time slice.  */
+    __extension__ union
+      {
+	long int ru_nivcsw;
+	__syscall_slong_t __ru_nivcsw_word;
+      };
+  };
+
+extern int __y2038_linux_support;
+
+int __getrusage_t64 (__rusage_who_t __who, struct __rusage_t64 *__usage)
+{
+  int result;
+  struct rusage usage32;
+
+  if (__y2038_linux_support)
+    {
+      // TODO: use 64-bit-time syscall if available
+    }
+
+  result = INLINE_SYSCALL(getrusage, 2, __who, &usage32);
+  /* Copy fields from 32-bit into 64-bit rusage structure */
+  /* Total amount of user time used.  */
+  __usage->ru_utime.tv_sec = usage32.ru_utime.tv_sec;
+  __usage->ru_utime.tv_usec = usage32.ru_utime.tv_usec;
+  /* Total amount of system time used.  */
+  __usage->ru_stime.tv_sec = usage32.ru_stime.tv_sec;
+  __usage->ru_stime.tv_usec = usage32.ru_stime.tv_usec;
+  /* Maximum resident set size (in kilobytes).  */
+  __usage->ru_maxrss = usage32.ru_maxrss;
+  /* Amount of sharing of text segment memory
+     with other processes (kilobyte-seconds).  */
+  /* Maximum resident set size (in kilobytes).  */
+  __usage->ru_ixrss = usage32.ru_ixrss;
+  /* Amount of data segment memory used (kilobyte-seconds).  */
+  __usage->ru_idrss = usage32.ru_idrss;
+  /* Amount of stack memory used (kilobyte-seconds).  */
+  __usage->ru_isrss = usage32.ru_isrss;
+  /* Number of soft page faults (i.e. those serviced by reclaiming
+     a page from the list of pages awaiting reallocation.  */
+  __usage->ru_minflt = usage32.ru_minflt;
+  /* Number of hard page faults (i.e. those that required I/O).  */
+  __usage->ru_majflt = usage32.ru_majflt;
+  /* Number of times a process was swapped out of physical memory.  */
+  __usage->ru_nswap = usage32.ru_nswap;
+  /* Number of input operations via the file system.  Note: This
+     and `ru_oublock' do not include operations with the cache.  */
+  __usage->ru_inblock = usage32.ru_inblock;
+  /* Number of output operations via the file system.  */
+  __usage->ru_oublock = usage32.ru_oublock;
+  /* Number of IPC messages sent.  */
+  __usage->ru_msgsnd = usage32.ru_msgsnd;
+  /* Number of IPC messages received.  */
+  __usage->ru_msgrcv = usage32.ru_msgrcv;
+  /* Number of signals delivered.  */
+  __usage->ru_nsignals = usage32.ru_nsignals;
+  /* Number of voluntary context switches, i.e. because the process
+     gave up the process before it had to (usually to wait for some
+     resource to be available).  */
+  __usage->ru_nvcsw = usage32.ru_nvcsw;
+  /* Number of involuntary context switches, i.e. a higher priority process
+     became runnable or the current process used up its time slice.  */
+  __usage->ru_nivcsw = usage32.ru_nivcsw;
+
+  return result;
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 45/52] Y2038: add struct __ntp_timeval_t64
  2017-09-07 22:45                                                                                       ` [RFC PATCH 44/52] Y2038: add function __getrusage_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                                         ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                                           ` [RFC PATCH 46/52] Y2038: add function __ntp_gettime_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/time.h b/include/time.h
index 47ec6e67b6..5db1d44470 100644
--- a/include/time.h
+++ b/include/time.h
@@ -59,6 +59,19 @@ struct __itimerval_t64
   struct __timeval64 it_value;
 };
 
+struct __ntptimeval_t64
+{
+  struct __timeval64 time;	/* current time (ro) */
+  long int maxerror;	/* maximum error (us) (ro) */
+  long int esterror;	/* estimated error (us) (ro) */
+  long int tai;		/* TAI offset (ro) */
+
+  long int __glibc_reserved1;
+  long int __glibc_reserved2;
+  long int __glibc_reserved3;
+  long int __glibc_reserved4;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 39/52] Y2038: add function __utime_t64
  2017-09-07 22:45                                                                           ` [RFC PATCH 38/52] Y2038: add function __adjtime_t64 Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:45                                                                             ` Albert ARIBAUD (3ADEV)
  2017-09-07 22:45                                                                               ` [RFC PATCH 40/52] Y2038: add struct __itimerval_t64 Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:45 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/utime.h       |  7 +++++++
 io/Versions           |  1 +
 io/utime.c            | 16 ++++++++++++++++
 sysdeps/posix/utime.c | 22 ++++++++++++++++++++++
 4 files changed, 46 insertions(+)

diff --git a/include/utime.h b/include/utime.h
index 5049251311..eb907f7472 100644
--- a/include/utime.h
+++ b/include/utime.h
@@ -6,4 +6,11 @@
 libc_hidden_proto (utime)
 #endif
 
+/* Structure describing file times, 64-bit time version.  */
+struct __utimbuf64
+  {
+    __time64_t actime;		/* Access time.  */
+    __time64_t modtime;		/* Modification time.  */
+  };
+
 #endif /* utime.h */
diff --git a/io/Versions b/io/Versions
index 33629a0d4e..622eb6fe12 100644
--- a/io/Versions
+++ b/io/Versions
@@ -134,5 +134,6 @@ libc {
     __xstat64_t64;
     __lxstat64_t64;
     __fxstatat64_t64;
+    __utime_t64;
   }
 }
diff --git a/io/utime.c b/io/utime.c
index 242ccd120a..776203896b 100644
--- a/io/utime.c
+++ b/io/utime.c
@@ -37,3 +37,19 @@ utime (const char *file, const struct utimbuf *times)
 libc_hidden_def (utime)
 
 stub_warning (utime)
+
+/* 64-bit time version */
+
+int
+__utime_t64 (const char *file, const struct utimbuf *times)
+{
+  if (file == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
+}
+stub_warning (__utime_t64)
diff --git a/sysdeps/posix/utime.c b/sysdeps/posix/utime.c
index c8fe60ba91..d6662b7d4b 100644
--- a/sysdeps/posix/utime.c
+++ b/sysdeps/posix/utime.c
@@ -45,3 +45,25 @@ utime (const char *file, const struct utimbuf *times)
   return __utimes (file, tvp);
 }
 libc_hidden_def (utime)
+
+/* 64-bit time version */
+
+int
+__utime_t64 (const char *file, const struct __utimbuf64 *times)
+{
+  struct __timeval64 timevals[2];
+  struct __timeval64 *tvp;
+
+  if (times != NULL)
+    {
+      timevals[0].tv_sec = (time_t) times->actime;
+      timevals[0].tv_usec = 0L;
+      timevals[1].tv_sec = (time_t) times->modtime;
+      timevals[1].tv_usec = 0L;
+      tvp = timevals;
+    }
+  else
+    tvp = NULL;
+
+  return __utimes_t64 (file, tvp);
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 49/52] Y2038: add function pselect
  2017-09-07 22:45                                                                                               ` [RFC PATCH 48/52] Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64) Albert ARIBAUD (3ADEV)
@ 2017-09-07 22:46                                                                                                 ` Albert ARIBAUD (3ADEV)
  2017-09-08 17:49                                                                                                   ` [RFC PATCH 50/52] Y2038: add function select Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-07 22:46 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/select.h              | 10 +++++++
 sysdeps/unix/sysv/linux/pselect.c | 61 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/include/sys/select.h b/include/sys/select.h
index 07bb49b994..3eb76faf9d 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -3,6 +3,9 @@
 
 #ifndef _ISOMAC
 /* Now define the internal interfaces.  */
+
+#include <include/time.h>
+
 extern int __pselect (int __nfds, fd_set *__readfds,
 		      fd_set *__writefds, fd_set *__exceptfds,
 		      const struct timespec *__timeout,
@@ -14,5 +17,12 @@ extern int __select (int __nfds, fd_set *__restrict __readfds,
 		     struct timeval *__restrict __timeout);
 libc_hidden_proto (__select)
 
+/* 64-bit time version */
+
+extern int __pselect_t64 (int __nfds, fd_set *__readfds,
+		         fd_set *__writefds, fd_set *__exceptfds,
+		         const struct __timespec64 *__timeout,
+		         const __sigset_t *__sigmask);
+
 #endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index b5e8c7fbcd..ce8db34843 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -79,6 +79,67 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 }
 weak_alias (__pselect, pselect)
 
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__pselect_t64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+	       const struct __timespec64 *timeout, const sigset_t *sigmask)
+{
+  struct timespec tval32, *timeout32 = NULL;
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using Linux kernel system call */
+  }
+
+  /* The Linux kernel can in some situations update the timeout value.
+     We do not want that so use a local variable.  */
+  if (timeout != NULL)
+    {
+      if (timeout->tv_sec > INT_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      tval32.tv_sec = timeout->tv_sec;
+      tval32.tv_nsec = timeout->tv_nsec;
+      timeout32 = &tval32;
+    }
+
+  /* Note: the system call expects 7 values but on most architectures
+     we can only pass in 6 directly.  If there is an architecture with
+     support for more parameters a new version of this file needs to
+     be created.  */
+  struct
+  {
+    __syscall_ulong_t ss;
+    __syscall_ulong_t ss_len;
+  } data;
+
+  data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
+  data.ss_len = _NSIG / 8;
+
+  int result;
+
+#ifndef CALL_PSELECT6
+# define CALL_PSELECT6(nfds, readfds, writefds, exceptfds, timeout, data) \
+  SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds,	timeout32, data)
+#endif
+
+  result = CALL_PSELECT6 (nfds, readfds, writefds, exceptfds, timeout32,
+			  &data);
+
+# ifndef __ASSUME_PSELECT
+  if (result == -1 && errno == ENOSYS)
+    result = __generic_pselect (nfds, readfds, writefds, exceptfds, timeout32,
+				sigmask);
+# endif
+
+  return result;
+}
+
 # ifndef __ASSUME_PSELECT
 #  define __pselect static __generic_pselect
 # endif
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-07 22:42 [RFC PATCH 00/52] Make GLIBC Y2038-proof Albert ARIBAUD (3ADEV)
  2017-09-07 22:42 ` [RFC PATCH 01/52] Y2038: add type __time64_t Albert ARIBAUD (3ADEV)
@ 2017-09-07 23:21 ` Joseph Myers
  2017-09-08 16:19   ` Zack Weinberg
  2017-09-08 17:08   ` Albert ARIBAUD
  2017-09-08  4:23 ` Albert ARIBAUD
  2 siblings, 2 replies; 76+ messages in thread
From: Joseph Myers @ 2017-09-07 23:21 UTC (permalink / raw)
  To: Albert ARIBAUD (3ADEV); +Cc: libc-alpha

General observations on this patch series:

* Nothing should use a GLIBC_Y2038 version.  Use GLIBC_2.27 and update as 
necessary during rebases if this doesn't get into 2.27.

* Nothing should go in architecture-specific files such as 
sysdeps/unix/sysv/linux/arm/Versions.  For OS-independent interfaces use 
files such as time/Versions - wherever the existing versions of those 
interfaces for existing time_t are.

* How such a patch series was tested needs to be described in the summary 
of the series.  For a series like this, full testsuite runs on multiple 
32-bit and 64-bit architectures as well as use of build-many-glibcs.py to 
do the compilation tests for (almost) all configurations is important (or 
if a series is a preliminary version with limited architecture support, 
that should be stated explicitly, but the full testsuite should still pass 
on at least one 32-bit and one 64-bit architecture).

* I'd expect lots of extra tests using _TIME_BITS=64 to be added in such a 
patch series, to make sure that every new ABI is covered by the testsuite.

* Documentation of _TIME_BITS is clearly needed.

* You need to make sure that new ABIs are not added / used on platforms 
where time_t is already 64-bit.

* All new files need a descriptive first line before the copyright notice.

* All copyright ranges in new files should end with 2017.

* No "Contributed by" in new files.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-07 22:42 [RFC PATCH 00/52] Make GLIBC Y2038-proof Albert ARIBAUD (3ADEV)
  2017-09-07 22:42 ` [RFC PATCH 01/52] Y2038: add type __time64_t Albert ARIBAUD (3ADEV)
  2017-09-07 23:21 ` [RFC PATCH 00/52] Make GLIBC Y2038-proof Joseph Myers
@ 2017-09-08  4:23 ` Albert ARIBAUD
  2 siblings, 0 replies; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-08  4:23 UTC (permalink / raw)
  To: libc-alpha

On Fri,  8 Sep 2017 00:41:27 +0200, "Albert ARIBAUD (3ADEV)"
<albert.aribaud@3adev.fr> wrote :

> This series implements Y2038-proof types, implementation, internal
> functions, and APIs. For more information, see documentation at
> https://sourceware.org/glibc/wiki/Y2038ProofnessDesign
> 
> Each patch in this series except the last add one type or function,
> with a few exception where several functions are implemented as a whole.
> 
> The last patch enables the _TIME_BITS mechanism. Once this patch is
> applied, API header files will will use 64-bit time if _TIME_BITS is
> defined and equal to 64 prior to their inclusion, and conversively,
> will use 32-bit time if _TIME_BITS is different from 64 or does not
> exist.

Additional info: this RFC patch series only works on ARM, but it should
be extended to all 32-bit architectures later.

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-07 23:21 ` [RFC PATCH 00/52] Make GLIBC Y2038-proof Joseph Myers
@ 2017-09-08 16:19   ` Zack Weinberg
  2017-09-08 16:43     ` Joseph Myers
  2017-09-08 17:42     ` Albert ARIBAUD
  2017-09-08 17:08   ` Albert ARIBAUD
  1 sibling, 2 replies; 76+ messages in thread
From: Zack Weinberg @ 2017-09-08 16:19 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Albert ARIBAUD (3ADEV), GNU C Library

On Thu, Sep 7, 2017 at 7:21 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> General observations on this patch series:

I concur with all of Joseph's observations and would add:

> * You need to make sure that new ABIs are not added / used on platforms
> where time_t is already 64-bit.

Elaborating on this, when time_t is already 64 bits, defining
_TIME_BITS=64 should have no effect on the generated code, and
defining _TIME_BITS=32 should cause a compile-time error.

* We are not going to land these patches until the kernel side is
finalized.  All of the places where you have "// TODO: implement after
the kernel does" must be replaced with an actual implementation.
Likewise, we need a complete implementation for all supported
architectures before landing.  You're not on the hook to implement
this feature for the Hurd, but you should coordinate with Samuel
Thibault so that at least you do not make glibc-for-Hurd more broken
than it already is.

(But I would encourage you to create a named branch in glibc git for
this project if you haven't already, to make it easier for others to
experiment with it.)

* I understand that you are trying to make the transition as seamless
as possible with _TIME_BITS and so on, but I would seriously question
whether it is appropriate to preserve super-legacy APIs such as
'stime' and 'utime' in the extended mode.  (I'd put the cutoff at
'gettimeofday', which is still heavily used even though
'clock_gettime' officially supersedes it.)

* The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
is, as discussed at great length earlier, incorrect and should be
ignored.  It should instead be a new typedef 'nsec_t' available in
<sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
field (all _t names are reserved for future extension, so the typedef
doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
HTML5 folks put it) must, of course, be documented.

* We do not use Signed-off-by: and we actively want you to _not_
include it in your patch submissions.  (We have the FSF-mandated
actual copyright assignments instead.)

* The patch series is split too finely.  I recommend breaking it up by
type instead of by function -- time64_t + all the functions that use
only time64_t; struct timeval64 + all the functions that use only
time64_t and/or struct timeval64; and so on.

zw

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 16:19   ` Zack Weinberg
@ 2017-09-08 16:43     ` Joseph Myers
  2017-09-08 16:54       ` Paul Eggert
  2017-09-08 17:01       ` Zack Weinberg
  2017-09-08 17:42     ` Albert ARIBAUD
  1 sibling, 2 replies; 76+ messages in thread
From: Joseph Myers @ 2017-09-08 16:43 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Albert ARIBAUD (3ADEV), GNU C Library

On Fri, 8 Sep 2017, Zack Weinberg wrote:

> * I understand that you are trying to make the transition as seamless
> as possible with _TIME_BITS and so on, but I would seriously question
> whether it is appropriate to preserve super-legacy APIs such as
> 'stime' and 'utime' in the extended mode.  (I'd put the cutoff at
> 'gettimeofday', which is still heavily used even though
> 'clock_gettime' officially supersedes it.)

I don't think utime is super-legacy; it's in the 2008 edition of POSIX.  
Now, stime is not part of any supported standard (it was withdrawn in 
XPG3) - such old BSD/SVID interfaces that are now in __USE_MISC but no 
other standard are definitely worth considering for obsoletion (removing 
declarations / documentation, making into compat symbols not available for 
new ports / static linking) if there are clear replacements for any 
current uses / not much current use.  And such obsoletion for nonstandard 
time-related interfaces may well be a useful preliminary to reduce the 
number of interfaces needing _TIME_BITS=64 versions.  (Many such 
interfaces are of course not time-related but just as deserving of 
consideration for obsoletion; in general obsoletion of one such interface 
is independent of obsoletion of any others.)

> * The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
> is, as discussed at great length earlier, incorrect and should be
> ignored.  It should instead be a new typedef 'nsec_t' available in

And as discussed, I disagree and don't think we should invent any such 
typedef or deviate from this requirement, given that long is fully able to 
represent all valid nanoseconds values, in the absence of clear evidence 
that POSIX and ISO C agree with removing that requirement (e.g. an Austin 
Group issue tagged issue8 with accepted changes for the next revision of 
POSIX, combined with acceptance for C2X in WG14 minutes of the issue 
raised by the Austin Group liaison - or a WG14 change accepted for C2X 
with agreement on the Austin Group side following the change being passed 
in the other direction).  When the matter was raised with the Austin Group 
in May 2014, no-one contradicted Rich Felker's comment (which I agree 
with) that the x32 issue is just a Linux kernel bug which needs to be 
fixed.  (I think this use of long is *less* of an issue than e.g. printf 
returning int, since you can legitimately print more characters than fit 
in int.)

> <sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
> field (all _t names are reserved for future extension, so the typedef
> doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the

They are not reserved in ISO C, only in POSIX.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 16:43     ` Joseph Myers
@ 2017-09-08 16:54       ` Paul Eggert
  2017-09-08 17:01       ` Zack Weinberg
  1 sibling, 0 replies; 76+ messages in thread
From: Paul Eggert @ 2017-09-08 16:54 UTC (permalink / raw)
  To: Joseph Myers, Zack Weinberg; +Cc: Albert ARIBAUD (3ADEV), GNU C Library

On 09/08/2017 09:43 AM, Joseph Myers wrote:
> (I think this use of long is*less*  of an issue than e.g. printf
> returning int, since you can legitimately print more characters than fit
> in int.)

printf is obviously more-important since it's used all over the place 
and is more likely to run into the arbitrary int limit. That being said, 
in practice GNU Coreutils, GNU Emacs, and other application code that I 
help maintain long ago stopped assuming the POSIX requirement that 
tv_nsec must be of type 'long', precisely because we want to be portable 
to x32. So from my point of view this ship already sailed and the POSIX 
requirement is no longer helpful; on the contrary, it is misleading 
programmers who are trying to write portable software.

If the issue is raised again at the Austin Group level, please let us 
know. I at least would like to put in my two cents.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 16:43     ` Joseph Myers
  2017-09-08 16:54       ` Paul Eggert
@ 2017-09-08 17:01       ` Zack Weinberg
  2017-09-08 17:24         ` Joseph Myers
  1 sibling, 1 reply; 76+ messages in thread
From: Zack Weinberg @ 2017-09-08 17:01 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Albert ARIBAUD (3ADEV), GNU C Library

On Fri, Sep 8, 2017 at 12:43 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Fri, 8 Sep 2017, Zack Weinberg wrote:
>> * I understand that you are trying to make the transition as seamless
>> as possible with _TIME_BITS and so on, but I would seriously question
>> whether it is appropriate to preserve super-legacy APIs such as
>> 'stime' and 'utime' in the extended mode.  (I'd put the cutoff at
>> 'gettimeofday', which is still heavily used even though
>> 'clock_gettime' officially supersedes it.)
>
> I don't think utime is super-legacy; it's in the 2008 edition of POSIX.

Hmm, OK.

> Now, stime is not part of any supported standard (it was withdrawn in
> XPG3) - such old BSD/SVID interfaces that are now in __USE_MISC but no
> other standard are definitely worth considering for obsoletion (removing
> declarations / documentation, making into compat symbols not available for
> new ports / static linking) if there are clear replacements for any
> current uses / not much current use.

That's a good point.  What I should have said is "before we do this,
we should inspect all affected interfaces and see whether any of them
are obsolete to the point where we should demote them to compat
symbols, at which point they don't need time64 versions".

stime is the only one I _know_ falls into that category: withdrawn in
XPG3 + completely superseded by newer APIs + niche usage (there are
very few programs that need to _set_ the system time, after all)
(unfortunately, a lot of the hits on codesearch.debian.net are
unrelated use of the same name, to the point where I can't actually
tell how many real uses there are, but I would bet any program that
still uses it does so only as a fallback-for-legacy-OSes from
clock_settime and friends).

>> * The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
>> is, as discussed at great length earlier, incorrect and should be
>> ignored.  It should instead be a new typedef 'nsec_t' available in
>
> And as discussed, I disagree and don't think we should invent any such
> typedef or deviate from this requirement, given that long is fully able to
> represent all valid nanoseconds values

Neither you, nor Rich, nor anyone else on the cited Austin Group
discussion has addressed the actual issue, which is that this is a
datum embedded in structures passed across the kernel/user boundary by
reference, it is impossible to enumerate all such structures,
therefore its type _must_ be a typedef so that it can be made to match
the kernel's expectations, whatever those might be.

(And I don't particularly see why people seem to think this is an
x32-specific issue.  It potentially affects *any* 32-bit ABI on a
64-bit kernel.)

>> <sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
>> field (all _t names are reserved for future extension, so the typedef
>> doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
>
> They are not reserved in ISO C, only in POSIX.

<sys/types.h> doesn't exist in ISO C as far as I know, so how could it
be?  But any program that uses it opts into POSIX's specification for
that header, even if compiled with -std=c89 and no _foo_SOURCE
definitions.

zw

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-07 23:21 ` [RFC PATCH 00/52] Make GLIBC Y2038-proof Joseph Myers
  2017-09-08 16:19   ` Zack Weinberg
@ 2017-09-08 17:08   ` Albert ARIBAUD
  2017-09-08 17:26     ` Joseph Myers
  1 sibling, 1 reply; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-08 17:08 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha

Hi Joseph,

On Thu, 7 Sep 2017 23:21:16 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> General observations on this patch series:
> 
> * Nothing should use a GLIBC_Y2038 version.  Use GLIBC_2.27 and update as 
> necessary during rebases if this doesn't get into 2.27.

Understood, will do.

> * Nothing should go in architecture-specific files such as 
> sysdeps/unix/sysv/linux/arm/Versions.  For OS-independent interfaces
> use files such as time/Versions - wherever the existing versions of
> those interfaces for existing time_t are.

Will do.

> * How such a patch series was tested needs to be described in the summary 
> of the series.  For a series like this, full testsuite runs on multiple 
> 32-bit and 64-bit architectures as well as use of build-many-glibcs.py to 
> do the compilation tests for (almost) all configurations is important (or 
> if a series is a preliminary version with limited architecture support, 
> that should be stated explicitly, but the full testsuite should still pass 
> on at least one 32-bit and one 64-bit architecture).

Will do. Right now, the patches are tested using an ad hoc system (as
stated in the cover letter). I'll run the GLIBC test suite and add
results to the cover letter in the next patcxh series iteration.

> * I'd expect lots of extra tests using _TIME_BITS=64 to be added in such a 
> patch series, to make sure that every new ABI is covered by the testsuite.

Indeed.

> * Documentation of _TIME_BITS is clearly needed.

Where should this documentation go?

> * You need to make sure that new ABIs are not added / used on platforms 
> where time_t is already 64-bit.

Will do.


> * All new files need a descriptive first line before the copyright notice.

Understood.

> * All copyright ranges in new files should end with 2017.

Will fix.

> * No "Contributed by" in new files.

Will fix.

Thanks for your feedback!

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 17:01       ` Zack Weinberg
@ 2017-09-08 17:24         ` Joseph Myers
  2017-09-08 18:32           ` Zack Weinberg
  0 siblings, 1 reply; 76+ messages in thread
From: Joseph Myers @ 2017-09-08 17:24 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Albert ARIBAUD (3ADEV), GNU C Library

On Fri, 8 Sep 2017, Zack Weinberg wrote:

> > And as discussed, I disagree and don't think we should invent any such
> > typedef or deviate from this requirement, given that long is fully able to
> > represent all valid nanoseconds values
> 
> Neither you, nor Rich, nor anyone else on the cited Austin Group
> discussion has addressed the actual issue, which is that this is a
> datum embedded in structures passed across the kernel/user boundary by
> reference, it is impossible to enumerate all such structures,
> therefore its type _must_ be a typedef so that it can be made to match
> the kernel's expectations, whatever those might be.

I don't see this as in any way an issue for having a definition of struct 
timespec that conforms to ISO C and POSIX requirements.  Code passing data 
to the kernel knows the structures being used locally and needs to convert 
it to the kernel's layout, which might be e.g. struct __kernel_timespec64.  
I don't see that as different in essence from e.g. converting a local-time 
broken down date/hours/minutes/seconds/nanoseconds value before passing it 
to the kernel, if that's the form the particular application stores time 
in.  It just so happens that, as an optimization, we can arrange the 
layout so that we both are POSIX-compatible and do not require any layout 
conversions between timestamps coming *from* the kernel and struct 
timespec.

> (And I don't particularly see why people seem to think this is an
> x32-specific issue.  It potentially affects *any* 32-bit ABI on a
> 64-bit kernel.)

The kernel does the conversion just fine for a pure 32-bit struct timespec 
- as it does for the entire compat interface - and could do them perfectly 
well for a structure with 64-bit seconds and 32-bit (+ padding) 
nanoseconds.  It just so happens not to for the very specific case of x32.

> >> <sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
> >> field (all _t names are reserved for future extension, so the typedef
> >> doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
> >
> > They are not reserved in ISO C, only in POSIX.
> 
> <sys/types.h> doesn't exist in ISO C as far as I know, so how could it
> be?  But any program that uses it opts into POSIX's specification for

My point is that you can't expose nsec_t, even as a typedef for long, in 
<time.h> for C11.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 17:08   ` Albert ARIBAUD
@ 2017-09-08 17:26     ` Joseph Myers
  2017-09-08 19:19       ` Albert ARIBAUD
  0 siblings, 1 reply; 76+ messages in thread
From: Joseph Myers @ 2017-09-08 17:26 UTC (permalink / raw)
  To: Albert ARIBAUD; +Cc: libc-alpha

On Fri, 8 Sep 2017, Albert ARIBAUD wrote:

> > * Documentation of _TIME_BITS is clearly needed.
> 
> Where should this documentation go?

In manual/creature.texi, alongside the documentation of _FILE_OFFSET_BITS.

(It occurred to me that patches 50-52 don't seem to have reached the 
mailing list, so I don't know what was in them.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 16:19   ` Zack Weinberg
  2017-09-08 16:43     ` Joseph Myers
@ 2017-09-08 17:42     ` Albert ARIBAUD
  2017-09-08 17:59       ` Joseph Myers
  1 sibling, 1 reply; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-08 17:42 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Joseph Myers, GNU C Library

Hi Zack,

On Fri, 8 Sep 2017 12:19:08 -0400, Zack Weinberg <zackw@panix.com>
wrote :

> On Thu, Sep 7, 2017 at 7:21 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> > General observations on this patch series:  
> 
> I concur with all of Joseph's observations and would add:
> 
> > * You need to make sure that new ABIs are not added / used on platforms
> > where time_t is already 64-bit.  
> 
> Elaborating on this, when time_t is already 64 bits, defining
> _TIME_BITS=64 should have no effect on the generated code, and
> defining _TIME_BITS=32 should cause a compile-time error.

Will add.

> * We are not going to land these patches until the kernel side is
> finalized.  All of the places where you have "// TODO: implement after
> the kernel does" must be replaced with an actual implementation.
> Likewise, we need a complete implementation for all supported
> architectures before landing.  You're not on the hook to implement
> this feature for the Hurd, but you should coordinate with Samuel
> Thibault so that at least you do not make glibc-for-Hurd more broken
> than it already is.

Regarding whether the patches should land only once the kernel is
Y0238-safe: these patches are intended to run even on a current and thus
completely Y2038-unsafe kernel, in which case they use 64-bit-time on
user side (to make applications compiled with _TIME_BITS==64 happy at
least until Y2038 happens) and 32-bit time on kernel side. So I don't
see why these patches should wait for a Y2038-safe kernel per se.

Re the TODOs: note that right now, all these TODOs are coded in such a
way that the implementation "falls through" to using 32-bit syscalls or
code, just like it would if running on an older kernel.

> (But I would encourage you to create a named branch in glibc git for
> this project if you haven't already, to make it easier for others to
> experiment with it.)

There is such a branch, mentioned in the implementation part of the
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign document.

> * I understand that you are trying to make the transition as seamless
> as possible with _TIME_BITS and so on, but I would seriously question
> whether it is appropriate to preserve super-legacy APIs such as
> 'stime' and 'utime' in the extended mode.  (I'd put the cutoff at
> 'gettimeofday', which is still heavily used even though
> 'clock_gettime' officially supersedes it.)

I'm all for not adding 64-bit-time versions of APIs which are obsolete.
The patch series is organized to facilitate removing or adding types and
functions.

As to which APIs should be made obsolete, there appears to be room for
debate.

I will add a section in the design document listing obsolete(d) APIs
(there are a few which are tagged as such, but not in a section of
their own yet) and as consensus emerges, I will update the patch series
and document.

> * The POSIX (and ISO C now, argh) requirement for tv_nsec to be 'long'
> is, as discussed at great length earlier, incorrect and should be
> ignored.  It should instead be a new typedef 'nsec_t' available in
> <sys/types.h>, matching the kernel's choice of 32 or 64 bits for this
> field (all _t names are reserved for future extension, so the typedef
> doesn't need to be _GNU_SOURCE-only). This "willful violation" (as the
> HTML5 folks put it) must, of course, be documented.

(seems to be a topic for debate)

> * We do not use Signed-off-by: and we actively want you to _not_
> include it in your patch submissions.  (We have the FSF-mandated
> actual copyright assignments instead.)

Will fix.

> * The patch series is split too finely.  I recommend breaking it up by
> type instead of by function -- time64_t + all the functions that use
> only time64_t; struct timeval64 + all the functions that use only
> time64_t and/or struct timeval64; and so on.

As indicated above, I broke it up by type and function (except when
dependencies made it really impractical) to easy adding or removing (and
reviewing) individual functions. 50-odd patches are manageable IMO, but
maybe some people may be put off by it... What I'll do is keep two
branches: this fine-grained one, and a coarser-grained one where all
changes related to one type are grouped. Best of both worlds.

> zw

Thanks for your review!

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 50/52] Y2038: add function select
  2017-09-07 22:46                                                                                                 ` [RFC PATCH 49/52] Y2038: add function pselect Albert ARIBAUD (3ADEV)
@ 2017-09-08 17:49                                                                                                   ` Albert ARIBAUD (3ADEV)
  2017-09-08 17:49                                                                                                     ` [RFC PATCH 51/52] Y2038: add RPC functions Albert ARIBAUD (3ADEV)
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-08 17:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/sys/select.h             |  5 +++
 sysdeps/unix/sysv/linux/select.c | 66 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/include/sys/select.h b/include/sys/select.h
index 3eb76faf9d..df10085e72 100644
--- a/include/sys/select.h
+++ b/include/sys/select.h
@@ -24,5 +24,10 @@ extern int __pselect_t64 (int __nfds, fd_set *__readfds,
 		         const struct __timespec64 *__timeout,
 		         const __sigset_t *__sigmask);
 
+extern int __select_t64 (int __nfds, fd_set *__restrict __readfds,
+		         fd_set *__restrict __writefds,
+		         fd_set *__restrict __exceptfds,
+		         struct __timeval64 *__restrict __timeout);
+
 #endif
 #endif
diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c
index be4a456a51..3e6140621c 100644
--- a/sysdeps/unix/sysv/linux/select.c
+++ b/sysdeps/unix/sysv/linux/select.c
@@ -33,6 +33,8 @@
 # define __NR_select __NR__newselect
 #endif
 
+extern int __y2038_linux_support;
+
 int
 __select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 	  struct timeval *timeout)
@@ -69,3 +71,67 @@ libc_hidden_def (__select)
 
 weak_alias (__select, select)
 weak_alias (__select, __libc_select)
+
+/* 64-bit time version */
+
+extern int __y2038_linux_support;
+
+int
+__select_t64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+	      struct __timeval64 *timeout)
+{
+  struct timeval tval32, *timeout32 = NULL;
+#ifndef __NR_select
+  int result;
+  struct timespec ts32, *tsp32 = NULL;
+#endif
+
+  if (__y2038_linux_support)
+  {
+    /* TODO: implement using Linux kernel system call */
+  }
+
+  if (timeout != NULL)
+    {
+      if (timeout->tv_sec > INT_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      tval32.tv_sec = timeout->tv_sec;
+      tval32.tv_usec = timeout->tv_usec;
+      timeout32 = &tval32;
+    }
+
+#ifdef __NR_select
+  return SYSCALL_CANCEL (select, nfds, readfds, writefds, exceptfds,
+			 timeout32);
+#else
+  if (timeout)
+    {
+      if (timeout->tv_sec > INT_MAX)
+      {
+        errno = EOVERFLOW;
+        return -1;
+      }
+      ts32.tv_sec = timeout->tv_sec;
+      ts32.tv_nsec = timeout->tv_usec * 1000;
+      tsp32 = &ts32;
+    }
+
+  result = SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds, tsp32,
+			   NULL);
+
+  if (timeout)
+    {
+      /* Linux by default will update the timeout after a pselect6 syscall
+         (though the pselect() glibc call suppresses this behavior).
+         Since select() on Linux has the same behavior as the pselect6
+         syscall, we update the timeout here.  */
+      timeout->tv_sec = ts32.tv_sec;
+      timeout->tv_usec = ts32.tv_nsec / 1000;
+    }
+
+  return result;
+#endif
+}
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-08 17:49                                                                                                   ` [RFC PATCH 50/52] Y2038: add function select Albert ARIBAUD (3ADEV)
@ 2017-09-08 17:49                                                                                                     ` Albert ARIBAUD (3ADEV)
  2017-09-08 17:49                                                                                                       ` [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support Albert ARIBAUD (3ADEV)
                                                                                                                         ` (2 more replies)
  0 siblings, 3 replies; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-08 17:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

Three functions in RPC have a struct timeval in their arguments:
pmap_rmtcall, clntudp_create, and clntudp_bufcreate.

Since these struct timeval arguments contain relative timeouts, and
since RPC timeouts can reasonably be expected to be small enough to
still fit in 32-bit representations, the implementations of these
functions just verify that the 64-bit timeout they received can fit
in 32 bits, convert it to 32 bit, and pass it to their 32-bit-time
counterparts.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 sunrpc/clnt_udp.c      | 27 +++++++++++++++++++++++++++
 sunrpc/pmap_rmt.c      | 23 +++++++++++++++++++++++
 sunrpc/rpc/clnt.h      | 24 ++++++++++++++++++++++++
 sunrpc/rpc/pmap_clnt.h | 15 +++++++++++++++
 4 files changed, 89 insertions(+)

diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index df21e28f64..b02b80e2c4 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -644,3 +644,30 @@ clntudp_destroy (CLIENT *cl)
   mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
   mem_free ((caddr_t) cl, sizeof (CLIENT));
 }
+
+/* 64-bit time versions */
+
+CLIENT *
+__clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
+		    struct __timeval64 wait, int *sockp)
+{
+  struct timeval wait32;
+  if (wait.tv_sec > INT_MAX)
+  {
+    return NULL;
+  }  
+  return clntudp_create (raddr, program, version, wait32, sockp);
+}
+
+CLIENT *
+__clntudp_bufcreate64 (struct sockaddr_in *raddr, u_long program, u_long version,
+		       struct __timeval64 wait, int *sockp, u_int sendsz,
+		       u_int recvsz)
+{
+  struct timeval wait32;
+  if (wait.tv_sec > INT_MAX)
+  {
+    return NULL;
+  }  
+  return clntudp_bufcreate (raddr, program, version, wait32, sockp, sendsz, recvsz);
+}
diff --git a/sunrpc/pmap_rmt.c b/sunrpc/pmap_rmt.c
index 6d4ed7206c..6dd360edcd 100644
--- a/sunrpc/pmap_rmt.c
+++ b/sunrpc/pmap_rmt.c
@@ -391,3 +391,26 @@ done_broad:
   return stat;
 }
 libc_hidden_nolink_sunrpc (clnt_broadcast, GLIBC_2_0)
+
+/* 64-bit-time version */
+
+/* The 64-bit-time version of pmap_rmtcall.
+ * Only handles 64-bit-time timeouts smaller than 2^^31 seconds.
+ */
+enum clnt_stat
+__pmap_rmtcall_t64 (struct sockaddr_in *addr, u_long prog, u_long vers,
+		    u_long proc, xdrproc_t xdrargs, caddr_t argsp,
+		    xdrproc_t xdrres, caddr_t resp,
+		    struct __timeval64 tout, u_long *port_ptr)
+{
+  struct timeval tout32;
+  if (tout.tv_sec > INT_MAX)
+  {
+    return RPC_SYSTEMERROR;
+  }
+  tout32.tv_sec = tout.tv_sec;
+  tout32.tv_usec = tout.tv_usec;
+  
+  return pmap_rmtcall (addr, prog, vers, proc, xdrargs, argsp, xdrres,
+                       resp, tout32, port_ptr);
+}
diff --git a/sunrpc/rpc/clnt.h b/sunrpc/rpc/clnt.h
index f4d4a941c7..e559242eeb 100644
--- a/sunrpc/rpc/clnt.h
+++ b/sunrpc/rpc/clnt.h
@@ -329,9 +329,33 @@ extern CLIENT *clnttcp_create (struct sockaddr_in *__raddr, u_long __prog,
  *	u_int sendsz;
  *	u_int recvsz;
  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern CLIENT * __REDIRECT (clntudp_create,(struct sockaddr_in *__raddr,
+                                            u_long __program,
+					    u_long __version,
+					    struct timeval __wait_resend,
+					    int *__sockp),
+                            __clntudp_create_t64) __THROW;
+# else
+# define clntudp_create __clntudp_create_t64
+# endif
+#endif
 extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program,
 			       u_long __version, struct timeval __wait_resend,
 			       int *__sockp) __THROW;
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern CLIENT * __REDIRECT (clntudp_bufcreate,(struct sockaddr_in *__raddr,
+				               u_long __program, u_long __version,
+				               struct __timeval64 __wait_resend,
+					       int *__sockp, u_int __sendsz,
+					       u_int __recvsz),
+                            __clntudp_bufcreate_t64) __THROW;
+# else
+# define clntudp_bufcreate __clntudp_bufcreate_t64
+# endif
+#endif
 extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr,
 				  u_long __program, u_long __version,
 				  struct timeval __wait_resend, int *__sockp,
diff --git a/sunrpc/rpc/pmap_clnt.h b/sunrpc/rpc/pmap_clnt.h
index 1cc94b8fee..70ec89b723 100644
--- a/sunrpc/rpc/pmap_clnt.h
+++ b/sunrpc/rpc/pmap_clnt.h
@@ -71,6 +71,21 @@ extern bool_t pmap_set (const u_long __program, const u_long __vers,
 extern bool_t pmap_unset (const u_long __program, const u_long __vers)
      __THROW;
 extern struct pmaplist *pmap_getmaps (struct sockaddr_in *__address) __THROW;
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern enum clnt_stat __REDIRECT (pmap_rmtcall, (struct sockaddr_in *__addr,
+                                                 const u_long __prog,
+                                                 const u_long __vers,
+                                                 const u_long __proc,
+                                                 xdrproc_t __xdrargs,
+                                                 caddr_t __argsp, xdrproc_t __xdrres,
+                                                 caddr_t __resp, struct timeval __tout,
+                                                 u_long *__port_ptr),
+                                  __pmap_rmtcall_t64) __THROW;
+# else
+# define pmap_rmtcall __pmap_rmtcall_t64
+# endif
+#endif
 extern enum clnt_stat pmap_rmtcall (struct sockaddr_in *__addr,
 				    const u_long __prog,
 				    const u_long __vers,
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support
  2017-09-08 17:49                                                                                                     ` [RFC PATCH 51/52] Y2038: add RPC functions Albert ARIBAUD (3ADEV)
@ 2017-09-08 17:49                                                                                                       ` Albert ARIBAUD (3ADEV)
  2017-09-08 19:47                                                                                                         ` Joseph Myers
  2017-09-08 19:47                                                                                                       ` [RFC PATCH 51/52] Y2038: add RPC functions Joseph Myers
  2017-09-08 19:59                                                                                                       ` Paul Eggert
  2 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD (3ADEV) @ 2017-09-08 17:49 UTC (permalink / raw)
  To: libc-alpha; +Cc: Albert ARIBAUD (3ADEV)

This makes all previously defined Y2038-proof API types, functions and
implementations the default when _TIME_BITS==64.

Note: it is assumed that the API is consistent, i.e. for each API type
which is enabled here, all API functions which depend on this type are
enabled and mapped to Y2038-proof implementations.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/features.h                    |   4 +
 io/sys/stat.h                         |  75 ++++++++++++++--
 io/utime.h                            |  15 +++-
 misc/sys/select.h                     |  25 ++++++
 posix/sched.h                         |   9 ++
 resource/sys/resource.h               |   9 ++
 rt/mqueue.h                           |  22 +++++
 signal/signal.h                       |  10 +++
 sysdeps/nptl/pthread.h                |  41 +++++++++
 sysdeps/pthread/semaphore.h           |  10 +++
 sysdeps/unix/sysv/linux/bits/stat.h   |   6 +-
 sysdeps/unix/sysv/linux/sys/timerfd.h |  19 ++++
 sysdeps/unix/sysv/linux/sys/timex.h   |  32 ++++++-
 sysvipc/sys/msg.h                     |   9 ++
 time/bits/types/struct_timespec.h     |  17 ++++
 time/bits/types/struct_timeval.h      |   9 ++
 time/bits/types/time_t.h              |   4 +
 time/sys/time.h                       |  74 ++++++++++++++++
 time/time.h                           | 161 +++++++++++++++++++++++++++++++++-
 19 files changed, 536 insertions(+), 15 deletions(-)

diff --git a/include/features.h b/include/features.h
index c063b33b49..bee0bbbd5e 100644
--- a/include/features.h
+++ b/include/features.h
@@ -359,6 +359,10 @@
 # define __USE_FILE_OFFSET64	1
 #endif
 
+#if defined _TIME_BITS && _TIME_BITS == 64
+# define __USE_TIME_BITS64	1
+#endif
+
 #if defined _DEFAULT_SOURCE
 # define __USE_MISC	1
 #endif
diff --git a/io/sys/stat.h b/io/sys/stat.h
index ac7ef1f572..8e6f9b62c1 100644
--- a/io/sys/stat.h
+++ b/io/sys/stat.h
@@ -210,14 +210,27 @@ extern int stat (const char *__restrict __file,
 extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2));
 #else
 # ifdef __REDIRECT_NTH
+#  ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
+				  struct stat *__restrict __buf), __stat64_t64)
+     __nonnull ((1, 2));
+extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), __fstat64_t64)
+     __nonnull ((2));
+#  else
 extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
 				  struct stat *__restrict __buf), stat64)
      __nonnull ((1, 2));
 extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), fstat64)
      __nonnull ((2));
+#  endif
 # else
-#  define stat stat64
-#  define fstat fstat64
+#  ifdef __USE_TIME_BITS64
+#   define stat stat64_t64
+#   define fstat fstat64_t64
+#  else
+#   define stat stat64
+#   define fstat fstat64
+#  endif
 # endif
 #endif
 #ifdef __USE_LARGEFILE64
@@ -260,12 +273,23 @@ extern int lstat (const char *__restrict __file,
 		  struct stat *__restrict __buf) __THROW __nonnull ((1, 2));
 # else
 #  ifdef __REDIRECT_NTH
+#   ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (lstat,
+			   (const char *__restrict __file,
+			    struct stat *__restrict __buf), __lstat64_t64)
+     __nonnull ((1, 2));
+#   else
 extern int __REDIRECT_NTH (lstat,
 			   (const char *__restrict __file,
 			    struct stat *__restrict __buf), lstat64)
      __nonnull ((1, 2));
+#   endif
 #  else
-#   define lstat lstat64
+#   ifdef __USE_TIME_BITS64
+#    define lstat __lstat64_t64
+#   else
+#    define lstat lstat64
+#   endif
 #  endif
 # endif
 # ifdef __USE_LARGEFILE64
@@ -357,6 +381,15 @@ extern int mkfifoat (int __fd, const char *__path, __mode_t __mode)
 #ifdef __USE_ATFILE
 /* Set file access and modification times relative to directory file
    descriptor.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utimensat, (int __fd, const char *__path,
+           const struct timespec __times[2], int __flags),
+           __utimensat64) __THROW __nonnull((2));
+# else
+# define utimensat __utimensat64
+# endif
+#endif
 extern int utimensat (int __fd, const char *__path,
 		      const struct timespec __times[2],
 		      int __flags)
@@ -365,6 +398,14 @@ extern int utimensat (int __fd, const char *__path,
 
 #ifdef __USE_XOPEN2K8
 /* Set file access and modification times of the file associated with FD.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (futimens, (int __fd, const struct timespec __times[2]),
+           __futimens64) __THROW;
+# else
+# define futimens __futimens64
+# endif
+#endif
 extern int futimens (int __fd, const struct timespec __times[2]) __THROW;
 #endif
 \f
@@ -403,6 +444,21 @@ extern int __fxstatat (int __ver, int __fildes, const char *__filename,
      __THROW __nonnull ((3, 4));
 #else
 # ifdef __REDIRECT_NTH
+#  ifdef __USE_TIME_BITS64
+extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
+				      struct stat *__stat_buf), __fxstat64_t64)
+     __nonnull ((3));
+extern int __REDIRECT_NTH (__xstat, (int __ver, const char *__filename,
+				     struct stat *__stat_buf), __xstat64_t64)
+     __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__lxstat, (int __ver, const char *__filename,
+				      struct stat *__stat_buf), __lxstat64_t64)
+     __nonnull ((2, 3));
+extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
+					const char *__filename,
+					struct stat *__stat_buf, int __flag),
+			   __fxstatat64_t64) __nonnull ((3, 4));
+#  else
 extern int __REDIRECT_NTH (__fxstat, (int __ver, int __fildes,
 				      struct stat *__stat_buf), __fxstat64)
      __nonnull ((3));
@@ -416,11 +472,18 @@ extern int __REDIRECT_NTH (__fxstatat, (int __ver, int __fildes,
 					const char *__filename,
 					struct stat *__stat_buf, int __flag),
 			   __fxstatat64) __nonnull ((3, 4));
+#  endif
 
 # else
-#  define __fxstat __fxstat64
-#  define __xstat __xstat64
-#  define __lxstat __lxstat64
+#  ifdef __USE_TIME_BITS64
+#   define __fxstat __fxstat64_t64
+#   define __xstat __xstat64_t64
+#   define __lxstat __lxstat64_t64
+#  else
+#   define __fxstat __fxstat64
+#   define __xstat __xstat64
+#   define __lxstat __lxstat64
+#  endif
 # endif
 #endif
 
diff --git a/io/utime.h b/io/utime.h
index 44a4e9cddd..3222b12e91 100644
--- a/io/utime.h
+++ b/io/utime.h
@@ -32,15 +32,24 @@ __BEGIN_DECLS
 # include <bits/types/time_t.h>
 #endif
 
-/* Structure describing file times.  */
+/* Structure describing file times, 32- or 64-bit time.  */
 struct utimbuf
   {
-    __time_t actime;		/* Access time.  */
-    __time_t modtime;		/* Modification time.  */
+    time_t actime;		/* Access time.  */
+    time_t modtime;		/* Modification time.  */
   };
 
 /* Set the access and modification times of FILE to those given in
    *FILE_TIMES.  If FILE_TIMES is NULL, set them to the current time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utime, (const char *__file,
+     const struct utimbuf *__file_times),
+     __utime_t64) __THROW __nonnull ((1));
+# else
+# define utime __utime_t64
+# endif
+#endif
 extern int utime (const char *__file,
 		  const struct utimbuf *__file_times)
      __THROW __nonnull ((1));
diff --git a/misc/sys/select.h b/misc/sys/select.h
index 06dd31b476..aa0348a116 100644
--- a/misc/sys/select.h
+++ b/misc/sys/select.h
@@ -98,6 +98,18 @@ __BEGIN_DECLS
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (select, (int __nfds,
+                                fd_set *__restrict __readfds,
+                                fd_set *__restrict __writefds,
+                                fd_set *__restrict __exceptfds,
+                                struct timeval *__restrict __timeout),
+                       __select_t64);
+# else
+# define select __select_t64
+# endif
+#endif
 extern int select (int __nfds, fd_set *__restrict __readfds,
 		   fd_set *__restrict __writefds,
 		   fd_set *__restrict __exceptfds,
@@ -110,6 +122,19 @@ extern int select (int __nfds, fd_set *__restrict __readfds,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (pselect, (int __nfds,
+                                 fd_set *__restrict __readfds,
+                                 fd_set *__restrict __writefds,
+                                 fd_set *__restrict __exceptfds,
+                                 const struct timespec *__restrict __timeout,
+                                 const __sigset_t *__restrict __sigmask),
+                       __pselect_t64);
+# else
+# define pselect __pselect_t64
+# endif
+#endif
 extern int pselect (int __nfds, fd_set *__restrict __readfds,
 		    fd_set *__restrict __writefds,
 		    fd_set *__restrict __exceptfds,
diff --git a/posix/sched.h b/posix/sched.h
index d5cdac37b0..5a15094f44 100644
--- a/posix/sched.h
+++ b/posix/sched.h
@@ -74,6 +74,15 @@ extern int sched_get_priority_max (int __algorithm) __THROW;
 extern int sched_get_priority_min (int __algorithm) __THROW;
 
 /* Get the SCHED_RR interval for the named process.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (sched_rr_get_interval,
+                       (__pid_t __pid, struct timespec *__t),
+                       __sched_rr_get_interval_t64) __THROW;
+# else
+# define sched_rr_get_interval __sched_rr_get_interval_t64
+# endif
+#endif
 extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW;
 
 
diff --git a/resource/sys/resource.h b/resource/sys/resource.h
index 423ac62a34..642fe791c5 100644
--- a/resource/sys/resource.h
+++ b/resource/sys/resource.h
@@ -84,6 +84,15 @@ extern int setrlimit64 (__rlimit_resource_t __resource,
 
 /* Return resource usage information on process indicated by WHO
    and put it in *USAGE.  Returns 0 for success, -1 for failure.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern double __REDIRECT (getrusage, (__rusage_who_t __who, 
+                                      struct rusage *__usage),
+     __getrusage_t64) __THROW;
+# else
+# define getrusage __getrusage_t64
+# endif
+#endif
 extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __THROW;
 
 /* Return the highest priority of any process specified by WHICH and WHO
diff --git a/rt/mqueue.h b/rt/mqueue.h
index c79aa53b94..f7e251ab79 100644
--- a/rt/mqueue.h
+++ b/rt/mqueue.h
@@ -73,6 +73,17 @@ extern int mq_send (mqd_t __mqdes, const char *__msg_ptr, size_t __msg_len,
 #ifdef __USE_XOPEN2K
 /* Receive the oldest from highest priority messages in message queue
    MQDES, stop waiting if ABS_TIMEOUT expires.  */
+# ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern ssize_t __REDIRECT (mq_timedreceive, (mqd_t __mqdes,
+                           char *__restrict __msg_ptr, size_t __msg_len,
+                           unsigned int *__restrict __msg_prio,
+                           const struct timespec *__restrict __abs_timeout),
+     __mq_timedreceive_t64) __nonnull((2, 5));
+#  else
+#   define mq_timedreceive __mq_timedreceive_t64
+#  endif
+# endif
 extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr,
 				size_t __msg_len,
 				unsigned int *__restrict __msg_prio,
@@ -81,6 +92,17 @@ extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr,
 
 /* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
    on full message queue if ABS_TIMEOUT expires.  */
+# ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern int __REDIRECT (mq_timedsend, (mqd_t __mqdes,
+                       const char *__msg_ptr, size_t __msg_len,
+                       unsigned int __msg_prio,
+                       const struct timespec *__abs_timeout),
+     __mq_timedsend_t64) __nonnull((2, 5));
+#  else
+#   define mq_timedsend __mq_timedsend_t64
+#  endif
+# endif
 extern int mq_timedsend (mqd_t __mqdes, const char *__msg_ptr,
 			 size_t __msg_len, unsigned int __msg_prio,
 			 const struct timespec *__abs_timeout)
diff --git a/signal/signal.h b/signal/signal.h
index c8f6100ac4..5e76ea6161 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -262,6 +262,16 @@ extern int sigwaitinfo (const sigset_t *__restrict __set,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (sigtimedwait, (const sigset_t *__restrict __set,
+			 siginfo_t *__restrict __info,
+			 const struct timespec *__restrict __timeout),
+     __sigtimedwait64) __nonnull ((1));
+# else
+# define sigtimedwait __sigtimedwait64
+# endif
+#endif
 extern int sigtimedwait (const sigset_t *__restrict __set,
 			 siginfo_t *__restrict __info,
 			 const struct timespec *__restrict __timeout)
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index 632ea7bc36..4289d990b5 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -765,6 +765,16 @@ extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
 
 #ifdef __USE_XOPEN2K
 /* Wait until lock becomes available, or specified time passes. */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (pthread_mutex_timedlock,
+                               (pthread_mutex_t *__restrict __mutex,
+                                const struct timespec *__restrict __abstime),
+       __pthread_mutex_timedlock_t64) __THROWNL __nonnull ((1, 2));
+# else
+# define pthread_mutex_timedlock __pthread_mutex_timedlock_t64
+# endif
+#endif
 extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
 				    const struct timespec *__restrict
 				    __abstime) __THROWNL __nonnull ((1, 2));
@@ -904,6 +914,16 @@ extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
 
 # ifdef __USE_XOPEN2K
 /* Try to acquire read lock for RWLOCK or return after specfied time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (pthread_rwlock_timedrdlock,
+                               (pthread_rwlock_t *__restrict __rwlock,
+                                struct timespec *__restrict __abstime),
+       __pthread_rwlock_timedrdlock_t64) __THROWNL __nonnull ((1, 2));
+# else
+# define pthread_rwlock_timedrdlock __pthread_rwlock_timedrdlock_t64
+# endif
+#endif
 extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
 				       const struct timespec *__restrict
 				       __abstime) __THROWNL __nonnull ((1, 2));
@@ -919,6 +939,16 @@ extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
 
 # ifdef __USE_XOPEN2K
 /* Try to acquire write lock for RWLOCK or return after specfied time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (pthread_rwlock_timedwrlock,
+                               (pthread_rwlock_t *__restrict __rwlock,
+                                struct timespec *__restrict __abstime),
+       __pthread_rwlock_timedwrlock_t64) __THROWNL __nonnull ((1, 2));
+# else
+# define pthread_rwlock_timedwrlock __pthread_rwlock_timedwrlock_t64
+# endif
+#endif
 extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
 				       const struct timespec *__restrict
 				       __abstime) __THROWNL __nonnull ((1, 2));
@@ -998,6 +1028,17 @@ extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (pthread_cond_timedwait,
+                               (pthread_cond_t *__restrict __cond,
+                                pthread_mutex_t *__restrict __mutex,
+                                const struct timespec *__restrict __abstime),
+       __pthread_cond_timedwait_t64) __nonnull ((1, 2, 3));
+# else
+# define pthread_cond_timedwait __pthread_cond_timedwait_t64
+# endif
+#endif
 extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
 				   pthread_mutex_t *__restrict __mutex,
 				   const struct timespec *__restrict __abstime)
diff --git a/sysdeps/pthread/semaphore.h b/sysdeps/pthread/semaphore.h
index 0b095a8891..f1dd8d265e 100644
--- a/sysdeps/pthread/semaphore.h
+++ b/sysdeps/pthread/semaphore.h
@@ -57,6 +57,16 @@ extern int sem_wait (sem_t *__sem);
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (sem_timedwait,
+                               (sem_t *__restrict __sem,
+                                const struct timespec *__restrict __abstime),
+       __sem_timedwait_t64);
+# else
+# define sem_timedwait __sem_timedwait_t64
+# endif
+#endif
 extern int sem_timedwait (sem_t *__restrict __sem,
 			  const struct timespec *__restrict __abstime);
 #endif
diff --git a/sysdeps/unix/sysv/linux/bits/stat.h b/sysdeps/unix/sysv/linux/bits/stat.h
index 187590e51e..28522c4479 100644
--- a/sysdeps/unix/sysv/linux/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/bits/stat.h
@@ -119,11 +119,11 @@ struct stat64
     struct timespec st_mtim;		/* Time of last modification.  */
     struct timespec st_ctim;		/* Time of last status change.  */
 # else
-    __time_t st_atime;			/* Time of last access.  */
+    time_t st_atime;			/* Time of last access.  */
     unsigned long int st_atimensec;	/* Nscecs of last access.  */
-    __time_t st_mtime;			/* Time of last modification.  */
+    time_t st_mtime;			/* Time of last modification.  */
     unsigned long int st_mtimensec;	/* Nsecs of last modification.  */
-    __time_t st_ctime;			/* Time of last status change.  */
+    time_t st_ctime;			/* Time of last status change.  */
     unsigned long int st_ctimensec;	/* Nsecs of last status change.  */
 # endif
     __ino64_t st_ino;			/* File serial number.		*/
diff --git a/sysdeps/unix/sysv/linux/sys/timerfd.h b/sysdeps/unix/sysv/linux/sys/timerfd.h
index 9811afe0fa..958065df1c 100644
--- a/sysdeps/unix/sysv/linux/sys/timerfd.h
+++ b/sysdeps/unix/sysv/linux/sys/timerfd.h
@@ -43,11 +43,30 @@ extern int timerfd_create (__clockid_t __clock_id, int __flags) __THROW;
 /* Set next expiration time of interval timer source UFD to UTMR.  If
    FLAGS has the TFD_TIMER_ABSTIME flag set the timeout value is
    absolute.  Optionally return the old expiration time in OTMR.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timerfd_settime, (int __ufd, int __flags,
+                       const struct itimerspec *__utmr,
+                       struct itimerspec *__otmr),__timerfd_settime64)
+                       __THROW;
+# else
+# define timerfd_settime __timerfd_settime64
+# endif
+#endif
 extern int timerfd_settime (int __ufd, int __flags,
 			    const struct itimerspec *__utmr,
 			    struct itimerspec *__otmr) __THROW;
 
 /* Return the next expiration time of UFD.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timerfd_gettime, (int __ufd,
+                       struct itimerspec *__otmr),__timerfd_gettime64)
+                       __THROW;
+# else
+# define timerfd_gettime __timerfd_gettime64
+# endif
+#endif
 extern int timerfd_gettime (int __ufd, struct itimerspec *__otmr) __THROW;
 
 __END_DECLS
diff --git a/sysdeps/unix/sysv/linux/sys/timex.h b/sysdeps/unix/sysv/linux/sys/timex.h
index 3f1b013afd..e10c9870f0 100644
--- a/sysdeps/unix/sysv/linux/sys/timex.h
+++ b/sysdeps/unix/sysv/linux/sys/timex.h
@@ -55,15 +55,43 @@ struct ntptimeval
 __BEGIN_DECLS
 
 extern int __adjtimex (struct timex *__ntx) __THROW;
+
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (adjtimex, (struct timex *__ntx),
+     __adjtimex_t64) __THROW;
+# else
+# define adjtimex __adjtimex_t64
+# endif
+#endif
 extern int adjtimex (struct timex *__ntx) __THROW;
 
-#ifdef __REDIRECT_NTH
+#ifndef __USE_TIME_BITS64
+# ifdef __REDIRECT_NTH
 extern int __REDIRECT_NTH (ntp_gettime, (struct ntptimeval *__ntv),
 			   ntp_gettimex);
-#else
+# else
 extern int ntp_gettimex (struct ntptimeval *__ntv) __THROW;
+#  define ntp_gettime ntp_gettimex
+# endif
+#else
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (ntp_gettimex, (struct ntptimeval *__ntv),
+                          __ntp_gettimex_t64) __THROW;
+# else
+# define ntp_gettimex __ntp_gettimex_t64
+# endif
 # define ntp_gettime ntp_gettimex
 #endif
+
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (ntp_adjtime, (struct timex *__tntx),
+                       __ntp_adjtime_t64) __THROW;
+# else
+# define ntp_adjtime __ntp_adjtime_t64
+# endif
+#endif
 extern int ntp_adjtime (struct timex *__tntx) __THROW;
 
 __END_DECLS
diff --git a/sysvipc/sys/msg.h b/sysvipc/sys/msg.h
index 3610050014..4a6a94705b 100644
--- a/sysvipc/sys/msg.h
+++ b/sysvipc/sys/msg.h
@@ -58,6 +58,15 @@ struct msgbuf
 __BEGIN_DECLS
 
 /* Message queue control operation.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (msgctl, (int __msqid, int __cmd,
+                       struct msqid_ds *__buf),
+                       __msgctl_t64) __THROW;
+# else
+# define msgctl __msgctl_t64
+# endif
+#endif
 extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) __THROW;
 
 /* Get messages queue.  */
diff --git a/time/bits/types/struct_timespec.h b/time/bits/types/struct_timespec.h
index 644db9fdb6..9f75a6d7e6 100644
--- a/time/bits/types/struct_timespec.h
+++ b/time/bits/types/struct_timespec.h
@@ -2,13 +2,30 @@
 #define __timespec_defined 1
 
 #include <bits/types.h>
+#include <endian.h>
 
 /* POSIX.1b structure for a time value.  This is like a `struct timeval' but
    has nanoseconds instead of microseconds.  */
+# ifndef __USE_TIME_BITS64
 struct timespec
 {
   __time_t tv_sec;		/* Seconds.  */
   __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
 };
+# elif BYTE_ORDER == BIG_ENDIAN
+struct timespec
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  int: 32;			/* Hidden padding */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+};
+# else
+struct timespec
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
+  int: 32;			/* Hidden padding */
+};
+# endif
 
 #endif
diff --git a/time/bits/types/struct_timeval.h b/time/bits/types/struct_timeval.h
index 70394ce886..85e0cb5996 100644
--- a/time/bits/types/struct_timeval.h
+++ b/time/bits/types/struct_timeval.h
@@ -5,9 +5,18 @@
 
 /* A time value that is accurate to the nearest
    microsecond but also has a range of years.  */
+#ifdef __USE_TIME_BITS64
+struct timeval
+{
+  __time64_t tv_sec;		/* Seconds.  */
+  __uint64_t tv_usec;   	/* Microseconds.  */
+};
+#else
 struct timeval
 {
   __time_t tv_sec;		/* Seconds.  */
   __suseconds_t tv_usec;	/* Microseconds.  */
 };
 #endif
+
+#endif
diff --git a/time/bits/types/time_t.h b/time/bits/types/time_t.h
index ab8287c6fe..84d67f6ac3 100644
--- a/time/bits/types/time_t.h
+++ b/time/bits/types/time_t.h
@@ -4,6 +4,10 @@
 #include <bits/types.h>
 
 /* Returned by `time'.  */
+#ifdef __USE_TIME_BITS64
+typedef __time64_t time_t;
+#else
 typedef __time_t time_t;
+#endif
 
 #endif
diff --git a/time/sys/time.h b/time/sys/time.h
index 165296ac59..614ff32a1f 100644
--- a/time/sys/time.h
+++ b/time/sys/time.h
@@ -65,12 +65,31 @@ typedef void *__restrict __timezone_ptr_t;
    Returns 0 on success, -1 on errors.
    NOTE: This form of timezone information is obsolete.
    Use the functions and variables declared in <time.h> instead.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (gettimeofday, (struct timeval *__restrict __tv,
+                                   __timezone_ptr_t __tz),
+                    __gettimeofday_t64) __THROW __nonnull((1));
+# else
+# define gettimeofday __gettimeofday_t64
+# endif
+#endif
 extern int gettimeofday (struct timeval *__restrict __tv,
 			 __timezone_ptr_t __tz) __THROW __nonnull ((1));
 
 #ifdef __USE_MISC
 /* Set the current time of day and timezone information.
    This call is restricted to the super-user.  */
+# ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern int __REDIRECT (settimeofday,
+                       (const struct timeval *__tv,
+                        const struct timezone *__tz),
+                    __settimeofday_t64) __THROW;
+#  else
+#   define settimeofday __settimeofday_t64
+#  endif
+# endif
 extern int settimeofday (const struct timeval *__tv,
 			 const struct timezone *__tz)
      __THROW;
@@ -79,6 +98,16 @@ extern int settimeofday (const struct timeval *__tv,
    If OLDDELTA is not NULL, it is filled in with the amount
    of time adjustment remaining to be done from the last `adjtime' call.
    This call is restricted to the super-user.  */
+# ifdef __USE_TIME_BITS64
+#  if defined(__REDIRECT)
+extern int __REDIRECT (adjtime,
+                       (const struct timeval *__delta,
+                        struct timeval *__olddelta),
+                    __adjtime_t64) __THROW;
+#  else
+#   define adjtime __adjtime_t64
+#  endif
+# endif
 extern int adjtime (const struct timeval *__delta,
 		    struct timeval *__olddelta) __THROW;
 #endif
@@ -119,12 +148,31 @@ typedef int __itimer_which_t;
 
 /* Set *VALUE to the current setting of timer WHICH.
    Return 0 on success, -1 on errors.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (getitimer, (__itimer_which_t __which,
+       struct itimerval *__value), __getitimer_t64)
+       __THROW;
+# else
+# define getitimer __getitimer_t64
+# endif
+#endif
 extern int getitimer (__itimer_which_t __which,
 		      struct itimerval *__value) __THROW;
 
 /* Set the timer WHICH to *NEW.  If OLD is not NULL,
    set *OLD to the old value of timer WHICH.
    Returns 0 on success, -1 on errors.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (setitimer, (__itimer_which_t __which,
+       const struct itimerval *__restrict __new,
+       struct itimerval *__restrict __old), __setitimer_t64)
+       __THROW;
+# else
+# define setitimer __setitimer_t64
+# endif
+#endif
 extern int setitimer (__itimer_which_t __which,
 		      const struct itimerval *__restrict __new,
 		      struct itimerval *__restrict __old) __THROW;
@@ -132,15 +180,41 @@ extern int setitimer (__itimer_which_t __which,
 /* Change the access time of FILE to TVP[0] and the modification time of
    FILE to TVP[1].  If TVP is a null pointer, use the current time instead.
    Returns 0 on success, -1 on errors.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (utimes, (const char *__file,
+       const struct timeval __tvp[2]), __utimes64)
+       __THROW __nonnull ((1));
+# else
+# define utimes __utimes64
+# endif
+#endif
 extern int utimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 
 #ifdef __USE_MISC
 /* Same as `utimes', but does not follow symbolic links.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (lutimes, (const char *__file,
+       const struct timeval __tvp[2]), __lutimes64)
+       __THROW __nonnull ((1));
+# else
+# define lutimes __lutimes64
+# endif
+#endif
 extern int lutimes (const char *__file, const struct timeval __tvp[2])
      __THROW __nonnull ((1));
 
 /* Same as `utimes', but takes an open file descriptor instead of a name.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (futimes, (int __fd, const struct timeval __tvp[2]),
+     __futimes64) __THROW;
+# else
+# define futimes __futimes64
+# endif
+#endif
 extern int futimes (int __fd, const struct timeval __tvp[2]) __THROW;
 #endif
 
diff --git a/time/time.h b/time/time.h
index f12a4613fc..ca0152b003 100644
--- a/time/time.h
+++ b/time/time.h
@@ -72,16 +72,38 @@ __BEGIN_DECLS
 extern clock_t clock (void) __THROW;
 
 /* Return the current time and put it in *TIMER if TIMER is not NULL.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (time, (time_t * __timer),
+     __time_t64) __THROW;
+# else
+# define time __time_t64
+# endif
+#endif
 extern time_t time (time_t *__timer) __THROW;
 
 /* Return the difference between TIME1 and TIME0.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern double __REDIRECT (difftime, (time_t __time1, time_t __time0),
+     __difftime64) __THROW;
+# else
+# define difftime __difftime64
+# endif
+#endif
 extern double difftime (time_t __time1, time_t __time0)
      __THROW __attribute__ ((__const__));
 
 /* Return the `time_t' representation of TP and normalize TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (mktime, (struct tm *__tp), __mktime64) __THROW;
+# else
+# define mktime __mktime64
+# endif
+#endif
 extern time_t mktime (struct tm *__tp) __THROW;
 
-
 /* Format TP into S according to FORMAT.
    Write no more than MAXSIZE characters and return the number
    of characters written, or 0 if it would exceed MAXSIZE.  */
@@ -116,20 +138,52 @@ extern char *strptime_l (const char *__restrict __s,
 
 /* Return the `struct tm' representation of *TIMER
    in Universal Coordinated Time (aka Greenwich Mean Time).  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (gmtime, (const time_t *__timer),
+       __gmtime64) __THROW;
+# else
+# define gmtime __gmtime64
+# endif
+#endif
 extern struct tm *gmtime (const time_t *__timer) __THROW;
 
 /* Return the `struct tm' representation
    of *TIMER in the local timezone.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (localtime, (const time_t *__timer),
+       __localtime64) __THROW;
+# else
+# define localtime __localtime64
+# endif
+#endif
 extern struct tm *localtime (const time_t *__timer) __THROW;
 
 #ifdef __USE_POSIX
 /* Return the `struct tm' representation of *TIMER in UTC,
    using *TP to store the result.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (gmtime_r, (const time_t *__restrict
+       __timer, struct tm *__restrict __tp), __gmtime64_r) __THROW;
+# else
+# define gmtime_r __gmtime64_r
+# endif
+#endif
 extern struct tm *gmtime_r (const time_t *__restrict __timer,
 			    struct tm *__restrict __tp) __THROW;
 
 /* Return the `struct tm' representation of *TIMER in local time,
    using *TP to store the result.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern struct tm * __REDIRECT (localtime_r, (const time_t *__restrict
+       __timer, struct tm *__restrict __tp), __localtime64_r) __THROW;
+# else
+# define localtime_r __localtime64_r
+# endif
+#endif
 extern struct tm *localtime_r (const time_t *__restrict __timer,
 			       struct tm *__restrict __tp) __THROW;
 #endif	/* POSIX */
@@ -139,6 +193,14 @@ extern struct tm *localtime_r (const time_t *__restrict __timer,
 extern char *asctime (const struct tm *__tp) __THROW;
 
 /* Equivalent to `asctime (localtime (timer))'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern char * __REDIRECT (ctime, (const time_t *__timer),
+       __ctime64) __THROW;
+# else
+# define ctime __ctime64
+# endif
+#endif
 extern char *ctime (const time_t *__timer) __THROW;
 
 #ifdef __USE_POSIX
@@ -150,6 +212,14 @@ extern char *asctime_r (const struct tm *__restrict __tp,
 			char *__restrict __buf) __THROW;
 
 /* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern char * __REDIRECT (ctime_r, (const time_t *__restrict __timer,
+       char *__restrict __buf), __ctime64_r) __THROW;
+# else
+# define ctime_r __ctime64_r
+# endif
+#endif
 extern char *ctime_r (const time_t *__restrict __timer,
 		      char *__restrict __buf) __THROW;
 #endif	/* POSIX */
@@ -178,6 +248,14 @@ extern long int timezone;
 #ifdef __USE_MISC
 /* Set the system time to *WHEN.
    This call is restricted to the superuser.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (stime, (const time_t *__when), __stime_t64)
+           __THROW;
+# else
+# define stime __stime_t64
+# endif
+#endif
 extern int stime (const time_t *__when) __THROW;
 #endif
 
@@ -193,9 +271,23 @@ extern int stime (const time_t *__when) __THROW;
    localtime package.  These are included only for compatibility.  */
 
 /* Like `mktime', but for TP represents Universal Time, not local time.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (timegm, (struct tm *__tp), __timegm64) __THROW;
+# else
+# define timegm __timegm64
+# endif
+#endif
 extern time_t timegm (struct tm *__tp) __THROW;
 
 /* Another name for `mktime'.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern time_t __REDIRECT (timelocal, (struct tm *__tp), __timelocal64) __THROW;
+# else
+# define timelocal __timelocal64
+# endif
+#endif
 extern time_t timelocal (struct tm *__tp) __THROW;
 
 /* Return the number of days in YEAR.  */
@@ -208,17 +300,49 @@ extern int dysize (int __year) __THROW  __attribute__ ((__const__));
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (nanosleep, (const struct timespec *__requested_time,
+		      struct timespec *__remaining), __nanosleep_t64);
+# else
+# define nanosleep __nanosleep_t64
+# endif
+#endif
 extern int nanosleep (const struct timespec *__requested_time,
 		      struct timespec *__remaining);
 
 
 /* Get resolution of clock CLOCK_ID.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_getres, (clockid_t __clock_id, struct
+     timespec *__res), __clock_getres64) __THROW;
+# else
+# define clock_getres __clock_getres64
+# endif
+#endif
 extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __THROW;
 
 /* Get current value of clock CLOCK_ID and store it in TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_gettime, (clockid_t __clock_id, struct
+     timespec *__tp), __clock_gettime64) __THROW;
+# else
+# define clock_gettime __clock_gettime64
+# endif
+#endif
 extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW;
 
 /* Set clock CLOCK_ID to value TP.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_settime, (clockid_t __clock_id, const struct
+     timespec *__tp), __clock_settime64) __THROW;
+# else
+# define clock_settime __clock_settime64
+# endif
+#endif
 extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
      __THROW;
 
@@ -227,6 +351,15 @@ extern int clock_settime (clockid_t __clock_id, const struct timespec *__tp)
 
    This function is a cancellation point and therefore not marked with
    __THROW.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (clock_nanosleep, (clockid_t __clock_id, int __flags,
+     const struct timespec *__req, struct timespec *__rem),
+     __clock_nanosleep64) __THROW;
+# else
+# define clock_nanosleep __clock_nanosleep64
+# endif
+#endif
 extern int clock_nanosleep (clockid_t __clock_id, int __flags,
 			    const struct timespec *__req,
 			    struct timespec *__rem);
@@ -245,11 +378,29 @@ extern int timer_create (clockid_t __clock_id,
 extern int timer_delete (timer_t __timerid) __THROW;
 
 /* Set timer TIMERID to VALUE, returning old value in OVALUE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timer_settime, (timer_t __timerid, int __flags,
+			  const struct itimerspec *__restrict __value,
+			  struct itimerspec *__restrict __ovalue),
+                          __timer_settime64) __THROW;
+# else
+# define timer_settime __timer_settime64
+# endif
+#endif
 extern int timer_settime (timer_t __timerid, int __flags,
 			  const struct itimerspec *__restrict __value,
 			  struct itimerspec *__restrict __ovalue) __THROW;
 
 /* Get current value of timer TIMERID and store it in VALUE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timer_gettime, (timer_t __timerid, struct
+     itimerspec *__value), __timer_gettime64) __THROW __nonnull ((1));
+# else
+# define timer_gettime __timer_gettime64
+# endif
+#endif
 extern int timer_gettime (timer_t __timerid, struct itimerspec *__value)
      __THROW;
 
@@ -260,6 +411,14 @@ extern int timer_getoverrun (timer_t __timerid) __THROW;
 
 #ifdef __USE_ISOC11
 /* Set TS to calendar time based in time base BASE.  */
+#ifdef __USE_TIME_BITS64
+# if defined(__REDIRECT)
+extern int __REDIRECT (timespec_get, (struct timespec *__ts, int __base),
+     __timespec_get64) __THROW __nonnull ((1));
+# else
+# define timespec_get __timespec_get64
+# endif
+#endif
 extern int timespec_get (struct timespec *__ts, int __base)
      __THROW __nonnull ((1));
 #endif
-- 
2.11.0

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 17:42     ` Albert ARIBAUD
@ 2017-09-08 17:59       ` Joseph Myers
  2017-09-08 18:16         ` Albert ARIBAUD
  0 siblings, 1 reply; 76+ messages in thread
From: Joseph Myers @ 2017-09-08 17:59 UTC (permalink / raw)
  To: Albert ARIBAUD; +Cc: Zack Weinberg, GNU C Library

On Fri, 8 Sep 2017, Albert ARIBAUD wrote:

> Regarding whether the patches should land only once the kernel is
> Y0238-safe: these patches are intended to run even on a current and thus
> completely Y2038-unsafe kernel, in which case they use 64-bit-time on
> user side (to make applications compiled with _TIME_BITS==64 happy at
> least until Y2038 happens) and 32-bit time on kernel side. So I don't
> see why these patches should wait for a Y2038-safe kernel per se.

Where the kernel layouts of structures are suitable for use by glibc, we'd 
like to avoid translation layers.  E.g., we need to know what the kernel's 
struct stat64 variant for 64-bit time_t will look like to ensure no 
translation layer is needed.  (If the answer is that statx is the 
interface that should be used for 64-bit times in struct stat so the 
kernel doesn't need to define such a stat64 variant, then the translation 
layer is needed anyway and we should maybe use the asm-generic 64-bit 
struct stat variant of the layout on all 32-bit platforms.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 17:59       ` Joseph Myers
@ 2017-09-08 18:16         ` Albert ARIBAUD
  2017-09-08 18:36           ` Zack Weinberg
  0 siblings, 1 reply; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-08 18:16 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Zack Weinberg, GNU C Library

On Fri, 8 Sep 2017 17:59:00 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> On Fri, 8 Sep 2017, Albert ARIBAUD wrote:
> 
> > Regarding whether the patches should land only once the kernel is
> > Y0238-safe: these patches are intended to run even on a current and thus
> > completely Y2038-unsafe kernel, in which case they use 64-bit-time on
> > user side (to make applications compiled with _TIME_BITS==64 happy at
> > least until Y2038 happens) and 32-bit time on kernel side. So I don't
> > see why these patches should wait for a Y2038-safe kernel per se.  
> 
> Where the kernel layouts of structures are suitable for use by glibc, we'd 
> like to avoid translation layers.  E.g., we need to know what the kernel's 
> struct stat64 variant for 64-bit time_t will look like to ensure no 
> translation layer is needed.  (If the answer is that statx is the 
> interface that should be used for 64-bit times in struct stat so the 
> kernel doesn't need to define such a stat64 variant, then the translation 
> layer is needed anyway and we should maybe use the asm-generic 64-bit 
> struct stat variant of the layout on all 32-bit platforms.)

Understood -- but as soon as 64-bit-time types are frozen on the kernel
side, we could freeze the corresponding GLIBC API types (hopefully
without a translation layer needed) and then if GLIBC gets out there
before the kernel does, it won't be a problem since in any case the
64-bit-time implementation must fall back to 32-bit syscalls if the
64-bit syscalls return an ENOSYS.

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 17:24         ` Joseph Myers
@ 2017-09-08 18:32           ` Zack Weinberg
  0 siblings, 0 replies; 76+ messages in thread
From: Zack Weinberg @ 2017-09-08 18:32 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Albert ARIBAUD (3ADEV), GNU C Library

On Fri, Sep 8, 2017 at 1:24 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Fri, 8 Sep 2017, Zack Weinberg wrote:
>
>> Neither you, nor Rich, nor anyone else on the cited Austin Group
>> discussion has addressed the actual issue, which is that this is a
>> datum embedded in structures passed across the kernel/user boundary by
>> reference, it is impossible to enumerate all such structures,
>> therefore its type _must_ be a typedef so that it can be made to match
>> the kernel's expectations, whatever those might be.
>
> I don't see this as in any way an issue for having a definition of struct
> timespec that conforms to ISO C and POSIX requirements.  Code passing data
> to the kernel knows the structures being used locally and needs to convert
> it to the kernel's layout, which might be e.g. struct __kernel_timespec64.

This only works if all such structures can be enumerated and forced
through a compatibility layer.  History indicates that it is not, in
fact, possible to enumerate all such structures (the problem case I
know about is device-specific ioctl operations, which tend to be
created by driver authors who don't realize the need for ABI
compatibility shims until it's too late).

>> (And I don't particularly see why people seem to think this is an
>> x32-specific issue.  It potentially affects *any* 32-bit ABI on a
>> 64-bit kernel.)
>
> The kernel does the conversion just fine for a pure 32-bit struct timespec
> - as it does for the entire compat interface

For the reason given above, I confidently predict that there is at
least one failure to do this conversion correctly in every released
kernel ever.

>> <sys/types.h> doesn't exist in ISO C as far as I know, so how could it
>> be?  But any program that uses it opts into POSIX's specification for
>
> My point is that you can't expose nsec_t, even as a typedef for long, in
> <time.h> for C11.

I suppose it could be __nsec_t in time.h, but I would prefer to
include "and time.h defines nsec_t" in the scope of the willful
violation of C11.

zw

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 18:16         ` Albert ARIBAUD
@ 2017-09-08 18:36           ` Zack Weinberg
  0 siblings, 0 replies; 76+ messages in thread
From: Zack Weinberg @ 2017-09-08 18:36 UTC (permalink / raw)
  To: Albert ARIBAUD; +Cc: Joseph Myers, GNU C Library

On Fri, Sep 8, 2017 at 2:16 PM, Albert ARIBAUD <albert.aribaud@3adev.fr> wrote:
> On Fri, 8 Sep 2017 17:59:00 +0000, Joseph Myers
> <joseph@codesourcery.com> wrote :
>
>> On Fri, 8 Sep 2017, Albert ARIBAUD wrote:
>>
>> > Regarding whether the patches should land only once the kernel is
>> > Y0238-safe: these patches are intended to run even on a current and thus
>> > completely Y2038-unsafe kernel, in which case they use 64-bit-time on
>> > user side (to make applications compiled with _TIME_BITS==64 happy at
>> > least until Y2038 happens) and 32-bit time on kernel side. So I don't
>> > see why these patches should wait for a Y2038-safe kernel per se.
>>
>> Where the kernel layouts of structures are suitable for use by glibc, we'd
>> like to avoid translation layers.  E.g., we need to know what the kernel's
>> struct stat64 variant for 64-bit time_t will look like to ensure no
>> translation layer is needed.  (If the answer is that statx is the
>> interface that should be used for 64-bit times in struct stat so the
>> kernel doesn't need to define such a stat64 variant, then the translation
>> layer is needed anyway and we should maybe use the asm-generic 64-bit
>> struct stat variant of the layout on all 32-bit platforms.)
>
> Understood -- but as soon as 64-bit-time types are frozen on the kernel
> side, we could freeze the corresponding GLIBC API types (hopefully
> without a translation layer needed) and then if GLIBC gets out there
> before the kernel does, it won't be a problem since in any case the
> 64-bit-time implementation must fall back to 32-bit syscalls if the
> 64-bit syscalls return an ENOSYS.

I think that's right.  Syscalls we can add support for later, types
are much more troublesome.

zw

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 00/52] Make GLIBC Y2038-proof
  2017-09-08 17:26     ` Joseph Myers
@ 2017-09-08 19:19       ` Albert ARIBAUD
  0 siblings, 0 replies; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-08 19:19 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha

Hi Joseph,

On Fri, 8 Sep 2017 17:26:26 +0000, Joseph Myers
<joseph@codesourcery.com> wrote :

> On Fri, 8 Sep 2017, Albert ARIBAUD wrote:
> 
> > > * Documentation of _TIME_BITS is clearly needed.  
> > 
> > Where should this documentation go?  
> 
> In manual/creature.texi, alongside the documentation of _FILE_OFFSET_BITS.

Thanks, will do in 01/52 of v2.

> (It occurred to me that patches 50-52 don't seem to have reached the 
> mailing list, so I don't know what was in them.)

You're correct. I did not get any NDR so I cannot tell what happened...
I have sent the rest (threaded properly after 49/52, although missing
"References:" headers to 0/48 and previous).

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-08 17:49                                                                                                     ` [RFC PATCH 51/52] Y2038: add RPC functions Albert ARIBAUD (3ADEV)
  2017-09-08 17:49                                                                                                       ` [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support Albert ARIBAUD (3ADEV)
@ 2017-09-08 19:47                                                                                                       ` Joseph Myers
  2017-09-08 19:59                                                                                                       ` Paul Eggert
  2 siblings, 0 replies; 76+ messages in thread
From: Joseph Myers @ 2017-09-08 19:47 UTC (permalink / raw)
  To: Albert ARIBAUD (3ADEV); +Cc: libc-alpha

Since the RPC functions are already obsoleted (compat symbols unless you 
use --enable-obsolete-rpc), I think there is a good case for not providing 
_TIME_BITS=64 variants of them (#error in the relevant headers if used 
with _TIME_BITS=64), leaving it to TIRPC to provide such versions.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support
  2017-09-08 17:49                                                                                                       ` [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support Albert ARIBAUD (3ADEV)
@ 2017-09-08 19:47                                                                                                         ` Joseph Myers
  0 siblings, 0 replies; 76+ messages in thread
From: Joseph Myers @ 2017-09-08 19:47 UTC (permalink / raw)
  To: Albert ARIBAUD (3ADEV); +Cc: libc-alpha

I'd expect this patch to include the previously discussed #error (in 
features.h) if _TIME_BITS=64 is used without _FILE_OFFSET_BITS=64.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-08 17:49                                                                                                     ` [RFC PATCH 51/52] Y2038: add RPC functions Albert ARIBAUD (3ADEV)
  2017-09-08 17:49                                                                                                       ` [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support Albert ARIBAUD (3ADEV)
  2017-09-08 19:47                                                                                                       ` [RFC PATCH 51/52] Y2038: add RPC functions Joseph Myers
@ 2017-09-08 19:59                                                                                                       ` Paul Eggert
  2017-09-09 14:37                                                                                                         ` Albert ARIBAUD
  2017-09-11  7:06                                                                                                         ` Paul Eggert
  2 siblings, 2 replies; 76+ messages in thread
From: Paul Eggert @ 2017-09-08 19:59 UTC (permalink / raw)
  To: Albert ARIBAUD (3ADEV), libc-alpha

On 09/08/2017 10:49 AM, Albert ARIBAUD (3ADEV) wrote:
> +CLIENT *
> +__clntudp_create64 (struct sockaddr_in *raddr, u_long program, u_long version,
> +		    struct __timeval64 wait, int *sockp)
> +{
> +  struct timeval wait32;
> +  if (wait.tv_sec > INT_MAX)
> +  {
> +    return NULL;
> +  }
> +  return clntudp_create (raddr, program, version, wait32, sockp);
> +}

I'm not seeing how this could work. The code does not copy the value of 
'wait' to 'wait32'. And the code doesn't have a proper check for fitting 
in 'int', e.g., it will do the wrong thing for INT_MIN - 1L. And there's 
no error status set when the time is out of range.

I haven't reviewed the patches carefully, just caught this in a spot 
check. Please look systematically for similar errors.

While you're doing that systematic review, I suggest putting something 
like the following code into a suitable private include file, and using 
it to tell whether a __time64_t value is in time_t range. This will 
generate zero instructions when time_t is 64-bit, so generic callers can 
use this function without needing any ifdefs and without losing any 
performance on 64-bit time_t platforms. You should write similar static 
functions for checking whether struct __timeval64 is in struct timeval 
range, and similarly for struct __timespec64. These can check for the 
subseconds parts being in range, as needed (watch for x32 here). The 
idea is to be systematic about this stuff and to do it in one place, to 
avoid ticky-tack range bugs such as are in the above-quoted code.

   /* time_t is always 'long int' in the GNU C Library.  */
   #define TIME_T_MIN LONG_MIN
   #define TIME_T_MAX LONG_MAX

   static inline bool
   fits_in_time_t (__time64_t t)
   {
   #if 7 <= __GNUC__
     return !__builtin_add_overflow_p (t, 0, TIME_T_MAX);
   #endif
     return TIME_T_MIN <= t && t <= TIME_T_MAX;
   }

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-08 19:59                                                                                                       ` Paul Eggert
@ 2017-09-09 14:37                                                                                                         ` Albert ARIBAUD
  2017-09-11  6:33                                                                                                           ` Paul Eggert
  2017-09-11  7:06                                                                                                         ` Paul Eggert
  1 sibling, 1 reply; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-09 14:37 UTC (permalink / raw)
  To: Paul Eggert; +Cc: libc-alpha

Hi Paul,

On Fri, 8 Sep 2017 12:59:27 -0700, Paul Eggert <eggert@cs.ucla.edu>
wrote :

> On 09/08/2017 10:49 AM, Albert ARIBAUD (3ADEV) wrote:
> > +CLIENT *
> > +__clntudp_create64 (struct sockaddr_in *raddr, u_long program,
> > u_long version,
> > +		    struct __timeval64 wait, int *sockp)
> > +{
> > +  struct timeval wait32;
> > +  if (wait.tv_sec > INT_MAX)
> > +  {
> > +    return NULL;
> > +  }
> > +  return clntudp_create (raddr, program, version, wait32, sockp);
> > +}  
> 
> I'm not seeing how this could work. The code does not copy the value
> of 'wait' to 'wait32'. And the code doesn't have a proper check for
> fitting in 'int', e.g., it will do the wrong thing for INT_MIN - 1L.
> And there's no error status set when the time is out of range.

That's a cut/paste typo during a recent cleanup round :( --
__clntudp_bufcreate64 is missing the same two lines which are present
in __pmap_rmtcall_t64 and copy the timeout into its 32-bit counterpart.
Thanks for spotting this, will add the missing lines (or possibly a
call to a conversion function, similar to your suggestion below).

> I haven't reviewed the patches carefully, just caught this in a spot 
> check. Please look systematically for similar errors.

Will do.

> While you're doing that systematic review, I suggest putting something 
> like the following code into a suitable private include file, and using 
> it to tell whether a __time64_t value is in time_t range. This will 
> generate zero instructions when time_t is 64-bit, so generic callers can 
> use this function without needing any ifdefs and without losing any 
> performance on 64-bit time_t platforms. You should write similar static 
> functions for checking whether struct __timeval64 is in struct timeval 
> range, and similarly for struct __timespec64. These can check for the 
> subseconds parts being in range, as needed (watch for x32 here). The 
> idea is to be systematic about this stuff and to do it in one place, to 
> avoid ticky-tack range bugs such as are in the above-quoted code.
> 
>    /* time_t is always 'long int' in the GNU C Library.  */
>    #define TIME_T_MIN LONG_MIN
>    #define TIME_T_MAX LONG_MAX

BTW, time_t is a signed int, but its negative range is not completely
usable since (time_t)-1 is used as an error status. So should the
TIME_T_MIN limit be LONG_MIN or should it be 0?

>    static inline bool
>    fits_in_time_t (__time64_t t)
>    {
>    #if 7 <= __GNUC__
>      return !__builtin_add_overflow_p (t, 0, TIME_T_MAX);
>    #endif
>      return TIME_T_MIN <= t && t <= TIME_T_MAX;
>    }

Will do -- in fact, as I hinted above, I'll probably augment this with
timeval and timespec test and conversion functions to automate things
such as setting errno to EOVERFLOW if the conversion cannot be done.

Thanks for your comment and suggestion!

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-09 14:37                                                                                                         ` Albert ARIBAUD
@ 2017-09-11  6:33                                                                                                           ` Paul Eggert
  0 siblings, 0 replies; 76+ messages in thread
From: Paul Eggert @ 2017-09-11  6:33 UTC (permalink / raw)
  To: Albert ARIBAUD; +Cc: libc-alpha

Albert ARIBAUD wrote:
> time_t is a signed int, but its negative range is not completely
> usable since (time_t)-1 is used as an error status. So should the
> TIME_T_MIN limit be LONG_MIN or should it be 0?

Definitely LONG_MIN. Functions like localtime accept -1 as valid input meaning 
1969-12-31 23:59:59 UTC.

Even for some functions like mktime that return -1 as an error indicator, -1 can 
also be a valid (non-error) return value. I help maintain application code that 
can tell the difference between the two seemingly-identical -1s that mktime 
returns, so that the time_t range is completely usable there too. Admittedly 
it's not an ideal API.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-08 19:59                                                                                                       ` Paul Eggert
  2017-09-09 14:37                                                                                                         ` Albert ARIBAUD
@ 2017-09-11  7:06                                                                                                         ` Paul Eggert
  2017-09-11 14:07                                                                                                           ` Paul Eggert
  1 sibling, 1 reply; 76+ messages in thread
From: Paul Eggert @ 2017-09-11  7:06 UTC (permalink / raw)
  To: Albert ARIBAUD (3ADEV), libc-alpha

Paul Eggert wrote:
> 
>    /* time_t is always 'long int' in the GNU C Library.  */
>    #define TIME_T_MIN LONG_MIN
>    #define TIME_T_MAX LONG_MAX
> 
>    static inline bool
>    fits_in_time_t (__time64_t t)
>    {
>    #if 7 <= __GNUC__
>      return !__builtin_add_overflow_p (t, 0, TIME_T_MAX);
>    #endif
>      return TIME_T_MIN <= t && t <= TIME_T_MAX;
>    }

Marc Glisse suggested a simpler solution:

   static inline bool
   fits_in_time_t (__time64_t t)
   {
     return t == (time64_t) t;
   }

This is documented to work for GCC, something I had forgotten, and it generates 
better code for pre-7 GCC. See:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82170#c2

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-11  7:06                                                                                                         ` Paul Eggert
@ 2017-09-11 14:07                                                                                                           ` Paul Eggert
  2017-09-11 15:59                                                                                                             ` Albert ARIBAUD
  0 siblings, 1 reply; 76+ messages in thread
From: Paul Eggert @ 2017-09-11 14:07 UTC (permalink / raw)
  To: Albert ARIBAUD (3ADEV), libc-alpha

Paul Eggert wrote:
>    static inline bool
>    fits_in_time_t (__time64_t t)
>    {
>      return t == (time64_t) t;
>    }

Ooops, that last statement should be "return t == (time_t) t;" of course. Sorry.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [RFC PATCH 51/52] Y2038: add RPC functions
  2017-09-11 14:07                                                                                                           ` Paul Eggert
@ 2017-09-11 15:59                                                                                                             ` Albert ARIBAUD
  0 siblings, 0 replies; 76+ messages in thread
From: Albert ARIBAUD @ 2017-09-11 15:59 UTC (permalink / raw)
  To: Paul Eggert; +Cc: libc-alpha

Hi Paul,

On Mon, 11 Sep 2017 07:07:29 -0700, Paul Eggert <eggert@cs.ucla.edu>
wrote :

> Paul Eggert wrote:
> >    static inline bool
> >    fits_in_time_t (__time64_t t)
> >    {
> >      return t == (time64_t) t;
> >    }  
> 
> Ooops, that last statement should be "return t == (time_t) t;" of course. Sorry.

Noted -- and thanks to you and Marc for the simpler formulation.

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2017-09-11 15:59 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-07 22:42 [RFC PATCH 00/52] Make GLIBC Y2038-proof Albert ARIBAUD (3ADEV)
2017-09-07 22:42 ` [RFC PATCH 01/52] Y2038: add type __time64_t Albert ARIBAUD (3ADEV)
2017-09-07 22:42   ` [RFC PATCH 02/52] Y2038: add function __difftime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:42     ` [RFC PATCH 03/52] Y2038: add functions using struct tm Albert ARIBAUD (3ADEV)
2017-09-07 22:42       ` [RFC PATCH 04/52] Y2038: add function __mktime64 (and timelocal) Albert ARIBAUD (3ADEV)
2017-09-07 22:42         ` [RFC PATCH 05/52] Y2038: add function __timegm64 Albert ARIBAUD (3ADEV)
2017-09-07 22:42           ` [RFC PATCH 06/52] Y2038: add struct __timespec64 Albert ARIBAUD (3ADEV)
2017-09-07 22:42             ` [RFC PATCH 07/52] Y2038: add function __clock_gettime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43               ` [RFC PATCH 08/52] Y2038: add function __clock_settime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                 ` [RFC PATCH 09/52] Y2038: add function __clock_getres64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                   ` [RFC PATCH 10/52] Y2038: add function __clock_nanosleep64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                     ` [RFC PATCH 11/52] Y2038: add function __timespec_get64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                       ` [RFC PATCH 12/52] Y2038: add function __futimens64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                         ` [RFC PATCH 13/52] Y2038: add function __utimensat64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                           ` [RFC PATCH 14/52] Y2038: add function __sigtimedwait64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                             ` [RFC PATCH 15/52] Y2038: add struct __timeval64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                               ` [RFC PATCH 16/52] Y2038: add function __futimes64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                                 ` [RFC PATCH 17/52] Y2038: add function __lutimes64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                                   ` [RFC PATCH 18/52] Y2038: add struct __itimerspec64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                                     ` [RFC PATCH 19/52] Y2038: add function __timer_gettime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                                       ` [RFC PATCH 20/52] Y2038: add function __timer_settime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:43                                         ` [RFC PATCH 21/52] Y2038: add function __timerfd_gettime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                           ` [RFC PATCH 22/52] Y2038: add function __timerfd_settime64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                             ` [RFC PATCH 23/52] Y2038: add struct __stat64_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                               ` [RFC PATCH 24/52] Y2038: add function __fstat64_t64 (and __fxstat64_t64) Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                 ` [RFC PATCH 25/52] Y2038: add function __stat64_t64 (and __xstat64_t64) Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                   ` [RFC PATCH 26/52] Y2038: add function __lstat64_t64 (and __lxstat64_t64) Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                     ` [RFC PATCH 27/52] Y2038: add function __fstatat64_t64 (and __fxstatat_t64) Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                       ` [RFC PATCH 28/52] Y2038: add function __time_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                         ` [RFC PATCH 29/52] Y2038: add function __stime_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                           ` [RFC PATCH 30/52] Y2038: add function __utimes_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                             ` [RFC PATCH 31/52] Y2038: add function __gettimeofday_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                               ` [RFC PATCH 32/52] Y2038: add function __settimeofday_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                                 ` [RFC PATCH 33/52] Y2038: add function __mq_timedsend_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                                   ` [RFC PATCH 34/52] Y2038: add function __mq_timedreceive_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:44                                                                     ` [RFC PATCH 35/52] Y2038: add function __msgctl_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                       ` [RFC PATCH 36/52] Y2038: add function __sched_rr_get_interval_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                         ` [RFC PATCH 37/52] Y2038: add function __nanosleep64_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                           ` [RFC PATCH 38/52] Y2038: add function __adjtime_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                             ` [RFC PATCH 39/52] Y2038: add function __utime_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                               ` [RFC PATCH 40/52] Y2038: add struct __itimerval_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                 ` [RFC PATCH 41/52] Y2038: add function __getitimer_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                   ` [RFC PATCH 42/52] Y2038: add function __setitimer_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                     ` [RFC PATCH 43/52] Y2038: add functions using futexes Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                       ` [RFC PATCH 44/52] Y2038: add function __getrusage_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                         ` [RFC PATCH 45/52] Y2038: add struct __ntp_timeval_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                           ` [RFC PATCH 46/52] Y2038: add function __ntp_gettime_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                             ` [RFC PATCH 47/52] Y2038: add function __ntp_gettimex_t64 Albert ARIBAUD (3ADEV)
2017-09-07 22:45                                                                                               ` [RFC PATCH 48/52] Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64) Albert ARIBAUD (3ADEV)
2017-09-07 22:46                                                                                                 ` [RFC PATCH 49/52] Y2038: add function pselect Albert ARIBAUD (3ADEV)
2017-09-08 17:49                                                                                                   ` [RFC PATCH 50/52] Y2038: add function select Albert ARIBAUD (3ADEV)
2017-09-08 17:49                                                                                                     ` [RFC PATCH 51/52] Y2038: add RPC functions Albert ARIBAUD (3ADEV)
2017-09-08 17:49                                                                                                       ` [RFC PATCH 52/52] Y2038: add _TIME_BITS==64 support Albert ARIBAUD (3ADEV)
2017-09-08 19:47                                                                                                         ` Joseph Myers
2017-09-08 19:47                                                                                                       ` [RFC PATCH 51/52] Y2038: add RPC functions Joseph Myers
2017-09-08 19:59                                                                                                       ` Paul Eggert
2017-09-09 14:37                                                                                                         ` Albert ARIBAUD
2017-09-11  6:33                                                                                                           ` Paul Eggert
2017-09-11  7:06                                                                                                         ` Paul Eggert
2017-09-11 14:07                                                                                                           ` Paul Eggert
2017-09-11 15:59                                                                                                             ` Albert ARIBAUD
2017-09-07 23:21 ` [RFC PATCH 00/52] Make GLIBC Y2038-proof Joseph Myers
2017-09-08 16:19   ` Zack Weinberg
2017-09-08 16:43     ` Joseph Myers
2017-09-08 16:54       ` Paul Eggert
2017-09-08 17:01       ` Zack Weinberg
2017-09-08 17:24         ` Joseph Myers
2017-09-08 18:32           ` Zack Weinberg
2017-09-08 17:42     ` Albert ARIBAUD
2017-09-08 17:59       ` Joseph Myers
2017-09-08 18:16         ` Albert ARIBAUD
2017-09-08 18:36           ` Zack Weinberg
2017-09-08 17:08   ` Albert ARIBAUD
2017-09-08 17:26     ` Joseph Myers
2017-09-08 19:19       ` Albert ARIBAUD
2017-09-08  4:23 ` Albert ARIBAUD

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).