Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Feb 2023 22:12:19 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: fd88f4e190bc - main - pps: Simplify capture and event processing
Message-ID:  <202302272212.31RMCJx0028799@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=fd88f4e190bc0a56f8d30179900553ce12d1c0d7

commit fd88f4e190bc0a56f8d30179900553ce12d1c0d7
Author:     Sebastian Huber <sebastian.huber@embedded-brains.de>
AuthorDate: 2023-02-27 21:49:09 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2023-02-27 22:10:55 +0000

    pps: Simplify capture and event processing
    
    Use local variables for the captured timehand and timecounter in pps_event().
    This fixes a potential issue in the nsec preparation for hardpps().  Here the
    timecounter was accessed through the captured timehand after the generation was
    checked.
    
    Make a snapshot of the relevent timehand values early in pps_event().  Check
    the timehand generation only once during the capture and event processing.  Use
    atomic_thread_fence_acq() similar to the other readers.
    
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/604
---
 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 = th->th_counter;
 	pps->capcount = tc->tc_get_timecount(tc);
-	atomic_thread_fence_acq();
-	if (pps->capgen != th->th_generation)
-		pps->capgen = 0;
 }
 
 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) == 0)
 		return;
+
+	/* Make a snapshot of the captured timehand */
+	capth = pps->capth;
+	captc = capth->th_counter;
+	capth_scale = capth->th_scale;
+	tcount = capth->th_offset_count;
+	bt = capth->th_bintime;
+
 	/* If the timecounter was wound up underneath us, bail out. */
-	if (pps->capgen == 0 || pps->capgen !=
-	    atomic_load_acq_int(&pps->capth->th_generation))
+	atomic_thread_fence_acq();
+	if (pps->capgen == 0 || pps->capgen != capth->th_generation)
 		return;
 
 	/* 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 != pps->capth->th_counter) {
-		pps->ppstc = pps->capth->th_counter;
+	if (__predict_false(pps->ppstc != captc)) {
+		pps->ppstc = captc;
 		*pcount = pps->capcount;
 		pps->ppscount[2] = pps->capcount;
 		return;
 	}
 
 	/* Convert the count to a timespec. */
-	tcount = pps->capcount - pps->capth->th_offset_count;
-	tcount &= pps->capth->th_counter->tc_counter_mask;
-	bt = pps->capth->th_bintime;
-	bintime_addx(&bt, pps->capth->th_scale * tcount);
+	tcount = pps->capcount - tcount;
+	tcount &= captc->tc_counter_mask;
+	bintime_addx(&bt, capth_scale * tcount);
 	bintime2timespec(&bt, &ts);
 
-	/* If the timecounter was wound up underneath us, bail out. */
-	atomic_thread_fence_acq();
-	if (pps->capgen != pps->capth->th_generation)
-		return;
-
 	*pcount = pps->capcount;
 	(*pseq)++;
 	*tsp = ts;
@@ -1890,9 +1892,9 @@ pps_event(struct pps_state *pps, int event)
 		 */
 		tcount = pps->capcount - pps->ppscount[2];
 		pps->ppscount[2] = pps->capcount;
-		tcount &= pps->capth->th_counter->tc_counter_mask;
+		tcount &= captc->tc_counter_mask;
 		scale = (uint64_t)1 << 63;
-		scale /= pps->capth->th_counter->tc_frequency;
+		scale /= captc->tc_frequency;
 		scale *= 2;
 		bt.sec = 0;
 		bt.frac = 0;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302272212.31RMCJx0028799>