The interrupt handler is the only writer of interval_ms, valid and next_slot. The foreground function takes an interrupt-safe ring-buffer snapshot inside a short critical section, copying the count and exactly that many valid entries before restoring the previous mask. It performs the comparatively expensive summation and division after interrupts are restored. A new pulse then affects the next query, while the current query consistently describes the earlier snapshot.
Without exclusion, the foreground could read an old entry, be interrupted while the buffer is updated, then read new entries or an inconsistent count. Even indivisible 32-bit loads would not make that multi-element snapshot atomic. The volatile-qualified objects in C ensure that the compiler performs required shared or device accesses; volatile does not provide mutual exclusion or a coherent multiword snapshot.[ref]
This design assumes a single-core foreground/interrupt execution model: no other interrupt, DMA engine or core modifies the protected buffer. The mask hooks must prevent compiler reordering across their boundaries and really mask the GPIO interrupt. Restoring the saved mask also makes the function safe to call when interrupts were already disabled. Keep the critical section short enough that the event register does not coalesce multiple heartbeats while interrupts are masked; otherwise the hardware interface cannot reconstruct events it never recorded.

Articles by others on the same topic (0)

There are currently no matching articles.