diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2012-05-12 17:23:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-05-14 18:32:56 -0400 |
commit | 6ff272c9ad65eda219cd975b9da2dbc31cc812ee (patch) | |
tree | 93236fdb1d8f23afe44fc4b7366c1997787cb8cf /include/net | |
parent | 748336087374ca7e5369f310745fa1d3b4a8cbf7 (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.h | 25 |
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 { | |||
133 | struct codel_vars { | 133 | struct 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 | */ |
178 | static void codel_Newton_step(struct codel_vars *vars) | 182 | static 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, |