* Adjust the fftimehands when the timecounter is changed. Stating the obvious, * the old and new hardware counter cannot be read simultaneously. tc_windup() * does read the two counters 'back to back', but a few cycles are effectively * lost, and not accumulated in tick_ffcount. This is a fairly radical * operation for a feed-forward synchronization daemon, and it is its job to not * pushing
| 748 | * realize the counter has changed. |
| 749 | */ |
| 750 | static void |
| 751 | ffclock_change_tc(struct timehands *th) |
| 752 | { |
| 753 | struct fftimehands *ffth; |
| 754 | struct ffclock_estimate *cest; |
| 755 | struct timecounter *tc; |
| 756 | uint8_t ogen; |
| 757 | |
| 758 | tc = th->th_counter; |
| 759 | ffth = fftimehands->next; |
| 760 | ogen = ffth->gen; |
| 761 | ffth->gen = 0; |
| 762 | |
| 763 | cest = &ffth->cest; |
| 764 | bcopy(&(fftimehands->cest), cest, sizeof(struct ffclock_estimate)); |
| 765 | cest->period = ((1ULL << 63) / tc->tc_frequency ) << 1; |
| 766 | cest->errb_abs = 0; |
| 767 | cest->errb_rate = 0; |
| 768 | cest->status |= FFCLOCK_STA_UNSYNC; |
| 769 | |
| 770 | ffth->tick_ffcount = fftimehands->tick_ffcount; |
| 771 | ffth->tick_time_lerp = fftimehands->tick_time_lerp; |
| 772 | ffth->tick_time = fftimehands->tick_time; |
| 773 | ffth->period_lerp = cest->period; |
| 774 | |
| 775 | /* Do not lock but ignore next update from synchronization daemon. */ |
| 776 | ffclock_updated--; |
| 777 | |
| 778 | if (++ogen == 0) |
| 779 | ogen = 1; |
| 780 | ffth->gen = ogen; |
| 781 | fftimehands = ffth; |
| 782 | } |
| 783 | |
| 784 | /* |
| 785 | * Retrieve feed-forward counter and time of last kernel tick. |