diff options
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 18 |
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 | ||
1431 | static inline u64 time_interpolator_get_counter(void) | 1432 | static 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) | |||
1455 | void time_interpolator_reset(void) | 1465 | void 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) |