Commit 6ff272c9 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

codel: use u16 field instead of 31bits for rec_inv_sqrt

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: default avatarDavid Miller <davem@davemloft.net>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 74833608
...@@ -133,13 +133,17 @@ struct codel_params { ...@@ -133,13 +133,17 @@ struct codel_params {
struct codel_vars { struct codel_vars {
u32 count; u32 count;
u32 lastcount; u32 lastcount;
bool dropping:1; bool dropping;
u32 rec_inv_sqrt:31; u16 rec_inv_sqrt;
codel_time_t first_above_time; codel_time_t first_above_time;
codel_time_t drop_next; codel_time_t drop_next;
codel_time_t ldelay; 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 * struct codel_stats - contains codel shared variables and stats
* @maxpacket: largest packet we've seen so far * @maxpacket: largest packet we've seen so far
...@@ -173,17 +177,18 @@ static void codel_stats_init(struct codel_stats *stats) ...@@ -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 * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
* new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) * 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) static void codel_Newton_step(struct codel_vars *vars)
{ {
u32 invsqrt = vars->rec_inv_sqrt; u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31; u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2); 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;
} }
/* /*
...@@ -195,7 +200,7 @@ static codel_time_t codel_control_law(codel_time_t t, ...@@ -195,7 +200,7 @@ static codel_time_t codel_control_law(codel_time_t t,
codel_time_t interval, codel_time_t interval,
u32 rec_inv_sqrt) 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);
} }
...@@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch, ...@@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
codel_Newton_step(vars); codel_Newton_step(vars);
} else { } else {
vars->count = 1; vars->count = 1;
vars->rec_inv_sqrt = 0x7fffffff; vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
} }
vars->lastcount = vars->count; vars->lastcount = vars->count;
vars->drop_next = codel_control_law(now, params->interval, vars->drop_next = codel_control_law(now, params->interval,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment