Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sched/fair: Introduce and use the vruntime_cmp() and vruntime_op() wrappers for wrapped-signed aritmetics

We have to be careful with vruntime comparisons and subtraction,
due to the possibility of wrapping, so we have macros like:

#define vruntime_gt(field, lse, rse) ({ (s64)((lse)->field - (rse)->field) > 0; })

Which is used like this:

if (vruntime_gt(min_vruntime, se, rse))
se->min_vruntime = rse->min_vruntime;

Replace this with an easier to read pattern that uses the regular
arithmetics operators:

if (vruntime_cmp(se->min_vruntime, ">", rse->min_vruntime))
se->min_vruntime = rse->min_vruntime;

Also replace vruntime subtractions with vruntime_op():

- delta = (s64)(sea->vruntime - seb->vruntime) +
- (s64)(cfs_rqb->zero_vruntime_fi - cfs_rqa->zero_vruntime_fi);
+ delta = vruntime_op(sea->vruntime, "-", seb->vruntime) +
+ vruntime_op(cfs_rqb->zero_vruntime_fi, "-", cfs_rqa->zero_vruntime_fi);

In the vruntime_cmp() and vruntime_op() macros use Use __builtin_strcmp(),
because of __HAVE_ARCH_STRCMP might turn off the compiler optimizations
we rely on here to catch usage bugs.

No change in functionality.

Signed-off-by: Ingo Molnar <mingo@kernel.org>

+51 -15
+51 -15
kernel/sched/fair.c
··· 524 524 * Scheduling class tree data structure manipulation methods: 525 525 */ 526 526 527 + extern void __BUILD_BUG_vruntime_cmp(void); 528 + 529 + /* Use __builtin_strcmp() because of __HAVE_ARCH_STRCMP: */ 530 + 531 + #define vruntime_cmp(A, CMP_STR, B) ({ \ 532 + int __res = 0; \ 533 + \ 534 + if (!__builtin_strcmp(CMP_STR, "<")) { \ 535 + __res = ((s64)((A)-(B)) < 0); \ 536 + } else if (!__builtin_strcmp(CMP_STR, "<=")) { \ 537 + __res = ((s64)((A)-(B)) <= 0); \ 538 + } else if (!__builtin_strcmp(CMP_STR, ">")) { \ 539 + __res = ((s64)((A)-(B)) > 0); \ 540 + } else if (!__builtin_strcmp(CMP_STR, ">=")) { \ 541 + __res = ((s64)((A)-(B)) >= 0); \ 542 + } else { \ 543 + /* Unknown operator throws linker error: */ \ 544 + __BUILD_BUG_vruntime_cmp(); \ 545 + } \ 546 + \ 547 + __res; \ 548 + }) 549 + 550 + extern void __BUILD_BUG_vruntime_op(void); 551 + 552 + #define vruntime_op(A, OP_STR, B) ({ \ 553 + s64 __res = 0; \ 554 + \ 555 + if (!__builtin_strcmp(OP_STR, "-")) { \ 556 + __res = (s64)((A)-(B)); \ 557 + } else { \ 558 + /* Unknown operator throws linker error: */ \ 559 + __BUILD_BUG_vruntime_op(); \ 560 + } \ 561 + \ 562 + __res; \ 563 + }) 564 + 565 + 527 566 static inline __maybe_unused u64 max_vruntime(u64 max_vruntime, u64 vruntime) 528 567 { 529 - s64 delta = (s64)(vruntime - max_vruntime); 530 - if (delta > 0) 568 + if (vruntime_cmp(vruntime, ">", max_vruntime)) 531 569 max_vruntime = vruntime; 532 570 533 571 return max_vruntime; ··· 573 535 574 536 static inline __maybe_unused u64 min_vruntime(u64 min_vruntime, u64 vruntime) 575 537 { 576 - s64 delta = (s64)(vruntime - min_vruntime); 577 - if (delta < 0) 538 + if (vruntime_cmp(vruntime, "<", min_vruntime)) 578 539 min_vruntime = vruntime; 579 540 580 541 return min_vruntime; ··· 586 549 * Tiebreak on vruntime seems unnecessary since it can 587 550 * hardly happen. 588 551 */ 589 - return (s64)(a->deadline - b->deadline) < 0; 552 + return vruntime_cmp(a->deadline, "<", b->deadline); 590 553 } 591 554 592 555 static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se) 593 556 { 594 - return (s64)(se->vruntime - cfs_rq->zero_vruntime); 557 + return vruntime_op(se->vruntime, "-", cfs_rq->zero_vruntime); 595 558 } 596 559 597 560 #define __node_2_se(node) \ ··· 769 732 load += weight; 770 733 } 771 734 772 - return avg >= (s64)(vruntime - cfs_rq->zero_vruntime) * load; 735 + return avg >= vruntime_op(vruntime, "-", cfs_rq->zero_vruntime) * load; 773 736 } 774 737 775 738 int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se) ··· 780 743 static void update_zero_vruntime(struct cfs_rq *cfs_rq) 781 744 { 782 745 u64 vruntime = avg_vruntime(cfs_rq); 783 - s64 delta = (s64)(vruntime - cfs_rq->zero_vruntime); 746 + s64 delta = vruntime_op(vruntime, "-", cfs_rq->zero_vruntime); 784 747 785 748 sum_w_vruntime_update(cfs_rq, delta); 786 749 ··· 807 770 return entity_before(__node_2_se(a), __node_2_se(b)); 808 771 } 809 772 810 - #define vruntime_gt(field, lse, rse) ({ (s64)((lse)->field - (rse)->field) > 0; }) 811 - 812 773 static inline void __min_vruntime_update(struct sched_entity *se, struct rb_node *node) 813 774 { 814 775 if (node) { 815 776 struct sched_entity *rse = __node_2_se(node); 816 - if (vruntime_gt(min_vruntime, se, rse)) 777 + 778 + if (vruntime_cmp(se->min_vruntime, ">", rse->min_vruntime)) 817 779 se->min_vruntime = rse->min_vruntime; 818 780 } 819 781 } ··· 923 887 924 888 static inline bool protect_slice(struct sched_entity *se) 925 889 { 926 - return ((s64)(se->vprot - se->vruntime) > 0); 890 + return vruntime_cmp(se->vruntime, "<", se->vprot); 927 891 } 928 892 929 893 static inline void cancel_protect_slice(struct sched_entity *se) ··· 1060 1024 */ 1061 1025 static bool update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) 1062 1026 { 1063 - if ((s64)(se->vruntime - se->deadline) < 0) 1027 + if (vruntime_cmp(se->vruntime, "<", se->deadline)) 1064 1028 return false; 1065 1029 1066 1030 /* ··· 13329 13293 * zero_vruntime_fi, which would have been updated in prior calls 13330 13294 * to se_fi_update(). 13331 13295 */ 13332 - delta = (s64)(sea->vruntime - seb->vruntime) + 13333 - (s64)(cfs_rqb->zero_vruntime_fi - cfs_rqa->zero_vruntime_fi); 13296 + delta = vruntime_op(sea->vruntime, "-", seb->vruntime) + 13297 + vruntime_op(cfs_rqb->zero_vruntime_fi, "-", cfs_rqa->zero_vruntime_fi); 13334 13298 13335 13299 return delta > 0; 13336 13300 }