Skip to content

Commit

Permalink
codel: use u16 field instead of 31bits for rec_inv_sqrt
Browse files Browse the repository at this point in the history
David pointed out gcc might generate poor code with 31bit fields.

Using u16 is more than enough and permits a better code output.

Also make the code intent more readable using constants, fixed point arithmetic
not being trivial for everybody.

Suggested-by: David Miller <davem@davemloft.net>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed May 14, 2012
1 parent 7483360 commit 6ff272c
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions include/net/codel.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,17 @@ struct codel_params {
struct codel_vars {
u32 count;
u32 lastcount;
bool dropping:1;
u32 rec_inv_sqrt:31;
bool dropping;
u16 rec_inv_sqrt;
codel_time_t first_above_time;
codel_time_t drop_next;
codel_time_t ldelay;
};

#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
/* needed shift to get a Q0.32 number from rec_inv_sqrt */
#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)

/**
* struct codel_stats - contains codel shared variables and stats
* @maxpacket: largest packet we've seen so far
Expand Down Expand Up @@ -173,17 +177,18 @@ static void codel_stats_init(struct codel_stats *stats)
* http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
* new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
*
* Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa)
* Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
*/
static void codel_Newton_step(struct codel_vars *vars)
{
u32 invsqrt = vars->rec_inv_sqrt;
u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31;
u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2);
u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);

val = (val * invsqrt) >> 32;
val >>= 2; /* avoid overflow in following multiply */
val = (val * invsqrt) >> (32 - 2 + 1);

vars->rec_inv_sqrt = val;
vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
}

/*
Expand All @@ -195,7 +200,7 @@ static codel_time_t codel_control_law(codel_time_t t,
codel_time_t interval,
u32 rec_inv_sqrt)
{
return t + reciprocal_divide(interval, rec_inv_sqrt << 1);
return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
}


Expand Down Expand Up @@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
codel_Newton_step(vars);
} else {
vars->count = 1;
vars->rec_inv_sqrt = 0x7fffffff;
vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
}
vars->lastcount = vars->count;
vars->drop_next = codel_control_law(now, params->interval,
Expand Down

0 comments on commit 6ff272c

Please sign in to comment.