Skip site navigation (1)Skip section navigation (2)
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>