Skip site navigation (1)Skip section navigation (2)
Date:      Thu,  7 Jul 2022 17:25:02 +0200
From:      Sebastian Huber <sebastian.huber@embedded-brains.de>
To:        freebsd-hackers@freebsd.org
Subject:   [PATCH 2/6] pps: Simplify capture and event processing
Message-ID:  <20220707152506.55626-3-sebastian.huber@embedded-brains.de>
In-Reply-To: <20220707152506.55626-1-sebastian.huber@embedded-brains.de>
References:  <20220707152506.55626-1-sebastian.huber@embedded-brains.de>

next in thread | previous in thread | raw e-mail | index | archive | help
Use local variables for the captured timehand and timecounter in pps_even=
t().
This fixes a potential issue in the nsec preparation for hardpps().  Here=
 the
timecounter was accessed through the captured timehand after the generati=
on was
checked.

Make a snapshot of the relevent timehand values early in pps_event().  Ch=
eck
the timehand generation only once during the capture and event processing=
.  Use
atomic_thread_fence_acq() similar to the other readers.
---
 sys/kern/kern_tc.c | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 20520adc0aba..b466fd4399e4 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -1772,14 +1772,14 @@ pps_capture(struct pps_state *pps)
 #endif
 	tc =3D th->th_counter;
 	pps->capcount =3D tc->tc_get_timecount(tc);
-	atomic_thread_fence_acq();
-	if (pps->capgen !=3D th->th_generation)
-		pps->capgen =3D 0;
 }
=20
 void
 pps_event(struct pps_state *pps, int event)
 {
+	struct timehands *capth;
+	struct timecounter *captc;
+	uint64_t capth_scale;
 	struct bintime bt;
 	struct timespec ts, *tsp, *osp;
 	u_int tcount, *pcount;
@@ -1798,9 +1798,17 @@ pps_event(struct pps_state *pps, int event)
 	/* Nothing to do if not currently set to capture this event type. */
 	if ((event & pps->ppsparam.mode) =3D=3D 0)
 		return;
+
+	/* Make a snapshot of the captured timehand */
+	capth =3D pps->capth;
+	captc =3D capth->th_counter;
+	capth_scale =3D capth->th_scale;
+	tcount =3D capth->th_offset_count;
+	bt =3D capth->th_bintime;
+
 	/* If the timecounter was wound up underneath us, bail out. */
-	if (pps->capgen =3D=3D 0 || pps->capgen !=3D
-	    atomic_load_acq_int(&pps->capth->th_generation))
+	atomic_thread_fence_acq();
+	if (pps->capgen =3D=3D 0 || pps->capgen !=3D capth->th_generation)
 		return;
=20
 	/* Things would be easier with arrays. */
@@ -1838,25 +1846,19 @@ pps_event(struct pps_state *pps, int event)
 	 * If the timecounter changed, we cannot compare the count values, so
 	 * we have to drop the rest of the PPS-stuff until the next event.
 	 */
-	if (pps->ppstc !=3D pps->capth->th_counter) {
-		pps->ppstc =3D pps->capth->th_counter;
+	if (__predict_false(pps->ppstc !=3D captc)) {
+		pps->ppstc =3D captc;
 		*pcount =3D pps->capcount;
 		pps->ppscount[2] =3D pps->capcount;
 		return;
 	}
=20
 	/* Convert the count to a timespec. */
-	tcount =3D pps->capcount - pps->capth->th_offset_count;
-	tcount &=3D pps->capth->th_counter->tc_counter_mask;
-	bt =3D pps->capth->th_bintime;
-	bintime_addx(&bt, pps->capth->th_scale * tcount);
+	tcount =3D pps->capcount - tcount;
+	tcount &=3D captc->tc_counter_mask;
+	bintime_addx(&bt, capth_scale * tcount);
 	bintime2timespec(&bt, &ts);
=20
-	/* If the timecounter was wound up underneath us, bail out. */
-	atomic_thread_fence_acq();
-	if (pps->capgen !=3D pps->capth->th_generation)
-		return;
-
 	*pcount =3D pps->capcount;
 	(*pseq)++;
 	*tsp =3D ts;
@@ -1890,9 +1892,9 @@ pps_event(struct pps_state *pps, int event)
 		 */
 		tcount =3D pps->capcount - pps->ppscount[2];
 		pps->ppscount[2] =3D pps->capcount;
-		tcount &=3D pps->capth->th_counter->tc_counter_mask;
+		tcount &=3D captc->tc_counter_mask;
 		scale =3D (uint64_t)1 << 63;
-		scale /=3D pps->capth->th_counter->tc_frequency;
+		scale /=3D captc->tc_frequency;
 		scale *=3D 2;
 		bt.sec =3D 0;
 		bt.frac =3D 0;
--=20
2.35.3




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20220707152506.55626-3-sebastian.huber>