* Update the fftimehands. * Push the tick ffcount and time(s) forward based on current clock estimate. * The conversion from ffcounter to bintime relies on the difference clock * principle, whose accuracy relies on computing small time intervals. If a new * clock estimate has been passed by the synchronisation daemon, make it * current, and compute the linear interpolation for monotonic time
| 596 | * current, and compute the linear interpolation for monotonic time if needed. |
| 597 | */ |
| 598 | static void |
| 599 | ffclock_windup(unsigned int delta) |
| 600 | { |
| 601 | struct ffclock_estimate *cest; |
| 602 | struct fftimehands *ffth; |
| 603 | struct bintime bt, gap_lerp; |
| 604 | ffcounter ffdelta; |
| 605 | uint64_t frac; |
| 606 | unsigned int polling; |
| 607 | uint8_t forward_jump, ogen; |
| 608 | |
| 609 | /* |
| 610 | * Pick the next timehand, copy current ffclock estimates and move tick |
| 611 | * times and counter forward. |
| 612 | */ |
| 613 | forward_jump = 0; |
| 614 | ffth = fftimehands->next; |
| 615 | ogen = ffth->gen; |
| 616 | ffth->gen = 0; |
| 617 | cest = &ffth->cest; |
| 618 | bcopy(&fftimehands->cest, cest, sizeof(struct ffclock_estimate)); |
| 619 | ffdelta = (ffcounter)delta; |
| 620 | ffth->period_lerp = fftimehands->period_lerp; |
| 621 | |
| 622 | ffth->tick_time = fftimehands->tick_time; |
| 623 | ffclock_convert_delta(ffdelta, cest->period, &bt); |
| 624 | bintime_add(&ffth->tick_time, &bt); |
| 625 | |
| 626 | ffth->tick_time_lerp = fftimehands->tick_time_lerp; |
| 627 | ffclock_convert_delta(ffdelta, ffth->period_lerp, &bt); |
| 628 | bintime_add(&ffth->tick_time_lerp, &bt); |
| 629 | |
| 630 | ffth->tick_ffcount = fftimehands->tick_ffcount + ffdelta; |
| 631 | |
| 632 | /* |
| 633 | * Assess the status of the clock, if the last update is too old, it is |
| 634 | * likely the synchronisation daemon is dead and the clock is free |
| 635 | * running. |
| 636 | */ |
| 637 | if (ffclock_updated == 0) { |
| 638 | ffdelta = ffth->tick_ffcount - cest->update_ffcount; |
| 639 | ffclock_convert_delta(ffdelta, cest->period, &bt); |
| 640 | if (bt.sec > 2 * FFCLOCK_SKM_SCALE) |
| 641 | ffclock_status |= FFCLOCK_STA_UNSYNC; |
| 642 | } |
| 643 | |
| 644 | /* |
| 645 | * If available, grab updated clock estimates and make them current. |
| 646 | * Recompute time at this tick using the updated estimates. The clock |
| 647 | * estimates passed the feed-forward synchronisation daemon may result |
| 648 | * in time conversion that is not monotonically increasing (just after |
| 649 | * the update). time_lerp is a particular linear interpolation over the |
| 650 | * synchronisation algo polling period that ensures monotonicity for the |
| 651 | * clock ids requesting it. |
| 652 | */ |
| 653 | if (ffclock_updated > 0) { |
| 654 | bcopy(&ffclock_estimate, cest, sizeof(struct ffclock_estimate)); |
| 655 | ffdelta = ffth->tick_ffcount - cest->update_ffcount; |
no test coverage detected