diff options
author | Paul Turner <pjt@google.com> | 2011-11-07 23:26:33 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-11-16 02:48:18 -0500 |
commit | 56f570e512eeb5b412cb3a62234adc446a8eb32b (patch) | |
tree | cabaea188d6e35c077abc34fda40cc83aea9ea37 | |
parent | fccfdc6f0d8c83c854eeb6d93aa158f0e551bd49 (diff) |
sched: Use jump labels to reduce overhead when bandwidth control is inactive
Now that the linkage of jump-labels has been fixed they show a measurable
improvement in overhead for the enabled-but-unused case.
Workload is:
'taskset -c 0 perf stat --repeat 50 -e instructions,cycles,branches
bash -c "for ((i=0;i<5;i++)); do $(dirname $0)/pipe-test 20000; done"'
There's a speedup for all situations:
instructions cycles branches
-------------------------------------------------------------------------
Intel Westmere
base 806611770 745895590 146765378
+jumplabel 803090165 (-0.44%) 713381840 (-4.36%) 144561130
AMD Barcelona
base 824657415 740055589 148855354
+jumplabel 821056910 (-0.44%) 737558389 (-0.34%) 146635229
Signed-off-by: Paul Turner <pjt@google.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20111108042736.560831357@google.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | kernel/sched.c | 33 | ||||
-rw-r--r-- | kernel/sched_fair.c | 15 |
2 files changed, 43 insertions, 5 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index d6b149ccf925..d9d79a4088c8 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -72,6 +72,7 @@ | |||
72 | #include <linux/ftrace.h> | 72 | #include <linux/ftrace.h> |
73 | #include <linux/slab.h> | 73 | #include <linux/slab.h> |
74 | #include <linux/init_task.h> | 74 | #include <linux/init_task.h> |
75 | #include <linux/jump_label.h> | ||
75 | 76 | ||
76 | #include <asm/tlb.h> | 77 | #include <asm/tlb.h> |
77 | #include <asm/irq_regs.h> | 78 | #include <asm/irq_regs.h> |
@@ -503,7 +504,32 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) | |||
503 | hrtimer_cancel(&cfs_b->period_timer); | 504 | hrtimer_cancel(&cfs_b->period_timer); |
504 | hrtimer_cancel(&cfs_b->slack_timer); | 505 | hrtimer_cancel(&cfs_b->slack_timer); |
505 | } | 506 | } |
506 | #else | 507 | |
508 | #ifdef HAVE_JUMP_LABEL | ||
509 | static struct jump_label_key __cfs_bandwidth_used; | ||
510 | |||
511 | static inline bool cfs_bandwidth_used(void) | ||
512 | { | ||
513 | return static_branch(&__cfs_bandwidth_used); | ||
514 | } | ||
515 | |||
516 | static void account_cfs_bandwidth_used(int enabled, int was_enabled) | ||
517 | { | ||
518 | /* only need to count groups transitioning between enabled/!enabled */ | ||
519 | if (enabled && !was_enabled) | ||
520 | jump_label_inc(&__cfs_bandwidth_used); | ||
521 | else if (!enabled && was_enabled) | ||
522 | jump_label_dec(&__cfs_bandwidth_used); | ||
523 | } | ||
524 | #else /* !HAVE_JUMP_LABEL */ | ||
525 | /* static_branch doesn't help unless supported */ | ||
526 | static int cfs_bandwidth_used(void) | ||
527 | { | ||
528 | return 1; | ||
529 | } | ||
530 | static void account_cfs_bandwidth_used(int enabled, int was_enabled) {} | ||
531 | #endif /* HAVE_JUMP_LABEL */ | ||
532 | #else /* !CONFIG_CFS_BANDWIDTH */ | ||
507 | static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq) {} | 533 | static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq) {} |
508 | static void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} | 534 | static void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} |
509 | static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} | 535 | static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} |
@@ -9203,7 +9229,7 @@ static int __cfs_schedulable(struct task_group *tg, u64 period, u64 runtime); | |||
9203 | 9229 | ||
9204 | static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota) | 9230 | static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota) |
9205 | { | 9231 | { |
9206 | int i, ret = 0, runtime_enabled; | 9232 | int i, ret = 0, runtime_enabled, runtime_was_enabled; |
9207 | struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(tg); | 9233 | struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(tg); |
9208 | 9234 | ||
9209 | if (tg == &root_task_group) | 9235 | if (tg == &root_task_group) |
@@ -9231,6 +9257,9 @@ static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota) | |||
9231 | goto out_unlock; | 9257 | goto out_unlock; |
9232 | 9258 | ||
9233 | runtime_enabled = quota != RUNTIME_INF; | 9259 | runtime_enabled = quota != RUNTIME_INF; |
9260 | runtime_was_enabled = cfs_b->quota != RUNTIME_INF; | ||
9261 | account_cfs_bandwidth_used(runtime_enabled, runtime_was_enabled); | ||
9262 | |||
9234 | raw_spin_lock_irq(&cfs_b->lock); | 9263 | raw_spin_lock_irq(&cfs_b->lock); |
9235 | cfs_b->period = ns_to_ktime(period); | 9264 | cfs_b->period = ns_to_ktime(period); |
9236 | cfs_b->quota = quota; | 9265 | cfs_b->quota = quota; |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index a78ed2736ba7..a608593df243 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -1421,7 +1421,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, | |||
1421 | static __always_inline void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, | 1421 | static __always_inline void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, |
1422 | unsigned long delta_exec) | 1422 | unsigned long delta_exec) |
1423 | { | 1423 | { |
1424 | if (!cfs_rq->runtime_enabled) | 1424 | if (!cfs_bandwidth_used() || !cfs_rq->runtime_enabled) |
1425 | return; | 1425 | return; |
1426 | 1426 | ||
1427 | __account_cfs_rq_runtime(cfs_rq, delta_exec); | 1427 | __account_cfs_rq_runtime(cfs_rq, delta_exec); |
@@ -1429,13 +1429,13 @@ static __always_inline void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, | |||
1429 | 1429 | ||
1430 | static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq) | 1430 | static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq) |
1431 | { | 1431 | { |
1432 | return cfs_rq->throttled; | 1432 | return cfs_bandwidth_used() && cfs_rq->throttled; |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | /* check whether cfs_rq, or any parent, is throttled */ | 1435 | /* check whether cfs_rq, or any parent, is throttled */ |
1436 | static inline int throttled_hierarchy(struct cfs_rq *cfs_rq) | 1436 | static inline int throttled_hierarchy(struct cfs_rq *cfs_rq) |
1437 | { | 1437 | { |
1438 | return cfs_rq->throttle_count; | 1438 | return cfs_bandwidth_used() && cfs_rq->throttle_count; |
1439 | } | 1439 | } |
1440 | 1440 | ||
1441 | /* | 1441 | /* |
@@ -1756,6 +1756,9 @@ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq) | |||
1756 | 1756 | ||
1757 | static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) | 1757 | static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) |
1758 | { | 1758 | { |
1759 | if (!cfs_bandwidth_used()) | ||
1760 | return; | ||
1761 | |||
1759 | if (!cfs_rq->runtime_enabled || cfs_rq->nr_running) | 1762 | if (!cfs_rq->runtime_enabled || cfs_rq->nr_running) |
1760 | return; | 1763 | return; |
1761 | 1764 | ||
@@ -1801,6 +1804,9 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) | |||
1801 | */ | 1804 | */ |
1802 | static void check_enqueue_throttle(struct cfs_rq *cfs_rq) | 1805 | static void check_enqueue_throttle(struct cfs_rq *cfs_rq) |
1803 | { | 1806 | { |
1807 | if (!cfs_bandwidth_used()) | ||
1808 | return; | ||
1809 | |||
1804 | /* an active group must be handled by the update_curr()->put() path */ | 1810 | /* an active group must be handled by the update_curr()->put() path */ |
1805 | if (!cfs_rq->runtime_enabled || cfs_rq->curr) | 1811 | if (!cfs_rq->runtime_enabled || cfs_rq->curr) |
1806 | return; | 1812 | return; |
@@ -1818,6 +1824,9 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq) | |||
1818 | /* conditionally throttle active cfs_rq's from put_prev_entity() */ | 1824 | /* conditionally throttle active cfs_rq's from put_prev_entity() */ |
1819 | static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) | 1825 | static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) |
1820 | { | 1826 | { |
1827 | if (!cfs_bandwidth_used()) | ||
1828 | return; | ||
1829 | |||
1821 | if (likely(!cfs_rq->runtime_enabled || cfs_rq->runtime_remaining > 0)) | 1830 | if (likely(!cfs_rq->runtime_enabled || cfs_rq->runtime_remaining > 0)) |
1822 | return; | 1831 | return; |
1823 | 1832 | ||