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/