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