aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/timer.c')
-rw-r--r--kernel/timer.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index 5377f40723ff..13e2b513be01 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -950,6 +950,7 @@ void do_timer(struct pt_regs *regs)
950{ 950{
951 jiffies_64++; 951 jiffies_64++;
952 update_times(); 952 update_times();
953 softlockup_tick(regs);
953} 954}
954 955
955#ifdef __ARCH_WANT_SYS_ALARM 956#ifdef __ARCH_WANT_SYS_ALARM
@@ -1428,7 +1429,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src)
1428 } 1429 }
1429} 1430}
1430 1431
1431static inline u64 time_interpolator_get_counter(void) 1432static inline u64 time_interpolator_get_counter(int writelock)
1432{ 1433{
1433 unsigned int src = time_interpolator->source; 1434 unsigned int src = time_interpolator->source;
1434 1435
@@ -1442,6 +1443,15 @@ static inline u64 time_interpolator_get_counter(void)
1442 now = time_interpolator_get_cycles(src); 1443 now = time_interpolator_get_cycles(src);
1443 if (lcycle && time_after(lcycle, now)) 1444 if (lcycle && time_after(lcycle, now))
1444 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 }
1445 /* 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
1446 * will cause contention in an SMP environment. 1456 * will cause contention in an SMP environment.
1447 */ 1457 */
@@ -1455,7 +1465,7 @@ static inline u64 time_interpolator_get_counter(void)
1455void time_interpolator_reset(void) 1465void time_interpolator_reset(void)
1456{ 1466{
1457 time_interpolator->offset = 0; 1467 time_interpolator->offset = 0;
1458 time_interpolator->last_counter = time_interpolator_get_counter(); 1468 time_interpolator->last_counter = time_interpolator_get_counter(1);
1459} 1469}
1460 1470
1461#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)
@@ -1467,7 +1477,7 @@ unsigned long time_interpolator_get_offset(void)
1467 return 0; 1477 return 0;
1468 1478
1469 return time_interpolator->offset + 1479 return time_interpolator->offset +
1470 GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator); 1480 GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
1471} 1481}
1472 1482
1473#define INTERPOLATOR_ADJUST 65536 1483#define INTERPOLATOR_ADJUST 65536
@@ -1490,7 +1500,7 @@ static void time_interpolator_update(long delta_nsec)
1490 * and the tuning logic insures that. 1500 * and the tuning logic insures that.
1491 */ 1501 */
1492 1502
1493 counter = time_interpolator_get_counter(); 1503 counter = time_interpolator_get_counter(1);
1494 offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator); 1504 offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
1495 1505
1496 if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) 1506 if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)