aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-06-22 23:24:08 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-06-23 21:36:33 +0000
commit60b0ad10dd0fc7ff6892ecc7ba3458482fcc064c (patch)
tree03a53983d09dcdf4faf803ef1271765f1ee75a35
parente912fbe1675714aab0179999923c171615e78c07 (diff)
downloadsrc-60b0ad10dd0fc7ff6892ecc7ba3458482fcc064c.tar.gz
src-60b0ad10dd0fc7ff6892ecc7ba3458482fcc064c.zip
vdso: lower precision of vdso implementation of CLOCK_MONOTONIC_FAST and CLOCK_UPTIME_FAST
so that libc vdso and kernel syscall give closer results. Reported by: dchagin Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D30873
-rw-r--r--lib/libc/sys/__vdso_gettimeofday.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/lib/libc/sys/__vdso_gettimeofday.c b/lib/libc/sys/__vdso_gettimeofday.c
index 4c1f4bda23e1..c1457a54d37e 100644
--- a/lib/libc/sys/__vdso_gettimeofday.c
+++ b/lib/libc/sys/__vdso_gettimeofday.c
@@ -106,6 +106,30 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, bool abs)
return (0);
}
+static int
+getnanouptime(struct bintime *bt, struct vdso_timekeep *tk)
+{
+ struct vdso_timehands *th;
+ uint32_t curr, gen;
+
+ do {
+ if (!tk->tk_enabled)
+ return (ENOSYS);
+
+ curr = atomic_load_acq_32(&tk->tk_current);
+ th = &tk->tk_th[curr];
+ gen = atomic_load_acq_32(&th->th_gen);
+ *bt = th->th_offset;
+
+ /*
+ * Ensure that the load of th_offset is completed
+ * before the load of th_gen.
+ */
+ atomic_thread_fence_acq();
+ } while (curr != tk->tk_current || gen == 0 || gen != th->th_gen);
+ return (0);
+}
+
static struct vdso_timekeep *tk;
#pragma weak __vdso_gettimeofday
@@ -154,9 +178,11 @@ __vdso_clock_gettime(clockid_t clock_id, struct timespec *ts)
break;
case CLOCK_MONOTONIC:
case CLOCK_MONOTONIC_PRECISE:
- case CLOCK_MONOTONIC_FAST:
case CLOCK_UPTIME:
case CLOCK_UPTIME_PRECISE:
+ error = binuptime(&bt, tk, false);
+ break;
+ case CLOCK_MONOTONIC_FAST:
case CLOCK_UPTIME_FAST:
error = getnanouptime(&bt, tk);
break;