045-codel-use-u16-field-instead-of-31bits-for-rec_inv_sq.patch 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. From 03333931c17d9c62ba4063d4e4fec1578c0729a7 Mon Sep 17 00:00:00 2001
  2. From: Eric Dumazet <eric.dumazet@gmail.com>
  3. Date: Sat, 12 May 2012 21:23:23 +0000
  4. Subject: [PATCH] codel: use u16 field instead of 31bits for rec_inv_sqrt
  5. commit 6ff272c9ad65eda219cd975b9da2dbc31cc812ee upstream.
  6. David pointed out gcc might generate poor code with 31bit fields.
  7. Using u16 is more than enough and permits a better code output.
  8. Also make the code intent more readable using constants, fixed point arithmetic
  9. not being trivial for everybody.
  10. Suggested-by: David Miller <davem@davemloft.net>
  11. Signed-off-by: Eric Dumazet <edumazet@google.com>
  12. Signed-off-by: David S. Miller <davem@davemloft.net>
  13. ---
  14. include/net/codel.h | 25 +++++++++++++++----------
  15. 1 file changed, 15 insertions(+), 10 deletions(-)
  16. --- a/include/net/codel.h
  17. +++ b/include/net/codel.h
  18. @@ -133,13 +133,17 @@ struct codel_params {
  19. struct codel_vars {
  20. u32 count;
  21. u32 lastcount;
  22. - bool dropping:1;
  23. - u32 rec_inv_sqrt:31;
  24. + bool dropping;
  25. + u16 rec_inv_sqrt;
  26. codel_time_t first_above_time;
  27. codel_time_t drop_next;
  28. codel_time_t ldelay;
  29. };
  30. +#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
  31. +/* needed shift to get a Q0.32 number from rec_inv_sqrt */
  32. +#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
  33. +
  34. /**
  35. * struct codel_stats - contains codel shared variables and stats
  36. * @maxpacket: largest packet we've seen so far
  37. @@ -173,17 +177,18 @@ static void codel_stats_init(struct code
  38. * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
  39. * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
  40. *
  41. - * Here, invsqrt is a fixed point number (< 1.0), 31bit mantissa)
  42. + * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
  43. */
  44. static void codel_Newton_step(struct codel_vars *vars)
  45. {
  46. - u32 invsqrt = vars->rec_inv_sqrt;
  47. - u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 31;
  48. - u64 val = (3LL << 31) - ((u64)vars->count * invsqrt2);
  49. + u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
  50. + u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
  51. + u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
  52. - val = (val * invsqrt) >> 32;
  53. + val >>= 2; /* avoid overflow in following multiply */
  54. + val = (val * invsqrt) >> (32 - 2 + 1);
  55. - vars->rec_inv_sqrt = val;
  56. + vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
  57. }
  58. /*
  59. @@ -195,7 +200,7 @@ static codel_time_t codel_control_law(co
  60. codel_time_t interval,
  61. u32 rec_inv_sqrt)
  62. {
  63. - return t + reciprocal_divide(interval, rec_inv_sqrt << 1);
  64. + return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
  65. }
  66. @@ -326,7 +331,7 @@ static struct sk_buff *codel_dequeue(str
  67. codel_Newton_step(vars);
  68. } else {
  69. vars->count = 1;
  70. - vars->rec_inv_sqrt = 0x7fffffff;
  71. + vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
  72. }
  73. vars->lastcount = vars->count;
  74. vars->drop_next = codel_control_law(now, params->interval,