@@ -305,24 +305,18 @@ TIMEOUT_PUBLIC void timeouts_del(struct timeouts *T, struct timeout *to) {
305305} /* timeouts_del() */
306306
307307
308- static inline reltime_t timeout_rem (struct timeouts * T , struct timeout * to ) {
309- return to -> expires - T -> curtime ;
310- } /* timeout_rem() */
311-
312-
313- static inline int timeout_wheel (timeout_t timeout ) {
314- /* must be called with timeout != 0, so fls input is nonzero */
315- return (fls (MIN (timeout , TIMEOUT_MAX )) - 1 ) / WHEEL_BIT ;
308+ static inline int timeout_wheel (timeout_t curtime , timeout_t expires ) {
309+ /* must be called with expires > curtime, so fls input is nonzero */
310+ return (fls (MIN (curtime ^ expires , TIMEOUT_MAX )) - 1 ) / WHEEL_BIT ;
316311} /* timeout_wheel() */
317312
318313
319314static inline int timeout_slot (int wheel , timeout_t expires ) {
320- return WHEEL_MASK & ((expires >> (wheel * WHEEL_BIT )) - !! wheel );
315+ return WHEEL_MASK & ((expires >> (wheel * WHEEL_BIT )));
321316} /* timeout_slot() */
322317
323318
324319static void timeouts_sched (struct timeouts * T , struct timeout * to , timeout_t expires ) {
325- timeout_t rem ;
326320 int wheel , slot ;
327321
328322 timeouts_del (T , to );
@@ -332,14 +326,7 @@ static void timeouts_sched(struct timeouts *T, struct timeout *to, timeout_t exp
332326 TO_SET_TIMEOUTS (to , T );
333327
334328 if (expires > T -> curtime ) {
335- rem = timeout_rem (T , to );
336-
337- /* rem is nonzero since:
338- * rem == timeout_rem(T,to),
339- * == to->expires - T->curtime
340- * and above we have expires > T->curtime.
341- */
342- wheel = timeout_wheel (rem );
329+ wheel = timeout_wheel (T -> curtime , expires );
343330 slot = timeout_slot (wheel , to -> expires );
344331
345332 to -> pending = & T -> wheel [wheel ][slot ];
@@ -402,34 +389,26 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
402389 /*
403390 * Calculate the slots expiring in this wheel
404391 *
405- * If the elapsed time is greater than the maximum period of
392+ * Assume that current slot is empty, it's timer either expired or moved to the lower wheel.
393+ * If the elapsed time is greater or equal to the maximum period of
406394 * the wheel, mark every position as expiring.
407395 *
408396 * Otherwise, to determine the expired slots fill in all the
409397 * bits between the last slot processed and the current
410- * slot, inclusive of the last slot. We'll bitwise-AND this
398+ * slot(exclusive, we don't need to check it again) , inclusive of the last slot. We'll bitwise-AND this
411399 * with our pending set below.
412- *
413- * If a wheel rolls over, force a tick of the next higher
414- * wheel.
415400 */
416- if ((elapsed >> (wheel * WHEEL_BIT )) > WHEEL_MAX ) {
401+ if ((elapsed >> (wheel * WHEEL_BIT )) >= WHEEL_MAX ) {
417402 pending = (wheel_t )~WHEEL_C (0 );
418403 } else {
419- wheel_t _elapsed = WHEEL_MASK & ( elapsed >> ( wheel * WHEEL_BIT )) ;
404+ wheel_t _elapsed ;
420405 int oslot , nslot ;
421406
422- /*
423- * TODO: It's likely that at least one of the
424- * following three bit fill operations is redundant
425- * or can be replaced with a simpler operation.
426- */
427407 oslot = WHEEL_MASK & (T -> curtime >> (wheel * WHEEL_BIT ));
428- pending = rotl (((UINT64_C (1 ) << _elapsed ) - 1 ), oslot );
429-
430408 nslot = WHEEL_MASK & (curtime >> (wheel * WHEEL_BIT ));
431- pending |= rotr (rotl (((WHEEL_C (1 ) << _elapsed ) - 1 ), nslot ), _elapsed );
432- pending |= WHEEL_C (1 ) << nslot ;
409+ _elapsed = WHEEL_MASK & (WHEEL_LEN + nslot - oslot );
410+
411+ pending = rotr (rotl (((WHEEL_C (1 ) << _elapsed ) - 1 ), nslot + 1 ), _elapsed );
433412 }
434413
435414 while (pending & T -> pending [wheel ]) {
@@ -441,9 +420,6 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
441420
442421 if (!(0x1 & pending ))
443422 break ; /* break if we didn't wrap around end of wheel */
444-
445- /* if we're continuing, the next wheel must tick at least once */
446- elapsed = MAX (elapsed , (WHEEL_LEN << (wheel * WHEEL_BIT )));
447423 }
448424
449425 T -> curtime = curtime ;
@@ -512,8 +488,8 @@ static timeout_t timeouts_int(struct timeouts *T) {
512488
513489 /* ctz input cannot be zero: T->pending[wheel] is
514490 * nonzero, so rotr() is nonzero. */
515- _timeout = (ctz (rotr (T -> pending [wheel ], slot )) + !!wheel ) << (wheel * WHEEL_BIT );
516- /* +1 to higher order wheels as those timeouts are one rotation in the future (otherwise they'd be on a lower wheel or expired) */
491+ _timeout = (ctz (rotr (T -> pending [wheel ], slot )) + !!( T -> pending [ wheel ] & ( TIMEOUT_C ( 1 ) << slot )) ) << (wheel * WHEEL_BIT );
492+ /* +1 when a timeout greater than TIMEOUT_MAX and wrap in to current slot of the highest wheel */
517493
518494 _timeout -= relmask & T -> curtime ;
519495 /* reduce by how much lower wheels have progressed */
0 commit comments