pps_capture() and pps_fetch()
- Reply: Poul-Henning Kamp: "Re: pps_capture() and pps_fetch()"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 01 Jun 2022 07:08:13 UTC
Hello,
I try to understand how the PPS synchronization works in FreeBSD. It
seems that pps_capture() starts a transaction and pps_event() completes
the transaction if nothing interfered in the meantime.
void
pps_capture(struct pps_state *pps)
{
struct timehands *th;
KASSERT(pps != NULL, ("NULL pps pointer in pps_capture"));
th = timehands;
pps->capgen = atomic_load_acq_int(&th->th_generation);
pps->capth = th;
#ifdef FFCLOCK
pps->capffth = fftimehands;
#endif
pps->capcount = th->th_counter->tc_get_timecount(th->th_counter);
atomic_thread_fence_acq();
if (pps->capgen != th->th_generation)
pps->capgen = 0;
}
This function uses the current timehand to capture the time measured by
the timecounter of the timehand. The timehand generation is used to
ensure a consistent transaction.
We have
void
pps_event(struct pps_state *pps, int event)
{
[...]
/* If the timecounter was wound up underneath us, bail out. */
if (pps->capgen == 0 || pps->capgen !=
atomic_load_acq_int(&pps->capth->th_generation))
return;
[...]
/*
* 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;
*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);
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;
[...]
}
Why do we need the
atomic_thread_fence_acq();
if (pps->capgen != th->th_generation)
pps->capgen = 0;
in pps_capture()?
Why do we need the early
/* If the timecounter was wound up underneath us, bail out. */
if (pps->capgen == 0 || pps->capgen !=
atomic_load_acq_int(&pps->capth->th_generation))
return;
in pps_event()?
Shouldn't a single
if (pps->capgen == 0 || pps->capgen !=
atomic_load_acq_int(&pps->capth->th_generation))
return;
after the bintime_addx(&bt, pps->capth->th_scale * tcount); in
pps_event() be sufficient? The capture timehand may change anytime, so
why is the generation checked multiple times?
--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.huber@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax: +49-89-18 94 741 - 08
Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/