Page MenuHomeFreeBSD

FFclock: Restructure of FFclock resets
Needs ReviewPublic

Authored by Darryl.Veitch_uts.edu.au on Dec 7 2023, 12:40 AM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Oct 13, 1:18 AM
Unknown Object (File)
Mon, Oct 6, 11:55 PM
Unknown Object (File)
Mon, Sep 29, 4:21 AM
Unknown Object (File)
Mon, Sep 29, 1:48 AM
Unknown Object (File)
Thu, Sep 25, 1:26 AM
Unknown Object (File)
Mon, Sep 22, 6:22 PM
Unknown Object (File)
Sat, Sep 20, 2:17 PM
Unknown Object (File)
Sat, Sep 20, 1:50 PM
Subscribers
None

Details

Reviewers
phk
imp
Summary

Context: Following a reset of the RTC (Real Time Clock),
subr_rtc.c:inittoddr is invoked to reset the system clock. The FBclock
is reset by a call to tc_setclock, then the FFclock by a call to
ffclock_reset_clock. The current implemention has several issues that
this commit corrects. Recall that the system clock can be powered by
either the FBclock or FFclock and that this can be changed at any time,
it is important that the two be as aligned as practicable, in particular
with respect to uptime.

sysclock alignment :
To manage FFclock resets within a coherent framework, with maximum
consistency with the FBclock, all reset intelligence has been relocated
within a reset_FBbootime branch of ffclock_windup. This had multiple
advantages:

i) integration of reset control: flow of control for FBclock reset is

 inittoddr
   tc_setclock
      mtx_lock_spin(&tc_setclock_mtx);
      tc_windup(&new_boottimebin);
      mtx_unlock_spin(&tc_setclock_mtx);

 In addition to new_boottimebin, tc_windup calculates the corresponding
 FBclock reset UTC value. The call to ffclock_windup has been
 repositioned within tc_windup and expanded to :
   ffclock_windup(delta, *reset_FBbootime, *reset_UTC)
 to take avantage of both of these.
 Within ffclock_windup, the reset case is now explicitly captured by
 the reset_FBbootime branch. Within it all FFclock absolute time
 clocks are set to correspond exactly to the FBclock UTC clock.
 Uptime setting however now depends on the active value of sysclock,
 as explained in the comments, in order to minimize issues under
 sysclock changes.
 As a result, FFclock code has been removed from subr_rtc.c, and both
 FB and FF clock families are reset together within the same tc-tick,
 effectively synchronously due to the tc_setclock_mtx protection.
 Verbosity is added to track the UTC and uptime impacts of the reset,
 a rare event.

NOTE: even diffFFC is jumped following a reset. This is because a reset
typically implies a sleep even where the counter itself stops. This
breaks the diffFFC paradigm. The diffFFC should not be used to
calculate time differences across a reset event.

ii) elimination of delayed signalling logic: previously the reset case

was signalled to ffclock_windup via a special value
(ffclock_updated = INT8_MAX;) set within ffclock_reset_clock. This
was detected in the ffclock_updated>0 branch on a subsequent tick,
but not all of the reinitializations required were performed, some
calculations were superfluous, and the ffclock_updated based
management could fail in some corner cases. Now a dedicated full
reinitialization is performed within the reset_FBbootime branch, the
logic is clearer and corner cases are eliminated.

iii) bug fix: previously in ffclock_reset_clock ffclock_boottime was

set to the RTC reset value. This caused uptime values to jump to
erroneous values that could cause kernel freezes when sysclock was
switched from FBclock to FFclock. The new structure prevents this.

monoFFC jumping code:
The monoFFC exceptional case jumping code has been enhanced:

  • removal of the FFCLOCK_STA_WARMUP test, since a RTC reset can occur at any time and will typically trigger the need for this case.
  • verbosity allowing uptime continuity to be tracked across a jump.

FF daemon feedback:
The FFclock reset events in ffclock_windup (RTC resets) and
ffclock_change_tc (counter change) each modify the current value of the
natFFC data in fftimehands->cest . To communicate these important (and
hopefully very rare) events to the FFclock daemon (for example by the
test secs_to_nextupdate == 0), pushing of the reset structure to the
global ffclock_estimate has been added.
Each of these functions is called within tc_windup, where the spin lock
tc_setclock_mtx is held. This requires that ffclock_mtx be changed to a
spinlock (since a non-spin lock can sleep, which generates a kernel
panic). This should not increase overheads since tc_setclock_mtx has
already blocked interrupts, and the critical section for ffclock_mtx is
just a memcpy and an assignment and so will execute deterministically.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 54835
Build 51724: arc lint + arc unit