aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@hp.com>2005-09-06 18:17:04 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:24 -0400
commit486d46aefe7ded0d343e306be740edd972aff740 (patch)
treee750143e578503b77a66eff21595b16730506802 /kernel
parent9f4a6dce10941380ad7365cc9b0ef038ed56cbf9 (diff)
[PATCH] optimize writer path in time_interpolator_get_counter()
Christoph Lameter <clameter@engr.sgi.com> When using a time interpolator that is susceptible to jitter there's potentially contention over a cmpxchg used to prevent time from going backwards. This is unnecessary when the caller holds the xtime write seqlock as all readers will be blocked from returning until the write is complete. We can therefore allow writers to insert a new value and exit rather than fight with CPUs who only hold a reader lock. Signed-off-by: Alex Williamson <alex.williamson@hp.com> Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-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)