aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/timer.c')
-rw-r--r--kernel/timer.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index 1433d87f46b3..13e2b513be01 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1429,7 +1429,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src)
1429 } 1429 }
1430} 1430}
1431 1431
1432static inline u64 time_interpolator_get_counter(void) 1432static inline u64 time_interpolator_get_counter(int writelock)
1433{ 1433{
1434 unsigned int src = time_interpolator->source; 1434 unsigned int src = time_interpolator->source;
1435 1435
@@ -1443,6 +1443,15 @@ static inline u64 time_interpolator_get_counter(void)
1443 now = time_interpolator_get_cycles(src); 1443 now = time_interpolator_get_cycles(src);
1444 if (lcycle && time_after(lcycle, now)) 1444 if (lcycle && time_after(lcycle, now))
1445 return lcycle; 1445 return lcycle;
1446
1447 /* When holding the xtime write lock, there's no need
1448 * to add the overhead of the cmpxchg. Readers are
1449 * force to retry until the write lock is released.
1450 */
1451 if (writelock) {
1452 time_interpolator->last_cycle = now;
1453 return now;
1454 }
1446 /* Keep track of the last timer value returned. The use of cmpxchg here 1455 /* Keep track of the last timer value returned. The use of cmpxchg here
1447 * will cause contention in an SMP environment. 1456 * will cause contention in an SMP environment.
1448 */ 1457 */
@@ -1456,7 +1465,7 @@ static inline u64 time_interpolator_get_counter(void)
1456void time_interpolator_reset(void) 1465void time_interpolator_reset(void)
1457{ 1466{
1458 time_interpolator->offset = 0; 1467 time_interpolator->offset = 0;
1459 time_interpolator->last_counter = time_interpolator_get_counter(); 1468 time_interpolator->last_counter = time_interpolator_get_counter(1);
1460} 1469}
1461 1470
1462#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift) 1471#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)
1468 return 0; 1477 return 0;
1469 1478
1470 return time_interpolator->offset + 1479 return time_interpolator->offset +
1471 GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator); 1480 GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
1472} 1481}
1473 1482
1474#define INTERPOLATOR_ADJUST 65536 1483#define INTERPOLATOR_ADJUST 65536
@@ -1491,7 +1500,7 @@ static void time_interpolator_update(long delta_nsec)
1491 * and the tuning logic insures that. 1500 * and the tuning logic insures that.
1492 */ 1501 */
1493 1502
1494 counter = time_interpolator_get_counter(); 1503 counter = time_interpolator_get_counter(1);
1495 offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator); 1504 offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
1496 1505
1497 if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) 1506 if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)