aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2012-05-12 17:23:23 -0400
committerDavid S. Miller <davem@davemloft.net>2012-05-14 18:32:56 -0400
commit6ff272c9ad65eda219cd975b9da2dbc31cc812ee (patch)
tree93236fdb1d8f23afe44fc4b7366c1997787cb8cf /include/net
parent748336087374ca7e5369f310745fa1d3b4a8cbf7 (diff)
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: David Miller <davem@davemloft.net> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/codel.h25
1 files changed, 15 insertions, 10 deletions
diff --git a/include/net/codel.h b/include/net/codel.h
index bd8747c3ba69..7546517326b5 100644
--- a/include/net/codel.h
+++ b/include/net/codel.h
@@ -133,13 +133,17 @@ struct codel_params {
133struct codel_vars { 133struct codel_vars {
134 u32 count; 134 u32 count;
135 u32 lastcount; 135 u32 lastcount;
136 bool dropping:1; 136 bool dropping;
137 u32 rec_inv_sqrt:31; 137 u16 rec_inv_sqrt;
138 codel_time_t first_above_time; 138 codel_time_t first_above_time;
139 codel_time_t drop_next; 139 codel_time_t drop_next;
140 codel_time_t ldelay; 140 codel_time_t ldelay;
141}; 141};
142 142
143#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
144/* needed shift to get a Q0.32 number from rec_inv_sqrt */
145#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
146
143/** 147/**
144 * struct codel_stats - contains codel shared variables and stats 148 * struct codel_stats - contains codel shared variables and stats
145 * @maxpacket: largest packet we've seen so far 149 * @maxpacket: largest packet we've seen so far
@@ -173,17 +177,18 @@ static void codel_stats_init(struct codel_stats *stats)
173 * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots 177 * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
174 * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) 178 * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
175 * 179 *
176 * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa) 180 * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
177 */ 181 */
178static void codel_Newton_step(struct codel_vars *vars) 182static void codel_Newton_step(struct codel_vars *vars)
179{ 183{
180 u32 invsqrt = vars->rec_inv_sqrt; 184 u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
181 u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31; 185 u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
182 u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2); 186 u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
183 187
184 val = (val * invsqrt) >> 32; 188 val >>= 2; /* avoid overflow in following multiply */
189 val = (val * invsqrt) >> (32 - 2 + 1);
185 190
186 vars->rec_inv_sqrt = val; 191 vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
187} 192}
188 193
189/* 194/*
@@ -195,7 +200,7 @@ static codel_time_t codel_control_law(codel_time_t t,
195 codel_time_t interval, 200 codel_time_t interval,
196 u32 rec_inv_sqrt) 201 u32 rec_inv_sqrt)
197{ 202{
198 return t + reciprocal_divide(interval, rec_inv_sqrt << 1); 203 return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
199} 204}
200 205
201 206
@@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
326 codel_Newton_step(vars); 331 codel_Newton_step(vars);
327 } else { 332 } else {
328 vars->count = 1; 333 vars->count = 1;
329 vars->rec_inv_sqrt = 0x7fffffff; 334 vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
330 } 335 }
331 vars->lastcount = vars->count; 336 vars->lastcount = vars->count;
332 vars->drop_next = codel_control_law(now, params->interval, 337 vars->drop_next = codel_control_law(now, params->interval,