History

[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.

Alex Williamson committed 21 years ago

Commit 486d46a1 parent 9f4a6dc1 file · +13 −4Browse files

Unified · Split

kernel/timer.c+13−4
@@ -1429,7 +1429,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src) · 1428 unmodified lines
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) · 7 unmodified lines
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 here1455 /* 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) · 7 unmodified lines
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) · 5 unmodified lines
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 655361483#define INTERPOLATOR_ADJUST 65536
@@ -1491,7 +1500,7 @@ static void time_interpolator_update(long delta_nsec) · 16 unmodified lines
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)