LCOV - code coverage report
Current view: top level - kernel/time - timecounter.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 33 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 4 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0+
       2             : /*
       3             :  * Based on clocksource code. See commit 74d23cc704d1
       4             :  */
       5             : #include <linux/export.h>
       6             : #include <linux/timecounter.h>
       7             : 
       8           0 : void timecounter_init(struct timecounter *tc,
       9             :                       const struct cyclecounter *cc,
      10             :                       u64 start_tstamp)
      11             : {
      12           0 :         tc->cc = cc;
      13           0 :         tc->cycle_last = cc->read(cc);
      14           0 :         tc->nsec = start_tstamp;
      15           0 :         tc->mask = (1ULL << cc->shift) - 1;
      16           0 :         tc->frac = 0;
      17           0 : }
      18             : EXPORT_SYMBOL_GPL(timecounter_init);
      19             : 
      20             : /**
      21             :  * timecounter_read_delta - get nanoseconds since last call of this function
      22             :  * @tc:         Pointer to time counter
      23             :  *
      24             :  * When the underlying cycle counter runs over, this will be handled
      25             :  * correctly as long as it does not run over more than once between
      26             :  * calls.
      27             :  *
      28             :  * The first call to this function for a new time counter initializes
      29             :  * the time tracking and returns an undefined result.
      30             :  */
      31           0 : static u64 timecounter_read_delta(struct timecounter *tc)
      32             : {
      33           0 :         u64 cycle_now, cycle_delta;
      34           0 :         u64 ns_offset;
      35             : 
      36             :         /* read cycle counter: */
      37           0 :         cycle_now = tc->cc->read(tc->cc);
      38             : 
      39             :         /* calculate the delta since the last timecounter_read_delta(): */
      40           0 :         cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
      41             : 
      42             :         /* convert to nanoseconds: */
      43           0 :         ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
      44             :                                         tc->mask, &tc->frac);
      45             : 
      46             :         /* update time stamp of timecounter_read_delta() call: */
      47           0 :         tc->cycle_last = cycle_now;
      48             : 
      49           0 :         return ns_offset;
      50             : }
      51             : 
      52           0 : u64 timecounter_read(struct timecounter *tc)
      53             : {
      54           0 :         u64 nsec;
      55             : 
      56             :         /* increment time by nanoseconds since last call */
      57           0 :         nsec = timecounter_read_delta(tc);
      58           0 :         nsec += tc->nsec;
      59           0 :         tc->nsec = nsec;
      60             : 
      61           0 :         return nsec;
      62             : }
      63             : EXPORT_SYMBOL_GPL(timecounter_read);
      64             : 
      65             : /*
      66             :  * This is like cyclecounter_cyc2ns(), but it is used for computing a
      67             :  * time previous to the time stored in the cycle counter.
      68             :  */
      69           0 : static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
      70             :                                u64 cycles, u64 mask, u64 frac)
      71             : {
      72           0 :         u64 ns = (u64) cycles;
      73             : 
      74           0 :         ns = ((ns * cc->mult) - frac) >> cc->shift;
      75             : 
      76           0 :         return ns;
      77             : }
      78             : 
      79           0 : u64 timecounter_cyc2time(struct timecounter *tc,
      80             :                          u64 cycle_tstamp)
      81             : {
      82           0 :         u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
      83           0 :         u64 nsec = tc->nsec, frac = tc->frac;
      84             : 
      85             :         /*
      86             :          * Instead of always treating cycle_tstamp as more recent
      87             :          * than tc->cycle_last, detect when it is too far in the
      88             :          * future and treat it as old time stamp instead.
      89             :          */
      90           0 :         if (delta > tc->cc->mask / 2) {
      91           0 :                 delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
      92           0 :                 nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
      93             :         } else {
      94           0 :                 nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
      95             :         }
      96             : 
      97           0 :         return nsec;
      98             : }
      99             : EXPORT_SYMBOL_GPL(timecounter_cyc2time);

Generated by: LCOV version 1.14