diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/exit.c | 4 | ||||
-rw-r--r-- | kernel/fork.c | 7 | ||||
-rw-r--r-- | kernel/hrtimer.c | 95 | ||||
-rw-r--r-- | kernel/printk.c | 14 | ||||
-rw-r--r-- | kernel/sched.c | 130 | ||||
-rw-r--r-- | kernel/sched_fair.c | 3 | ||||
-rw-r--r-- | kernel/sched_rt.c | 2 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 47 |
8 files changed, 289 insertions, 13 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index f2b321bae440..64879bdff921 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -57,6 +57,8 @@ | |||
57 | #include <asm/pgtable.h> | 57 | #include <asm/pgtable.h> |
58 | #include <asm/mmu_context.h> | 58 | #include <asm/mmu_context.h> |
59 | 59 | ||
60 | extern void exit_od_table(struct task_struct *t); | ||
61 | |||
60 | static void exit_mm(struct task_struct * tsk); | 62 | static void exit_mm(struct task_struct * tsk); |
61 | 63 | ||
62 | static void __unhash_process(struct task_struct *p, bool group_dead) | 64 | static void __unhash_process(struct task_struct *p, bool group_dead) |
@@ -980,6 +982,8 @@ NORET_TYPE void do_exit(long code) | |||
980 | if (unlikely(tsk->audit_context)) | 982 | if (unlikely(tsk->audit_context)) |
981 | audit_free(tsk); | 983 | audit_free(tsk); |
982 | 984 | ||
985 | exit_od_table(tsk); | ||
986 | |||
983 | tsk->exit_code = code; | 987 | tsk->exit_code = code; |
984 | taskstats_exit(tsk, group_dead); | 988 | taskstats_exit(tsk, group_dead); |
985 | 989 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 0276c30401a0..25c6111fe3a6 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -77,6 +77,9 @@ | |||
77 | 77 | ||
78 | #include <trace/events/sched.h> | 78 | #include <trace/events/sched.h> |
79 | 79 | ||
80 | #include <litmus/litmus.h> | ||
81 | #include <litmus/sched_plugin.h> | ||
82 | |||
80 | /* | 83 | /* |
81 | * Protected counters by write_lock_irq(&tasklist_lock) | 84 | * Protected counters by write_lock_irq(&tasklist_lock) |
82 | */ | 85 | */ |
@@ -191,6 +194,7 @@ void __put_task_struct(struct task_struct *tsk) | |||
191 | WARN_ON(atomic_read(&tsk->usage)); | 194 | WARN_ON(atomic_read(&tsk->usage)); |
192 | WARN_ON(tsk == current); | 195 | WARN_ON(tsk == current); |
193 | 196 | ||
197 | exit_litmus(tsk); | ||
194 | exit_creds(tsk); | 198 | exit_creds(tsk); |
195 | delayacct_tsk_free(tsk); | 199 | delayacct_tsk_free(tsk); |
196 | put_signal_struct(tsk->signal); | 200 | put_signal_struct(tsk->signal); |
@@ -275,6 +279,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
275 | 279 | ||
276 | tsk->stack = ti; | 280 | tsk->stack = ti; |
277 | 281 | ||
282 | /* Don't let the new task be a real-time task. */ | ||
283 | litmus_fork(tsk); | ||
284 | |||
278 | err = prop_local_init_single(&tsk->dirties); | 285 | err = prop_local_init_single(&tsk->dirties); |
279 | if (err) | 286 | if (err) |
280 | goto out; | 287 | goto out; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index a9205e32a059..11e896903828 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include <linux/sched.h> | 46 | #include <linux/sched.h> |
47 | #include <linux/timer.h> | 47 | #include <linux/timer.h> |
48 | 48 | ||
49 | #include <litmus/litmus.h> | ||
50 | |||
49 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
50 | 52 | ||
51 | #include <trace/events/timer.h> | 53 | #include <trace/events/timer.h> |
@@ -1026,6 +1028,98 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
1026 | } | 1028 | } |
1027 | EXPORT_SYMBOL_GPL(hrtimer_start); | 1029 | EXPORT_SYMBOL_GPL(hrtimer_start); |
1028 | 1030 | ||
1031 | #ifdef CONFIG_ARCH_HAS_SEND_PULL_TIMERS | ||
1032 | |||
1033 | /** | ||
1034 | * hrtimer_start_on_info_init - Initialize hrtimer_start_on_info | ||
1035 | */ | ||
1036 | void hrtimer_start_on_info_init(struct hrtimer_start_on_info *info) | ||
1037 | { | ||
1038 | memset(info, 0, sizeof(struct hrtimer_start_on_info)); | ||
1039 | atomic_set(&info->state, HRTIMER_START_ON_INACTIVE); | ||
1040 | } | ||
1041 | |||
1042 | /** | ||
1043 | * hrtimer_pull - PULL_TIMERS_VECTOR callback on remote cpu | ||
1044 | */ | ||
1045 | void hrtimer_pull(void) | ||
1046 | { | ||
1047 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | ||
1048 | struct hrtimer_start_on_info *info; | ||
1049 | struct list_head *pos, *safe, list; | ||
1050 | |||
1051 | raw_spin_lock(&base->lock); | ||
1052 | list_replace_init(&base->to_pull, &list); | ||
1053 | raw_spin_unlock(&base->lock); | ||
1054 | |||
1055 | list_for_each_safe(pos, safe, &list) { | ||
1056 | info = list_entry(pos, struct hrtimer_start_on_info, list); | ||
1057 | TRACE("pulled timer 0x%x\n", info->timer); | ||
1058 | list_del(pos); | ||
1059 | hrtimer_start(info->timer, info->time, info->mode); | ||
1060 | } | ||
1061 | } | ||
1062 | |||
1063 | /** | ||
1064 | * hrtimer_start_on - trigger timer arming on remote cpu | ||
1065 | * @cpu: remote cpu | ||
1066 | * @info: save timer information for enqueuing on remote cpu | ||
1067 | * @timer: timer to be pulled | ||
1068 | * @time: expire time | ||
1069 | * @mode: timer mode | ||
1070 | */ | ||
1071 | int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, | ||
1072 | struct hrtimer *timer, ktime_t time, | ||
1073 | const enum hrtimer_mode mode) | ||
1074 | { | ||
1075 | unsigned long flags; | ||
1076 | struct hrtimer_cpu_base* base; | ||
1077 | int in_use = 0, was_empty; | ||
1078 | |||
1079 | /* serialize access to info through the timer base */ | ||
1080 | lock_hrtimer_base(timer, &flags); | ||
1081 | |||
1082 | in_use = (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE); | ||
1083 | if (!in_use) { | ||
1084 | INIT_LIST_HEAD(&info->list); | ||
1085 | info->timer = timer; | ||
1086 | info->time = time; | ||
1087 | info->mode = mode; | ||
1088 | /* mark as in use */ | ||
1089 | atomic_set(&info->state, HRTIMER_START_ON_QUEUED); | ||
1090 | } | ||
1091 | |||
1092 | unlock_hrtimer_base(timer, &flags); | ||
1093 | |||
1094 | if (!in_use) { | ||
1095 | /* initiate pull */ | ||
1096 | preempt_disable(); | ||
1097 | if (cpu == smp_processor_id()) { | ||
1098 | /* start timer locally; we may get called | ||
1099 | * with rq->lock held, do not wake up anything | ||
1100 | */ | ||
1101 | TRACE("hrtimer_start_on: starting on local CPU\n"); | ||
1102 | __hrtimer_start_range_ns(info->timer, info->time, | ||
1103 | 0, info->mode, 0); | ||
1104 | } else { | ||
1105 | TRACE("hrtimer_start_on: pulling to remote CPU\n"); | ||
1106 | base = &per_cpu(hrtimer_bases, cpu); | ||
1107 | raw_spin_lock_irqsave(&base->lock, flags); | ||
1108 | was_empty = list_empty(&base->to_pull); | ||
1109 | list_add(&info->list, &base->to_pull); | ||
1110 | raw_spin_unlock_irqrestore(&base->lock, flags); | ||
1111 | if (was_empty) | ||
1112 | /* only send IPI if other no else | ||
1113 | * has done so already | ||
1114 | */ | ||
1115 | smp_send_pull_timers(cpu); | ||
1116 | } | ||
1117 | preempt_enable(); | ||
1118 | } | ||
1119 | return in_use; | ||
1120 | } | ||
1121 | |||
1122 | #endif | ||
1029 | 1123 | ||
1030 | /** | 1124 | /** |
1031 | * hrtimer_try_to_cancel - try to deactivate a timer | 1125 | * hrtimer_try_to_cancel - try to deactivate a timer |
@@ -1625,6 +1719,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu) | |||
1625 | } | 1719 | } |
1626 | 1720 | ||
1627 | hrtimer_init_hres(cpu_base); | 1721 | hrtimer_init_hres(cpu_base); |
1722 | INIT_LIST_HEAD(&cpu_base->to_pull); | ||
1628 | } | 1723 | } |
1629 | 1724 | ||
1630 | #ifdef CONFIG_HOTPLUG_CPU | 1725 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/kernel/printk.c b/kernel/printk.c index 35185392173f..b799a2ee96e5 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -70,6 +70,13 @@ int console_printk[4] = { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * divert printk() messages when there is a LITMUS^RT debug listener | ||
74 | */ | ||
75 | #include <litmus/litmus.h> | ||
76 | int trace_override = 0; | ||
77 | int trace_recurse = 0; | ||
78 | |||
79 | /* | ||
73 | * Low level drivers may need that to know if they can schedule in | 80 | * Low level drivers may need that to know if they can schedule in |
74 | * their unblank() callback or not. So let's export it. | 81 | * their unblank() callback or not. So let's export it. |
75 | */ | 82 | */ |
@@ -871,6 +878,9 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
871 | /* Emit the output into the temporary buffer */ | 878 | /* Emit the output into the temporary buffer */ |
872 | printed_len += vscnprintf(printk_buf + printed_len, | 879 | printed_len += vscnprintf(printk_buf + printed_len, |
873 | sizeof(printk_buf) - printed_len, fmt, args); | 880 | sizeof(printk_buf) - printed_len, fmt, args); |
881 | /* if LITMUS^RT tracer is active divert printk() msgs */ | ||
882 | if (trace_override && !trace_recurse) | ||
883 | TRACE("%s", printk_buf); | ||
874 | 884 | ||
875 | p = printk_buf; | 885 | p = printk_buf; |
876 | 886 | ||
@@ -947,7 +957,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
947 | * Try to acquire and then immediately release the | 957 | * Try to acquire and then immediately release the |
948 | * console semaphore. The release will do all the | 958 | * console semaphore. The release will do all the |
949 | * actual magic (print out buffers, wake up klogd, | 959 | * actual magic (print out buffers, wake up klogd, |
950 | * etc). | 960 | * etc). |
951 | * | 961 | * |
952 | * The console_trylock_for_printk() function | 962 | * The console_trylock_for_printk() function |
953 | * will release 'logbuf_lock' regardless of whether it | 963 | * will release 'logbuf_lock' regardless of whether it |
@@ -1220,7 +1230,7 @@ int printk_needs_cpu(int cpu) | |||
1220 | 1230 | ||
1221 | void wake_up_klogd(void) | 1231 | void wake_up_klogd(void) |
1222 | { | 1232 | { |
1223 | if (waitqueue_active(&log_wait)) | 1233 | if (!trace_override && waitqueue_active(&log_wait)) |
1224 | this_cpu_write(printk_pending, 1); | 1234 | this_cpu_write(printk_pending, 1); |
1225 | } | 1235 | } |
1226 | 1236 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index fde6ff903525..935f8e8e6160 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -80,6 +80,11 @@ | |||
80 | #include "workqueue_sched.h" | 80 | #include "workqueue_sched.h" |
81 | #include "sched_autogroup.h" | 81 | #include "sched_autogroup.h" |
82 | 82 | ||
83 | #include <litmus/sched_trace.h> | ||
84 | #include <litmus/trace.h> | ||
85 | |||
86 | static void litmus_tick(struct rq*, struct task_struct*); | ||
87 | |||
83 | #define CREATE_TRACE_POINTS | 88 | #define CREATE_TRACE_POINTS |
84 | #include <trace/events/sched.h> | 89 | #include <trace/events/sched.h> |
85 | 90 | ||
@@ -410,6 +415,12 @@ struct rt_rq { | |||
410 | #endif | 415 | #endif |
411 | }; | 416 | }; |
412 | 417 | ||
418 | /* Litmus related fields in a runqueue */ | ||
419 | struct litmus_rq { | ||
420 | unsigned long nr_running; | ||
421 | struct task_struct *prev; | ||
422 | }; | ||
423 | |||
413 | #ifdef CONFIG_SMP | 424 | #ifdef CONFIG_SMP |
414 | 425 | ||
415 | /* | 426 | /* |
@@ -475,6 +486,7 @@ struct rq { | |||
475 | 486 | ||
476 | struct cfs_rq cfs; | 487 | struct cfs_rq cfs; |
477 | struct rt_rq rt; | 488 | struct rt_rq rt; |
489 | struct litmus_rq litmus; | ||
478 | 490 | ||
479 | #ifdef CONFIG_FAIR_GROUP_SCHED | 491 | #ifdef CONFIG_FAIR_GROUP_SCHED |
480 | /* list of leaf cfs_rq on this cpu: */ | 492 | /* list of leaf cfs_rq on this cpu: */ |
@@ -1045,6 +1057,7 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer) | |||
1045 | raw_spin_lock(&rq->lock); | 1057 | raw_spin_lock(&rq->lock); |
1046 | update_rq_clock(rq); | 1058 | update_rq_clock(rq); |
1047 | rq->curr->sched_class->task_tick(rq, rq->curr, 1); | 1059 | rq->curr->sched_class->task_tick(rq, rq->curr, 1); |
1060 | litmus_tick(rq, rq->curr); | ||
1048 | raw_spin_unlock(&rq->lock); | 1061 | raw_spin_unlock(&rq->lock); |
1049 | 1062 | ||
1050 | return HRTIMER_NORESTART; | 1063 | return HRTIMER_NORESTART; |
@@ -1773,7 +1786,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) | |||
1773 | 1786 | ||
1774 | static const struct sched_class rt_sched_class; | 1787 | static const struct sched_class rt_sched_class; |
1775 | 1788 | ||
1776 | #define sched_class_highest (&stop_sched_class) | 1789 | #define sched_class_highest (&litmus_sched_class) |
1777 | #define for_each_class(class) \ | 1790 | #define for_each_class(class) \ |
1778 | for (class = sched_class_highest; class; class = class->next) | 1791 | for (class = sched_class_highest; class; class = class->next) |
1779 | 1792 | ||
@@ -2031,6 +2044,7 @@ static void update_rq_clock_task(struct rq *rq, s64 delta) | |||
2031 | #include "sched_rt.c" | 2044 | #include "sched_rt.c" |
2032 | #include "sched_autogroup.c" | 2045 | #include "sched_autogroup.c" |
2033 | #include "sched_stoptask.c" | 2046 | #include "sched_stoptask.c" |
2047 | #include "../litmus/sched_litmus.c" | ||
2034 | #ifdef CONFIG_SCHED_DEBUG | 2048 | #ifdef CONFIG_SCHED_DEBUG |
2035 | # include "sched_debug.c" | 2049 | # include "sched_debug.c" |
2036 | #endif | 2050 | #endif |
@@ -2153,6 +2167,10 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags) | |||
2153 | * A queue event has occurred, and we're going to schedule. In | 2167 | * A queue event has occurred, and we're going to schedule. In |
2154 | * this case, we can save a useless back to back clock update. | 2168 | * this case, we can save a useless back to back clock update. |
2155 | */ | 2169 | */ |
2170 | /* LITMUS^RT: | ||
2171 | * The "disable-clock-update" approach was buggy in Linux 2.6.36. | ||
2172 | * The issue has been solved in 2.6.37. | ||
2173 | */ | ||
2156 | if (rq->curr->on_rq && test_tsk_need_resched(rq->curr)) | 2174 | if (rq->curr->on_rq && test_tsk_need_resched(rq->curr)) |
2157 | rq->skip_clock_update = 1; | 2175 | rq->skip_clock_update = 1; |
2158 | } | 2176 | } |
@@ -2676,6 +2694,9 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) | |||
2676 | unsigned long flags; | 2694 | unsigned long flags; |
2677 | int cpu, success = 0; | 2695 | int cpu, success = 0; |
2678 | 2696 | ||
2697 | if (is_realtime(p)) | ||
2698 | TRACE_TASK(p, "try_to_wake_up() state:%d\n", p->state); | ||
2699 | |||
2679 | smp_wmb(); | 2700 | smp_wmb(); |
2680 | raw_spin_lock_irqsave(&p->pi_lock, flags); | 2701 | raw_spin_lock_irqsave(&p->pi_lock, flags); |
2681 | if (!(p->state & state)) | 2702 | if (!(p->state & state)) |
@@ -2712,6 +2733,12 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) | |||
2712 | */ | 2733 | */ |
2713 | smp_rmb(); | 2734 | smp_rmb(); |
2714 | 2735 | ||
2736 | /* LITMUS^RT: once the task can be safely referenced by this | ||
2737 | * CPU, don't mess up with Linux load balancing stuff. | ||
2738 | */ | ||
2739 | if (is_realtime(p)) | ||
2740 | goto litmus_out_activate; | ||
2741 | |||
2715 | p->sched_contributes_to_load = !!task_contributes_to_load(p); | 2742 | p->sched_contributes_to_load = !!task_contributes_to_load(p); |
2716 | p->state = TASK_WAKING; | 2743 | p->state = TASK_WAKING; |
2717 | 2744 | ||
@@ -2723,12 +2750,16 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) | |||
2723 | wake_flags |= WF_MIGRATED; | 2750 | wake_flags |= WF_MIGRATED; |
2724 | set_task_cpu(p, cpu); | 2751 | set_task_cpu(p, cpu); |
2725 | } | 2752 | } |
2753 | |||
2754 | litmus_out_activate: | ||
2726 | #endif /* CONFIG_SMP */ | 2755 | #endif /* CONFIG_SMP */ |
2727 | 2756 | ||
2728 | ttwu_queue(p, cpu); | 2757 | ttwu_queue(p, cpu); |
2729 | stat: | 2758 | stat: |
2730 | ttwu_stat(p, cpu, wake_flags); | 2759 | ttwu_stat(p, cpu, wake_flags); |
2731 | out: | 2760 | out: |
2761 | if (is_realtime(p)) | ||
2762 | TRACE_TASK(p, "try_to_wake_up() done state:%d\n", p->state); | ||
2732 | raw_spin_unlock_irqrestore(&p->pi_lock, flags); | 2763 | raw_spin_unlock_irqrestore(&p->pi_lock, flags); |
2733 | 2764 | ||
2734 | return success; | 2765 | return success; |
@@ -2839,7 +2870,8 @@ void sched_fork(struct task_struct *p) | |||
2839 | * Revert to default priority/policy on fork if requested. | 2870 | * Revert to default priority/policy on fork if requested. |
2840 | */ | 2871 | */ |
2841 | if (unlikely(p->sched_reset_on_fork)) { | 2872 | if (unlikely(p->sched_reset_on_fork)) { |
2842 | if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) { | 2873 | if (p->policy == SCHED_FIFO || p->policy == SCHED_RR || |
2874 | p->policy == SCHED_LITMUS) { | ||
2843 | p->policy = SCHED_NORMAL; | 2875 | p->policy = SCHED_NORMAL; |
2844 | p->normal_prio = p->static_prio; | 2876 | p->normal_prio = p->static_prio; |
2845 | } | 2877 | } |
@@ -3050,6 +3082,8 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) | |||
3050 | */ | 3082 | */ |
3051 | prev_state = prev->state; | 3083 | prev_state = prev->state; |
3052 | finish_arch_switch(prev); | 3084 | finish_arch_switch(prev); |
3085 | litmus->finish_switch(prev); | ||
3086 | prev->rt_param.stack_in_use = NO_CPU; | ||
3053 | #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW | 3087 | #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW |
3054 | local_irq_disable(); | 3088 | local_irq_disable(); |
3055 | #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ | 3089 | #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ |
@@ -3079,6 +3113,15 @@ static inline void pre_schedule(struct rq *rq, struct task_struct *prev) | |||
3079 | { | 3113 | { |
3080 | if (prev->sched_class->pre_schedule) | 3114 | if (prev->sched_class->pre_schedule) |
3081 | prev->sched_class->pre_schedule(rq, prev); | 3115 | prev->sched_class->pre_schedule(rq, prev); |
3116 | |||
3117 | /* LITMUS^RT not very clean hack: we need to save the prev task | ||
3118 | * as our scheduling decision rely on it (as we drop the rq lock | ||
3119 | * something in prev can change...); there is no way to escape | ||
3120 | * this ack apart from modifying pick_nex_task(rq, _prev_) or | ||
3121 | * falling back on the previous solution of decoupling | ||
3122 | * scheduling decisions | ||
3123 | */ | ||
3124 | rq->litmus.prev = prev; | ||
3082 | } | 3125 | } |
3083 | 3126 | ||
3084 | /* rq->lock is NOT held, but preemption is disabled */ | 3127 | /* rq->lock is NOT held, but preemption is disabled */ |
@@ -4094,18 +4137,26 @@ void scheduler_tick(void) | |||
4094 | 4137 | ||
4095 | sched_clock_tick(); | 4138 | sched_clock_tick(); |
4096 | 4139 | ||
4140 | TS_TICK_START(current); | ||
4141 | |||
4097 | raw_spin_lock(&rq->lock); | 4142 | raw_spin_lock(&rq->lock); |
4098 | update_rq_clock(rq); | 4143 | update_rq_clock(rq); |
4099 | update_cpu_load_active(rq); | 4144 | update_cpu_load_active(rq); |
4100 | curr->sched_class->task_tick(rq, curr, 0); | 4145 | curr->sched_class->task_tick(rq, curr, 0); |
4146 | |||
4147 | /* litmus_tick may force current to resched */ | ||
4148 | litmus_tick(rq, curr); | ||
4149 | |||
4101 | raw_spin_unlock(&rq->lock); | 4150 | raw_spin_unlock(&rq->lock); |
4102 | 4151 | ||
4103 | perf_event_task_tick(); | 4152 | perf_event_task_tick(); |
4104 | 4153 | ||
4105 | #ifdef CONFIG_SMP | 4154 | #ifdef CONFIG_SMP |
4106 | rq->idle_at_tick = idle_cpu(cpu); | 4155 | rq->idle_at_tick = idle_cpu(cpu); |
4107 | trigger_load_balance(rq, cpu); | 4156 | if (!is_realtime(current)) |
4157 | trigger_load_balance(rq, cpu); | ||
4108 | #endif | 4158 | #endif |
4159 | TS_TICK_END(current); | ||
4109 | } | 4160 | } |
4110 | 4161 | ||
4111 | notrace unsigned long get_parent_ip(unsigned long addr) | 4162 | notrace unsigned long get_parent_ip(unsigned long addr) |
@@ -4225,12 +4276,20 @@ pick_next_task(struct rq *rq) | |||
4225 | /* | 4276 | /* |
4226 | * Optimization: we know that if all tasks are in | 4277 | * Optimization: we know that if all tasks are in |
4227 | * the fair class we can call that function directly: | 4278 | * the fair class we can call that function directly: |
4228 | */ | 4279 | |
4229 | if (likely(rq->nr_running == rq->cfs.nr_running)) { | 4280 | * NOT IN LITMUS^RT! |
4281 | |||
4282 | * This breaks many assumptions in the plugins. | ||
4283 | * Do not uncomment without thinking long and hard | ||
4284 | * about how this affects global plugins such as GSN-EDF. | ||
4285 | |||
4286 | if (rq->nr_running == rq->cfs.nr_running) { | ||
4287 | TRACE("taking shortcut in pick_next_task()\n"); | ||
4230 | p = fair_sched_class.pick_next_task(rq); | 4288 | p = fair_sched_class.pick_next_task(rq); |
4231 | if (likely(p)) | 4289 | if (likely(p)) |
4232 | return p; | 4290 | return p; |
4233 | } | 4291 | } |
4292 | */ | ||
4234 | 4293 | ||
4235 | for_each_class(class) { | 4294 | for_each_class(class) { |
4236 | p = class->pick_next_task(rq); | 4295 | p = class->pick_next_task(rq); |
@@ -4253,11 +4312,19 @@ asmlinkage void __sched schedule(void) | |||
4253 | 4312 | ||
4254 | need_resched: | 4313 | need_resched: |
4255 | preempt_disable(); | 4314 | preempt_disable(); |
4315 | sched_state_entered_schedule(); | ||
4256 | cpu = smp_processor_id(); | 4316 | cpu = smp_processor_id(); |
4257 | rq = cpu_rq(cpu); | 4317 | rq = cpu_rq(cpu); |
4258 | rcu_note_context_switch(cpu); | 4318 | rcu_note_context_switch(cpu); |
4259 | prev = rq->curr; | 4319 | prev = rq->curr; |
4260 | 4320 | ||
4321 | /* LITMUS^RT: quickly re-evaluate the scheduling decision | ||
4322 | * if the previous one is no longer valid after CTX. | ||
4323 | */ | ||
4324 | litmus_need_resched_nonpreemptible: | ||
4325 | TS_SCHED_START; | ||
4326 | sched_trace_task_switch_away(prev); | ||
4327 | |||
4261 | schedule_debug(prev); | 4328 | schedule_debug(prev); |
4262 | 4329 | ||
4263 | if (sched_feat(HRTICK)) | 4330 | if (sched_feat(HRTICK)) |
@@ -4314,7 +4381,10 @@ need_resched: | |||
4314 | rq->curr = next; | 4381 | rq->curr = next; |
4315 | ++*switch_count; | 4382 | ++*switch_count; |
4316 | 4383 | ||
4384 | TS_SCHED_END(next); | ||
4385 | TS_CXS_START(next); | ||
4317 | context_switch(rq, prev, next); /* unlocks the rq */ | 4386 | context_switch(rq, prev, next); /* unlocks the rq */ |
4387 | TS_CXS_END(current); | ||
4318 | /* | 4388 | /* |
4319 | * The context switch have flipped the stack from under us | 4389 | * The context switch have flipped the stack from under us |
4320 | * and restored the local variables which were saved when | 4390 | * and restored the local variables which were saved when |
@@ -4323,14 +4393,23 @@ need_resched: | |||
4323 | */ | 4393 | */ |
4324 | cpu = smp_processor_id(); | 4394 | cpu = smp_processor_id(); |
4325 | rq = cpu_rq(cpu); | 4395 | rq = cpu_rq(cpu); |
4326 | } else | 4396 | } else { |
4397 | TS_SCHED_END(prev); | ||
4327 | raw_spin_unlock_irq(&rq->lock); | 4398 | raw_spin_unlock_irq(&rq->lock); |
4399 | } | ||
4400 | |||
4401 | sched_trace_task_switch_to(current); | ||
4328 | 4402 | ||
4329 | post_schedule(rq); | 4403 | post_schedule(rq); |
4330 | 4404 | ||
4405 | if (sched_state_validate_switch()) | ||
4406 | goto litmus_need_resched_nonpreemptible; | ||
4407 | |||
4331 | preempt_enable_no_resched(); | 4408 | preempt_enable_no_resched(); |
4332 | if (need_resched()) | 4409 | if (need_resched()) |
4333 | goto need_resched; | 4410 | goto need_resched; |
4411 | |||
4412 | srp_ceiling_block(); | ||
4334 | } | 4413 | } |
4335 | EXPORT_SYMBOL(schedule); | 4414 | EXPORT_SYMBOL(schedule); |
4336 | 4415 | ||
@@ -4600,6 +4679,17 @@ void complete_all(struct completion *x) | |||
4600 | } | 4679 | } |
4601 | EXPORT_SYMBOL(complete_all); | 4680 | EXPORT_SYMBOL(complete_all); |
4602 | 4681 | ||
4682 | void complete_n(struct completion *x, int n) | ||
4683 | { | ||
4684 | unsigned long flags; | ||
4685 | |||
4686 | spin_lock_irqsave(&x->wait.lock, flags); | ||
4687 | x->done += n; | ||
4688 | __wake_up_common(&x->wait, TASK_NORMAL, n, 0, NULL); | ||
4689 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
4690 | } | ||
4691 | EXPORT_SYMBOL(complete_n); | ||
4692 | |||
4603 | static inline long __sched | 4693 | static inline long __sched |
4604 | do_wait_for_common(struct completion *x, long timeout, int state) | 4694 | do_wait_for_common(struct completion *x, long timeout, int state) |
4605 | { | 4695 | { |
@@ -5039,7 +5129,9 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) | |||
5039 | p->normal_prio = normal_prio(p); | 5129 | p->normal_prio = normal_prio(p); |
5040 | /* we are holding p->pi_lock already */ | 5130 | /* we are holding p->pi_lock already */ |
5041 | p->prio = rt_mutex_getprio(p); | 5131 | p->prio = rt_mutex_getprio(p); |
5042 | if (rt_prio(p->prio)) | 5132 | if (p->policy == SCHED_LITMUS) |
5133 | p->sched_class = &litmus_sched_class; | ||
5134 | else if (rt_prio(p->prio)) | ||
5043 | p->sched_class = &rt_sched_class; | 5135 | p->sched_class = &rt_sched_class; |
5044 | else | 5136 | else |
5045 | p->sched_class = &fair_sched_class; | 5137 | p->sched_class = &fair_sched_class; |
@@ -5087,7 +5179,7 @@ recheck: | |||
5087 | 5179 | ||
5088 | if (policy != SCHED_FIFO && policy != SCHED_RR && | 5180 | if (policy != SCHED_FIFO && policy != SCHED_RR && |
5089 | policy != SCHED_NORMAL && policy != SCHED_BATCH && | 5181 | policy != SCHED_NORMAL && policy != SCHED_BATCH && |
5090 | policy != SCHED_IDLE) | 5182 | policy != SCHED_IDLE && policy != SCHED_LITMUS) |
5091 | return -EINVAL; | 5183 | return -EINVAL; |
5092 | } | 5184 | } |
5093 | 5185 | ||
@@ -5102,6 +5194,8 @@ recheck: | |||
5102 | return -EINVAL; | 5194 | return -EINVAL; |
5103 | if (rt_policy(policy) != (param->sched_priority != 0)) | 5195 | if (rt_policy(policy) != (param->sched_priority != 0)) |
5104 | return -EINVAL; | 5196 | return -EINVAL; |
5197 | if (policy == SCHED_LITMUS && policy == p->policy) | ||
5198 | return -EINVAL; | ||
5105 | 5199 | ||
5106 | /* | 5200 | /* |
5107 | * Allow unprivileged RT tasks to decrease priority: | 5201 | * Allow unprivileged RT tasks to decrease priority: |
@@ -5145,6 +5239,12 @@ recheck: | |||
5145 | return retval; | 5239 | return retval; |
5146 | } | 5240 | } |
5147 | 5241 | ||
5242 | if (policy == SCHED_LITMUS) { | ||
5243 | retval = litmus_admit_task(p); | ||
5244 | if (retval) | ||
5245 | return retval; | ||
5246 | } | ||
5247 | |||
5148 | /* | 5248 | /* |
5149 | * make sure no PI-waiters arrive (or leave) while we are | 5249 | * make sure no PI-waiters arrive (or leave) while we are |
5150 | * changing the priority of the task: | 5250 | * changing the priority of the task: |
@@ -5203,10 +5303,19 @@ recheck: | |||
5203 | 5303 | ||
5204 | p->sched_reset_on_fork = reset_on_fork; | 5304 | p->sched_reset_on_fork = reset_on_fork; |
5205 | 5305 | ||
5306 | if (p->policy == SCHED_LITMUS) | ||
5307 | litmus_exit_task(p); | ||
5308 | |||
5206 | oldprio = p->prio; | 5309 | oldprio = p->prio; |
5207 | prev_class = p->sched_class; | 5310 | prev_class = p->sched_class; |
5208 | __setscheduler(rq, p, policy, param->sched_priority); | 5311 | __setscheduler(rq, p, policy, param->sched_priority); |
5209 | 5312 | ||
5313 | if (policy == SCHED_LITMUS) { | ||
5314 | p->rt_param.stack_in_use = running ? rq->cpu : NO_CPU; | ||
5315 | p->rt_param.present = running; | ||
5316 | litmus->task_new(p, on_rq, running); | ||
5317 | } | ||
5318 | |||
5210 | if (running) | 5319 | if (running) |
5211 | p->sched_class->set_curr_task(rq); | 5320 | p->sched_class->set_curr_task(rq); |
5212 | if (on_rq) | 5321 | if (on_rq) |
@@ -5374,10 +5483,11 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) | |||
5374 | rcu_read_lock(); | 5483 | rcu_read_lock(); |
5375 | 5484 | ||
5376 | p = find_process_by_pid(pid); | 5485 | p = find_process_by_pid(pid); |
5377 | if (!p) { | 5486 | /* Don't set affinity if task not found and for LITMUS tasks */ |
5487 | if (!p || is_realtime(p)) { | ||
5378 | rcu_read_unlock(); | 5488 | rcu_read_unlock(); |
5379 | put_online_cpus(); | 5489 | put_online_cpus(); |
5380 | return -ESRCH; | 5490 | return p ? -EPERM : -ESRCH; |
5381 | } | 5491 | } |
5382 | 5492 | ||
5383 | /* Prevent p going away */ | 5493 | /* Prevent p going away */ |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index c768588e180b..334eb474af93 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -1890,6 +1890,9 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ | |||
1890 | int scale = cfs_rq->nr_running >= sched_nr_latency; | 1890 | int scale = cfs_rq->nr_running >= sched_nr_latency; |
1891 | int next_buddy_marked = 0; | 1891 | int next_buddy_marked = 0; |
1892 | 1892 | ||
1893 | if (unlikely(rt_prio(p->prio)) || p->policy == SCHED_LITMUS) | ||
1894 | goto preempt; | ||
1895 | |||
1893 | if (unlikely(se == pse)) | 1896 | if (unlikely(se == pse)) |
1894 | return; | 1897 | return; |
1895 | 1898 | ||
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 10d018212bab..58cf5d18dfdc 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
@@ -1078,7 +1078,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p) | |||
1078 | */ | 1078 | */ |
1079 | static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flags) | 1079 | static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flags) |
1080 | { | 1080 | { |
1081 | if (p->prio < rq->curr->prio) { | 1081 | if (p->prio < rq->curr->prio || p->policy == SCHED_LITMUS) { |
1082 | resched_task(rq->curr); | 1082 | resched_task(rq->curr); |
1083 | return; | 1083 | return; |
1084 | } | 1084 | } |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index d5097c44b407..0c0e02f1b819 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -766,12 +766,53 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) | |||
766 | } | 766 | } |
767 | 767 | ||
768 | /** | 768 | /** |
769 | * tick_set_quanta_type - get the quanta type as a boot option | ||
770 | * Default is standard setup with ticks staggered over first | ||
771 | * half of tick period. | ||
772 | */ | ||
773 | int quanta_type = LINUX_DEFAULT_TICKS; | ||
774 | static int __init tick_set_quanta_type(char *str) | ||
775 | { | ||
776 | if (strcmp("aligned", str) == 0) { | ||
777 | quanta_type = LITMUS_ALIGNED_TICKS; | ||
778 | printk(KERN_INFO "LITMUS^RT: setting aligned quanta\n"); | ||
779 | } | ||
780 | else if (strcmp("staggered", str) == 0) { | ||
781 | quanta_type = LITMUS_STAGGERED_TICKS; | ||
782 | printk(KERN_INFO "LITMUS^RT: setting staggered quanta\n"); | ||
783 | } | ||
784 | return 1; | ||
785 | } | ||
786 | __setup("quanta=", tick_set_quanta_type); | ||
787 | |||
788 | u64 cpu_stagger_offset(int cpu) | ||
789 | { | ||
790 | u64 offset = 0; | ||
791 | switch (quanta_type) { | ||
792 | case LITMUS_ALIGNED_TICKS: | ||
793 | offset = 0; | ||
794 | break; | ||
795 | case LITMUS_STAGGERED_TICKS: | ||
796 | offset = ktime_to_ns(tick_period); | ||
797 | do_div(offset, num_possible_cpus()); | ||
798 | offset *= cpu; | ||
799 | break; | ||
800 | default: | ||
801 | offset = ktime_to_ns(tick_period) >> 1; | ||
802 | do_div(offset, num_possible_cpus()); | ||
803 | offset *= cpu; | ||
804 | } | ||
805 | return offset; | ||
806 | } | ||
807 | |||
808 | /** | ||
769 | * tick_setup_sched_timer - setup the tick emulation timer | 809 | * tick_setup_sched_timer - setup the tick emulation timer |
770 | */ | 810 | */ |
771 | void tick_setup_sched_timer(void) | 811 | void tick_setup_sched_timer(void) |
772 | { | 812 | { |
773 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); | 813 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
774 | ktime_t now = ktime_get(); | 814 | ktime_t now = ktime_get(); |
815 | u64 offset; | ||
775 | 816 | ||
776 | /* | 817 | /* |
777 | * Emulate tick processing via per-CPU hrtimers: | 818 | * Emulate tick processing via per-CPU hrtimers: |
@@ -782,6 +823,12 @@ void tick_setup_sched_timer(void) | |||
782 | /* Get the next period (per cpu) */ | 823 | /* Get the next period (per cpu) */ |
783 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); | 824 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); |
784 | 825 | ||
826 | /* Offset must be set correctly to achieve desired quanta type. */ | ||
827 | offset = cpu_stagger_offset(smp_processor_id()); | ||
828 | |||
829 | /* Add the correct offset to expiration time */ | ||
830 | hrtimer_add_expires_ns(&ts->sched_timer, offset); | ||
831 | |||
785 | for (;;) { | 832 | for (;;) { |
786 | hrtimer_forward(&ts->sched_timer, now, tick_period); | 833 | hrtimer_forward(&ts->sched_timer, now, tick_period); |
787 | hrtimer_start_expires(&ts->sched_timer, | 834 | hrtimer_start_expires(&ts->sched_timer, |