|
@@ -1429,7 +1429,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static inline u64 time_interpolator_get_counter(void)
|
|
|
|
|
|
+static inline u64 time_interpolator_get_counter(int writelock)
|
|
{
|
|
{
|
|
unsigned int src = time_interpolator->source;
|
|
unsigned int src = time_interpolator->source;
|
|
|
|
|
|
@@ -1443,6 +1443,15 @@ static inline u64 time_interpolator_get_counter(void)
|
|
now = time_interpolator_get_cycles(src);
|
|
now = time_interpolator_get_cycles(src);
|
|
if (lcycle && time_after(lcycle, now))
|
|
if (lcycle && time_after(lcycle, now))
|
|
return lcycle;
|
|
return lcycle;
|
|
|
|
+
|
|
|
|
+ /* When holding the xtime write lock, there's no need
|
|
|
|
+ * to add the overhead of the cmpxchg. Readers are
|
|
|
|
+ * force to retry until the write lock is released.
|
|
|
|
+ */
|
|
|
|
+ if (writelock) {
|
|
|
|
+ time_interpolator->last_cycle = now;
|
|
|
|
+ return now;
|
|
|
|
+ }
|
|
/* Keep track of the last timer value returned. The use of cmpxchg here
|
|
/* Keep track of the last timer value returned. The use of cmpxchg here
|
|
* will cause contention in an SMP environment.
|
|
* will cause contention in an SMP environment.
|
|
*/
|
|
*/
|
|
@@ -1456,7 +1465,7 @@ static inline u64 time_interpolator_get_counter(void)
|
|
void time_interpolator_reset(void)
|
|
void time_interpolator_reset(void)
|
|
{
|
|
{
|
|
time_interpolator->offset = 0;
|
|
time_interpolator->offset = 0;
|
|
- time_interpolator->last_counter = time_interpolator_get_counter();
|
|
|
|
|
|
+ time_interpolator->last_counter = time_interpolator_get_counter(1);
|
|
}
|
|
}
|
|
|
|
|
|
#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
|
|
#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
|
|
@@ -1468,7 +1477,7 @@ unsigned long time_interpolator_get_offset(void)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
return time_interpolator->offset +
|
|
return time_interpolator->offset +
|
|
- GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
|
|
|
|
|
|
+ GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
|
|
}
|
|
}
|
|
|
|
|
|
#define INTERPOLATOR_ADJUST 65536
|
|
#define INTERPOLATOR_ADJUST 65536
|
|
@@ -1491,7 +1500,7 @@ static void time_interpolator_update(long delta_nsec)
|
|
* and the tuning logic insures that.
|
|
* and the tuning logic insures that.
|
|
*/
|
|
*/
|
|
|
|
|
|
- counter = time_interpolator_get_counter();
|
|
|
|
|
|
+ counter = time_interpolator_get_counter(1);
|
|
offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
|
|
offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
|
|
|
|
|
|
if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
|
|
if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
|