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) |
