diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 5470ab0258a8..b0afd8db1396 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -638,6 +638,11 @@ static u64 div64_likely32(u64 divident, unsigned long divisor) | |||
638 | 638 | ||
639 | #define WMULT_SHIFT 32 | 639 | #define WMULT_SHIFT 32 |
640 | 640 | ||
641 | /* | ||
642 | * Shift right and round: | ||
643 | */ | ||
644 | #define RSR(x, y) (((x) + (1UL << ((y) - 1))) >> (y)) | ||
645 | |||
641 | static unsigned long | 646 | static unsigned long |
642 | calc_delta_mine(unsigned long delta_exec, unsigned long weight, | 647 | calc_delta_mine(unsigned long delta_exec, unsigned long weight, |
643 | struct load_weight *lw) | 648 | struct load_weight *lw) |
@@ -645,18 +650,17 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight, | |||
645 | u64 tmp; | 650 | u64 tmp; |
646 | 651 | ||
647 | if (unlikely(!lw->inv_weight)) | 652 | if (unlikely(!lw->inv_weight)) |
648 | lw->inv_weight = WMULT_CONST / lw->weight; | 653 | lw->inv_weight = (WMULT_CONST - lw->weight/2) / lw->weight + 1; |
649 | 654 | ||
650 | tmp = (u64)delta_exec * weight; | 655 | tmp = (u64)delta_exec * weight; |
651 | /* | 656 | /* |
652 | * Check whether we'd overflow the 64-bit multiplication: | 657 | * Check whether we'd overflow the 64-bit multiplication: |
653 | */ | 658 | */ |
654 | if (unlikely(tmp > WMULT_CONST)) { | 659 | if (unlikely(tmp > WMULT_CONST)) |
655 | tmp = ((tmp >> WMULT_SHIFT/2) * lw->inv_weight) | 660 | tmp = RSR(RSR(tmp, WMULT_SHIFT/2) * lw->inv_weight, |
656 | >> (WMULT_SHIFT/2); | 661 | WMULT_SHIFT/2); |
657 | } else { | 662 | else |
658 | tmp = (tmp * lw->inv_weight) >> WMULT_SHIFT; | 663 | tmp = RSR(tmp * lw->inv_weight, WMULT_SHIFT); |
659 | } | ||
660 | 664 | ||
661 | return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX); | 665 | return (unsigned long)min(tmp, (u64)(unsigned long)LONG_MAX); |
662 | } | 666 | } |