diff --git a/support/Makefile b/support/Makefile
index 3325feb790..b308fe0856 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -31,6 +31,7 @@ libsupport-routines = \
   check_dns_packet \
   check_hostent \
   check_netent \
+  cpuclock \
   delayed_exit \
   ignore_stderr \
   next_to_fault \
diff --git a/support/cpuclock.c b/support/cpuclock.c
new file mode 100644
index 0000000000..f40c7e8d4a
--- /dev/null
+++ b/support/cpuclock.c
@@ -0,0 +1,51 @@
+/* Support functions for cpuclock tests.
+   Copyright (C) 2018-2020 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include "cpuclock.h"
+#include <stdlib.h>
+
+#define T_1s 1000000000.0
+
+struct timespec time_normalize(struct timespec t) {
+	int diff;
+	diff = (t.tv_nsec / T_1s);
+	t.tv_sec += diff;
+	t.tv_nsec += -(diff * T_1s);
+	return t;
+}
+
+struct timespec time_add(struct timespec a, struct timespec b) {
+	struct timespec s = {.tv_sec = a.tv_sec + b.tv_sec,
+			     .tv_nsec = a.tv_nsec + b.tv_nsec};
+	return time_normalize(s);
+}
+
+struct timespec time_sub(struct timespec a, struct timespec b) {
+	struct timespec d = {.tv_sec = a.tv_sec - b.tv_sec,
+			     .tv_nsec = a.tv_nsec - b.tv_nsec};
+	return time_normalize(d);
+}
+
+int percent_diff_check(struct timespec base, struct timespec dev,
+		       float upper_bound, float lower_bound) {
+	double timea = base.tv_sec + base.tv_nsec / T_1s;
+	double timeb = dev.tv_sec + dev.tv_nsec / T_1s;
+	double diff = (timea - timeb) / (0.5 * (timea + timeb));
+	return (diff >= -upper_bound && diff <= lower_bound );
+}
+
diff --git a/support/cpuclock.h b/support/cpuclock.h
new file mode 100644
index 0000000000..2505fbdcff
--- /dev/null
+++ b/support/cpuclock.h
@@ -0,0 +1,30 @@
+/* Support functions for cpuclock tests.
+   Copyright (C) 2018-2020 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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef SUPPORT_CPUCLOCK_H
+#define SUPPORT_CPUCLOCK_H
+
+#include <time.h>
+
+struct timespec time_normalize(struct timespec t);
+struct timespec time_add(struct timespec a, struct timespec b);
+struct timespec time_sub(struct timespec a, struct timespec b);
+int percent_diff_check(struct timespec base, struct timespec dev,
+		       float upper_bound, float lower_bound);
+
+#endif /* SUPPORT_CPUCLOCK_H */
diff --git a/time/tst-cpuclock1.c b/time/tst-cpuclock1.c
index 0120906f23..4051de1646 100644
--- a/time/tst-cpuclock1.c
+++ b/time/tst-cpuclock1.c
@@ -26,6 +26,7 @@
 #include <signal.h>
 #include <stdint.h>
 #include <sys/wait.h>
+#include <support/cpuclock.h>
 
 /* This function is intended to rack up both user and system time.  */
 static void
@@ -155,19 +156,11 @@ do_test (void)
   printf ("live PID %d after sleep => %ju.%.9ju\n",
 	  child, (uintmax_t) after.tv_sec, (uintmax_t) after.tv_nsec);
 
-  struct timespec diff = { .tv_sec = after.tv_sec - before.tv_sec,
-			   .tv_nsec = after.tv_nsec - before.tv_nsec };
-  if (diff.tv_nsec < 0)
-    {
-      --diff.tv_sec;
-      diff.tv_nsec += 1000000000;
-    }
-  if (diff.tv_sec != 0
-      || diff.tv_nsec > 600000000
-      || diff.tv_nsec < 100000000)
+  struct timespec diff = time_sub(after, before);
+  if (!percent_diff_check(sleeptime, diff, .3, 2))
     {
       printf ("before - after %ju.%.9ju outside reasonable range\n",
-	      (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
+	    (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
       result = 1;
     }
 
@@ -194,19 +187,11 @@ do_test (void)
 	}
       else
 	{
-	  struct timespec d = { .tv_sec = afterns.tv_sec - after.tv_sec,
-				.tv_nsec = afterns.tv_nsec - after.tv_nsec };
-	  if (d.tv_nsec < 0)
-	    {
-	      --d.tv_sec;
-	      d.tv_nsec += 1000000000;
-	    }
-	  if (d.tv_sec > 0
-	      || d.tv_nsec < sleeptime.tv_nsec
-	      || d.tv_nsec > sleeptime.tv_nsec * 2)
+	  diff = time_sub(afterns, after);
+	  if (!percent_diff_check(sleeptime, diff, .6, .34))
 	    {
 	      printf ("nanosleep time %ju.%.9ju outside reasonable range\n",
-		      (uintmax_t) d.tv_sec, (uintmax_t) d.tv_nsec);
+		     (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
 	      result = 1;
 	    }
 	}
@@ -241,20 +226,14 @@ do_test (void)
   printf ("dead PID %d => %ju.%.9ju\n",
 	  child, (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
 
-  diff.tv_sec = dead.tv_sec - after.tv_sec;
-  diff.tv_nsec = dead.tv_nsec - after.tv_nsec;
-  if (diff.tv_nsec < 0)
-    {
-      --diff.tv_sec;
-      diff.tv_nsec += 1000000000;
-    }
-  if (diff.tv_sec != 0 || diff.tv_nsec > 200000000)
+  diff = time_sub(dead, after);
+  sleeptime.tv_nsec = 100000000;
+  if (!percent_diff_check(sleeptime, diff, .6, .36))
     {
       printf ("dead - after %ju.%.9ju outside reasonable range\n",
-	      (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
+	     (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
       result = 1;
     }
-
   /* Now reap the child and verify that its clock is no longer valid.  */
   {
     int x;
