Date: Wed, 1 Jun 2022 09:08:13 +0200 From: Sebastian Huber <sebastian.huber@embedded-brains.de> To: hackers@freebsd.org Subject: pps_capture() and pps_fetch() Message-ID: <5b8310db-c94b-709f-8c57-bec2d413a80f@embedded-brains.de>
next in thread | raw e-mail | index | archive | help
Hello,
I try to understand how the PPS synchronization works in FreeBSD. It=20
seems that pps_capture() starts a transaction and pps_event() completes=20
the transaction if nothing interfered in the meantime.
void
pps_capture(struct pps_state *pps)
{
struct timehands *th;
KASSERT(pps !=3D NULL, ("NULL pps pointer in pps_capture"));
th =3D timehands;
pps->capgen =3D atomic_load_acq_int(&th->th_generation);
pps->capth =3D th;
#ifdef FFCLOCK
pps->capffth =3D fftimehands;
#endif
pps->capcount =3D th->th_counter->tc_get_timecount(th->th_counter);
atomic_thread_fence_acq();
if (pps->capgen !=3D th->th_generation)
pps->capgen =3D 0;
}
This function uses the current timehand to capture the time measured by=20
the timecounter of the timehand. The timehand generation is used to=20
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 =3D=3D 0 || pps->capgen !=3D
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 !=3D pps->capth->th_counter) {
pps->ppstc =3D pps->capth->th_counter;
*pcount =3D pps->capcount;
pps->ppscount[2] =3D pps->capcount;
return;
}
/* 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);
bintime2timespec(&bt, &ts);
/* If the timecounter was wound up underneath us, bail out. */
atomic_thread_fence_acq();
if (pps->capgen !=3D pps->capth->th_generation)
return;
[...]
}
Why do we need the
atomic_thread_fence_acq();
if (pps->capgen !=3D th->th_generation)
pps->capgen =3D 0;
in pps_capture()?
Why do we need the early
/* 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))
return;
in pps_event()?
Shouldn't a single
if (pps->capgen =3D=3D 0 || pps->capgen !=3D
atomic_load_acq_int(&pps->capth->th_generation))
return;
after the bintime_addx(&bt, pps->capth->th_scale * tcount); in=20
pps_event() be sufficient? The capture timehand may change anytime, so=20
why is the generation checked multiple times?
--=20
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=C3=BCnchen
Registernummer: HRB 157899
Vertretungsberechtigte Gesch=C3=A4ftsf=C3=BChrer: Peter Rasmussen, Thomas=
D=C3=B6rfler
Unsere Datenschutzerkl=C3=A4rung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5b8310db-c94b-709f-8c57-bec2d413a80f>
