summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Turner <pjt@google.com>2011-11-07 23:26:33 -0500
committerIngo Molnar <mingo@elte.hu>2011-11-16 02:48:18 -0500
commit56f570e512eeb5b412cb3a62234adc446a8eb32b (patch)
treecabaea188d6e35c077abc34fda40cc83aea9ea37
parentfccfdc6f0d8c83c854eeb6d93aa158f0e551bd49 (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.c33
-rw-r--r--kernel/sched_fair.c15
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
509static struct jump_label_key __cfs_bandwidth_used;
510
511static inline bool cfs_bandwidth_used(void)
512{
513 return static_branch(&__cfs_bandwidth_used);
514}
515
516static 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 */
526static int cfs_bandwidth_used(void)
527{
528 return 1;
529}
530static void account_cfs_bandwidth_used(int enabled, int was_enabled) {}
531#endif /* HAVE_JUMP_LABEL */
532#else /* !CONFIG_CFS_BANDWIDTH */
507static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq) {} 533static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq) {}
508static void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} 534static void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {}
509static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} 535static 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
9204static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota) 9230static 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,
1421static __always_inline void account_cfs_rq_runtime(struct cfs_rq *cfs_rq, 1421static __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
1430static inline int cfs_rq_throttled(struct cfs_rq *cfs_rq) 1430static 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 */
1436static inline int throttled_hierarchy(struct cfs_rq *cfs_rq) 1436static 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
1757static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) 1757static __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 */
1802static void check_enqueue_throttle(struct cfs_rq *cfs_rq) 1805static 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() */
1819static void check_cfs_rq_runtime(struct cfs_rq *cfs_rq) 1825static 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