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
14291429 }
14301430 }
14311431
1432−static inline u64 time_interpolator_get_counter(void)
1432+static inline u64 time_interpolator_get_counter(int writelock)
14331433 {
14341434 unsigned int src = time_interpolator->source;
14351435
@@ -1443,6 +1443,15 @@ static inline u64 time_interpolator_get_counter(void) · 7 unmodified lines
14431443 now = time_interpolator_get_cycles(src);
14441444 if (lcycle && time_after(lcycle, now))
14451445 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+ }
14461455 /* Keep track of the last timer value returned. The use of cmpxchg here
14471456 * will cause contention in an SMP environment.
14481457 */
@@ -1456,7 +1465,7 @@ static inline u64 time_interpolator_get_counter(void) · 7 unmodified lines
14561465 void time_interpolator_reset(void)
14571466 {
14581467 time_interpolator->offset = 0;
1459− time_interpolator->last_counter = time_interpolator_get_counter();
1468+ time_interpolator->last_counter = time_interpolator_get_counter(1);
14601469 }
14611470
14621471 #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
14681477 return 0;
14691478
14701479 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);
14721481 }
14731482
14741483 #define INTERPOLATOR_ADJUST 65536
@@ -1491,7 +1500,7 @@ static void time_interpolator_update(long delta_nsec) · 16 unmodified lines
14911500 * and the tuning logic insures that.
14921501 */
14931502
1494− counter = time_interpolator_get_counter();
1503+ counter = time_interpolator_get_counter(1);
14951504 offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
14961505
14971506 if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)