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>