summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-02-27 14:49:09 -0700
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-03-07 07:30:44 +0100
commit2a30bbf85225124359429cd765613b57aad9580b (patch)
treeebce41b7a85c3e38b69a13de5b24567550f8e62e
parentpps: Load timecounter once in pps_capture() (diff)
downloadrtems-2a30bbf85225124359429cd765613b57aad9580b.tar.bz2
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
-rw-r--r--cpukit/score/src/kern_tc.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index eca1a80f33..99abd652d8 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -2152,16 +2152,14 @@ pps_capture(struct pps_state *pps)
#endif
tc = th->th_counter;
pps->capcount = tc->tc_get_timecount(tc);
-#if defined(RTEMS_SMP)
- atomic_thread_fence_acq();
- if (pps->capgen != th->th_generation)
- pps->capgen = 0;
-#endif
}
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;
uint32_t tcount, *pcount;
@@ -2180,13 +2178,21 @@ 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. */
+ atomic_thread_fence_acq();
#if defined(RTEMS_SMP)
- if (pps->capgen == 0 || pps->capgen !=
+ if (pps->capgen == 0 || pps->capgen != capth->th_generation)
#else
- if (pps->capgen !=
+ if (pps->capgen != capth->th_generation)
#endif
- atomic_load_acq_int(&pps->capth->th_generation))
return;
/* Things would be easier with arrays. */
@@ -2224,25 +2230,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;
@@ -2276,9 +2276,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;