populateDataV2 populates fbclock.DataV2 with data from fbclock.Data plus calculated values
(shmv2 *fbclock.Shm)
| 561 | err = fmt.Errorf("PHC time is not monotonic: %d > %d", phcTimeFixed, cur.PHCTimeNS) |
| 562 | } |
| 563 | return coefPPB, err |
| 564 | } |
| 565 | |
| 566 | // populateDataV2 populates fbclock.DataV2 with data from fbclock.Data plus calculated values |
| 567 | func (s *Daemon) populateDataV2(shmv2 *fbclock.Shm) { |
| 568 | prevPrimary := fbclock.DataV2{} |
| 569 | prevRealtime := fbclock.DataV2{} |
| 570 | |
| 571 | fastTicker := time.NewTicker(10 * time.Millisecond) |
| 572 | defer fastTicker.Stop() |
| 573 | for ; true; <-fastTicker.C { // first run without delay, then at interval |
| 574 | if s.state.lastStoredData != nil { |
| 575 | // we need a copy of the latest v1 data to fill in parts of v2 data |
| 576 | // the pointer dereference is needed to avoid partial reads of the data |
| 577 | curData := *s.state.lastStoredData |
| 578 | phcTime, sysTime, clockID, phcReadDelay, err := s.getPHCAndSysTime() |
| 579 | if err != nil { |
| 580 | log.Errorf("reading PHC time from %s: %v", s.cfg.Iface, err) |
| 581 | s.stats.UpdateCounterBy("phc_read_error", 1) |
| 582 | continue |
| 583 | } |
| 584 | primary := fbclock.DataV2{ |
| 585 | IngressTimeNS: curData.IngressTimeNS, |
| 586 | ErrorBoundNS: curData.ErrorBoundNS + uint64(phcReadDelay.Nanoseconds()), //nolint:gosec |
| 587 | HoldoverMultiplierNS: curData.HoldoverMultiplierNS, |
| 588 | SmearingStartS: curData.SmearingStartS, |
| 589 | UTCOffsetPreS: int16(curData.UTCOffsetPreS), //nolint:gosec |
| 590 | UTCOffsetPostS: int16(curData.UTCOffsetPostS), //nolint:gosec |
| 591 | PHCTimeNS: phcTime.UnixNano(), |
| 592 | SysclockTimeNS: sysTime.UnixNano(), |
| 593 | ClockID: clockID, |
| 594 | } |
| 595 | if primary.CoefPPB, err = calcCoeffPPB(&prevPrimary, &primary); err != nil { |
| 596 | log.Warning(err) |
| 597 | s.stats.UpdateCounterBy("monotonictime_error", 1) |
| 598 | } |
| 599 | prevPrimary = primary |
| 600 | // Publish the primary section right away, before the slower REALTIME |
| 601 | // read below, so its anchor isn't aged by that read. |
| 602 | if err := fbclock.StoreFBClockDataV2(shmv2.File.Fd(), primary); err != nil { |
| 603 | log.Errorf("writing dataV2 to shm: %v", err) |
| 604 | } |
| 605 | |
| 606 | // The REALTIME anchor section is only needed on hosts whose primary is |
| 607 | // MONOTONIC_RAW. When the primary is already REALTIME, gettime_past uses |
| 608 | // it directly, so we skip the second ioctl and don't write the section. |
| 609 | if clockID != unix.CLOCK_REALTIME { |
| 610 | phcTimeRT, sysTimeRT, phcReadDelayRT, errRT := s.getPHCAndSysTimeRealtime() |
| 611 | if errRT != nil { |
| 612 | // Tolerate failure: the primary section still publishes. |
| 613 | log.Warningf("reading PHC time (REALTIME anchor) from %s: %v", s.cfg.Iface, errRT) |
| 614 | s.stats.UpdateCounterBy("phc_read_error", 1) |
| 615 | } else { |
| 616 | // Start from the primary so the host-level fields (ingress, |
| 617 | // holdover, utc, smearing) are shared, then override with the |
| 618 | // REALTIME anchor and its own independent error bound. |
| 619 | rt := primary |
| 620 | rt.ClockID = unix.CLOCK_REALTIME |
no test coverage detected