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 | 82 | ||||
-rw-r--r-- | kernel/printk.c | 14 | ||||
-rw-r--r-- | kernel/sched.c | 106 | ||||
-rw-r--r-- | kernel/sched_fair.c | 2 | ||||
-rw-r--r-- | kernel/sched_rt.c | 2 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 48 |
8 files changed, 248 insertions, 17 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 7f2683a10ac4..256ce8c2ebc8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -57,6 +57,8 @@ | |||
57 | #include <asm/mmu_context.h> | 57 | #include <asm/mmu_context.h> |
58 | #include "cred-internals.h" | 58 | #include "cred-internals.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) | 64 | static void __unhash_process(struct task_struct *p) |
@@ -968,6 +970,8 @@ NORET_TYPE void do_exit(long code) | |||
968 | if (unlikely(tsk->audit_context)) | 970 | if (unlikely(tsk->audit_context)) |
969 | audit_free(tsk); | 971 | audit_free(tsk); |
970 | 972 | ||
973 | exit_od_table(tsk); | ||
974 | |||
971 | tsk->exit_code = code; | 975 | tsk->exit_code = code; |
972 | taskstats_exit(tsk, group_dead); | 976 | taskstats_exit(tsk, group_dead); |
973 | 977 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index 4c14942a0ee3..166eb780dd7d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -75,6 +75,9 @@ | |||
75 | 75 | ||
76 | #include <trace/events/sched.h> | 76 | #include <trace/events/sched.h> |
77 | 77 | ||
78 | #include <litmus/litmus.h> | ||
79 | #include <litmus/sched_plugin.h> | ||
80 | |||
78 | /* | 81 | /* |
79 | * Protected counters by write_lock_irq(&tasklist_lock) | 82 | * Protected counters by write_lock_irq(&tasklist_lock) |
80 | */ | 83 | */ |
@@ -171,6 +174,7 @@ void __put_task_struct(struct task_struct *tsk) | |||
171 | WARN_ON(atomic_read(&tsk->usage)); | 174 | WARN_ON(atomic_read(&tsk->usage)); |
172 | WARN_ON(tsk == current); | 175 | WARN_ON(tsk == current); |
173 | 176 | ||
177 | exit_litmus(tsk); | ||
174 | exit_creds(tsk); | 178 | exit_creds(tsk); |
175 | delayacct_tsk_free(tsk); | 179 | delayacct_tsk_free(tsk); |
176 | 180 | ||
@@ -253,6 +257,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
253 | 257 | ||
254 | tsk->stack = ti; | 258 | tsk->stack = ti; |
255 | 259 | ||
260 | /* Don't let the new task be a real-time task. */ | ||
261 | litmus_fork(tsk); | ||
262 | |||
256 | err = prop_local_init_single(&tsk->dirties); | 263 | err = prop_local_init_single(&tsk->dirties); |
257 | if (err) | 264 | if (err) |
258 | goto out; | 265 | goto out; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 0086628b6e97..c0b440b1f6ee 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> |
@@ -1041,6 +1043,85 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) | |||
1041 | } | 1043 | } |
1042 | EXPORT_SYMBOL_GPL(hrtimer_start); | 1044 | EXPORT_SYMBOL_GPL(hrtimer_start); |
1043 | 1045 | ||
1046 | /** | ||
1047 | * hrtimer_pull - PULL_TIMERS_VECTOR callback on remote cpu | ||
1048 | */ | ||
1049 | void hrtimer_pull(void) | ||
1050 | { | ||
1051 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | ||
1052 | struct hrtimer_start_on_info *info; | ||
1053 | struct list_head *pos, *safe, list; | ||
1054 | |||
1055 | spin_lock(&base->lock); | ||
1056 | list_replace_init(&base->to_pull, &list); | ||
1057 | spin_unlock(&base->lock); | ||
1058 | |||
1059 | list_for_each_safe(pos, safe, &list) { | ||
1060 | info = list_entry(pos, struct hrtimer_start_on_info, list); | ||
1061 | TRACE("pulled timer 0x%x\n", info->timer); | ||
1062 | list_del(pos); | ||
1063 | hrtimer_start(info->timer, info->time, info->mode); | ||
1064 | } | ||
1065 | } | ||
1066 | |||
1067 | /** | ||
1068 | * hrtimer_start_on - trigger timer arming on remote cpu | ||
1069 | * @cpu: remote cpu | ||
1070 | * @info: save timer information for enqueuing on remote cpu | ||
1071 | * @timer: timer to be pulled | ||
1072 | * @time: expire time | ||
1073 | * @mode: timer mode | ||
1074 | */ | ||
1075 | int hrtimer_start_on(int cpu, struct hrtimer_start_on_info* info, | ||
1076 | struct hrtimer *timer, ktime_t time, | ||
1077 | const enum hrtimer_mode mode) | ||
1078 | { | ||
1079 | unsigned long flags; | ||
1080 | struct hrtimer_cpu_base* base; | ||
1081 | int in_use = 0, was_empty; | ||
1082 | |||
1083 | /* serialize access to info through the timer base */ | ||
1084 | lock_hrtimer_base(timer, &flags); | ||
1085 | |||
1086 | in_use = (atomic_read(&info->state) != HRTIMER_START_ON_INACTIVE); | ||
1087 | if (!in_use) { | ||
1088 | INIT_LIST_HEAD(&info->list); | ||
1089 | info->timer = timer; | ||
1090 | info->time = time; | ||
1091 | info->mode = mode; | ||
1092 | /* mark as in use */ | ||
1093 | atomic_set(&info->state, HRTIMER_START_ON_QUEUED); | ||
1094 | } | ||
1095 | |||
1096 | unlock_hrtimer_base(timer, &flags); | ||
1097 | |||
1098 | if (!in_use) { | ||
1099 | /* initiate pull */ | ||
1100 | preempt_disable(); | ||
1101 | if (cpu == smp_processor_id()) { | ||
1102 | /* start timer locally; we may get called | ||
1103 | * with rq->lock held, do not wake up anything | ||
1104 | */ | ||
1105 | TRACE("hrtimer_start_on: starting on local CPU\n"); | ||
1106 | __hrtimer_start_range_ns(info->timer, info->time, | ||
1107 | 0, info->mode, 0); | ||
1108 | } else { | ||
1109 | TRACE("hrtimer_start_on: pulling to remote CPU\n"); | ||
1110 | base = &per_cpu(hrtimer_bases, cpu); | ||
1111 | spin_lock_irqsave(&base->lock, flags); | ||
1112 | was_empty = list_empty(&base->to_pull); | ||
1113 | list_add(&info->list, &base->to_pull); | ||
1114 | spin_unlock_irqrestore(&base->lock, flags); | ||
1115 | if (was_empty) | ||
1116 | /* only send IPI if other no else | ||
1117 | * has done so already | ||
1118 | */ | ||
1119 | smp_send_pull_timers(cpu); | ||
1120 | } | ||
1121 | preempt_enable(); | ||
1122 | } | ||
1123 | return in_use; | ||
1124 | } | ||
1044 | 1125 | ||
1045 | /** | 1126 | /** |
1046 | * hrtimer_try_to_cancel - try to deactivate a timer | 1127 | * hrtimer_try_to_cancel - try to deactivate a timer |
@@ -1631,6 +1712,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu) | |||
1631 | cpu_base->clock_base[i].cpu_base = cpu_base; | 1712 | cpu_base->clock_base[i].cpu_base = cpu_base; |
1632 | 1713 | ||
1633 | hrtimer_init_hres(cpu_base); | 1714 | hrtimer_init_hres(cpu_base); |
1715 | INIT_LIST_HEAD(&cpu_base->to_pull); | ||
1634 | } | 1716 | } |
1635 | 1717 | ||
1636 | #ifdef CONFIG_HOTPLUG_CPU | 1718 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/kernel/printk.c b/kernel/printk.c index 75077ad0b537..ee54355cfdf1 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -71,6 +71,13 @@ int console_printk[4] = { | |||
71 | }; | 71 | }; |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * divert printk() messages when there is a LITMUS^RT debug listener | ||
75 | */ | ||
76 | #include <litmus/litmus.h> | ||
77 | int trace_override = 0; | ||
78 | int trace_recurse = 0; | ||
79 | |||
80 | /* | ||
74 | * Low level drivers may need that to know if they can schedule in | 81 | * Low level drivers may need that to know if they can schedule in |
75 | * their unblank() callback or not. So let's export it. | 82 | * their unblank() callback or not. So let's export it. |
76 | */ | 83 | */ |
@@ -708,6 +715,9 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
708 | /* Emit the output into the temporary buffer */ | 715 | /* Emit the output into the temporary buffer */ |
709 | printed_len += vscnprintf(printk_buf + printed_len, | 716 | printed_len += vscnprintf(printk_buf + printed_len, |
710 | sizeof(printk_buf) - printed_len, fmt, args); | 717 | sizeof(printk_buf) - printed_len, fmt, args); |
718 | /* if LITMUS^RT tracer is active divert printk() msgs */ | ||
719 | if (trace_override && !trace_recurse) | ||
720 | TRACE("%s", printk_buf); | ||
711 | 721 | ||
712 | 722 | ||
713 | p = printk_buf; | 723 | p = printk_buf; |
@@ -777,7 +787,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
777 | * Try to acquire and then immediately release the | 787 | * Try to acquire and then immediately release the |
778 | * console semaphore. The release will do all the | 788 | * console semaphore. The release will do all the |
779 | * actual magic (print out buffers, wake up klogd, | 789 | * actual magic (print out buffers, wake up klogd, |
780 | * etc). | 790 | * etc). |
781 | * | 791 | * |
782 | * The acquire_console_semaphore_for_printk() function | 792 | * The acquire_console_semaphore_for_printk() function |
783 | * will release 'logbuf_lock' regardless of whether it | 793 | * will release 'logbuf_lock' regardless of whether it |
@@ -1014,7 +1024,7 @@ int printk_needs_cpu(int cpu) | |||
1014 | 1024 | ||
1015 | void wake_up_klogd(void) | 1025 | void wake_up_klogd(void) |
1016 | { | 1026 | { |
1017 | if (waitqueue_active(&log_wait)) | 1027 | if (!trace_override && waitqueue_active(&log_wait)) |
1018 | __raw_get_cpu_var(printk_pending) = 1; | 1028 | __raw_get_cpu_var(printk_pending) = 1; |
1019 | } | 1029 | } |
1020 | 1030 | ||
diff --git a/kernel/sched.c b/kernel/sched.c index 3c2a54f70ffe..5e3c509e0efe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -78,6 +78,9 @@ | |||
78 | 78 | ||
79 | #include "sched_cpupri.h" | 79 | #include "sched_cpupri.h" |
80 | 80 | ||
81 | #include <litmus/sched_trace.h> | ||
82 | #include <litmus/trace.h> | ||
83 | |||
81 | #define CREATE_TRACE_POINTS | 84 | #define CREATE_TRACE_POINTS |
82 | #include <trace/events/sched.h> | 85 | #include <trace/events/sched.h> |
83 | 86 | ||
@@ -450,6 +453,12 @@ struct rt_rq { | |||
450 | #endif | 453 | #endif |
451 | }; | 454 | }; |
452 | 455 | ||
456 | /* Litmus related fields in a runqueue */ | ||
457 | struct litmus_rq { | ||
458 | unsigned long nr_running; | ||
459 | struct task_struct *prev; | ||
460 | }; | ||
461 | |||
453 | #ifdef CONFIG_SMP | 462 | #ifdef CONFIG_SMP |
454 | 463 | ||
455 | /* | 464 | /* |
@@ -512,6 +521,7 @@ struct rq { | |||
512 | 521 | ||
513 | struct cfs_rq cfs; | 522 | struct cfs_rq cfs; |
514 | struct rt_rq rt; | 523 | struct rt_rq rt; |
524 | struct litmus_rq litmus; | ||
515 | 525 | ||
516 | #ifdef CONFIG_FAIR_GROUP_SCHED | 526 | #ifdef CONFIG_FAIR_GROUP_SCHED |
517 | /* list of leaf cfs_rq on this cpu: */ | 527 | /* list of leaf cfs_rq on this cpu: */ |
@@ -1833,7 +1843,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) | |||
1833 | 1843 | ||
1834 | static const struct sched_class rt_sched_class; | 1844 | static const struct sched_class rt_sched_class; |
1835 | 1845 | ||
1836 | #define sched_class_highest (&rt_sched_class) | 1846 | #define sched_class_highest (&litmus_sched_class) |
1837 | #define for_each_class(class) \ | 1847 | #define for_each_class(class) \ |
1838 | for (class = sched_class_highest; class; class = class->next) | 1848 | for (class = sched_class_highest; class; class = class->next) |
1839 | 1849 | ||
@@ -1932,6 +1942,7 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep) | |||
1932 | #include "sched_idletask.c" | 1942 | #include "sched_idletask.c" |
1933 | #include "sched_fair.c" | 1943 | #include "sched_fair.c" |
1934 | #include "sched_rt.c" | 1944 | #include "sched_rt.c" |
1945 | #include "../litmus/sched_litmus.c" | ||
1935 | #ifdef CONFIG_SCHED_DEBUG | 1946 | #ifdef CONFIG_SCHED_DEBUG |
1936 | # include "sched_debug.c" | 1947 | # include "sched_debug.c" |
1937 | #endif | 1948 | #endif |
@@ -2372,6 +2383,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, | |||
2372 | unsigned long flags; | 2383 | unsigned long flags; |
2373 | struct rq *rq; | 2384 | struct rq *rq; |
2374 | 2385 | ||
2386 | if (is_realtime(p)) | ||
2387 | TRACE_TASK(p, "try_to_wake_up() state:%d\n", p->state); | ||
2388 | |||
2375 | if (!sched_feat(SYNC_WAKEUPS)) | 2389 | if (!sched_feat(SYNC_WAKEUPS)) |
2376 | wake_flags &= ~WF_SYNC; | 2390 | wake_flags &= ~WF_SYNC; |
2377 | 2391 | ||
@@ -2390,7 +2404,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, | |||
2390 | orig_cpu = cpu; | 2404 | orig_cpu = cpu; |
2391 | 2405 | ||
2392 | #ifdef CONFIG_SMP | 2406 | #ifdef CONFIG_SMP |
2393 | if (unlikely(task_running(rq, p))) | 2407 | if (unlikely(task_running(rq, p)) || is_realtime(p)) |
2394 | goto out_activate; | 2408 | goto out_activate; |
2395 | 2409 | ||
2396 | /* | 2410 | /* |
@@ -2497,6 +2511,8 @@ out_running: | |||
2497 | } | 2511 | } |
2498 | #endif | 2512 | #endif |
2499 | out: | 2513 | out: |
2514 | if (is_realtime(p)) | ||
2515 | TRACE_TASK(p, "try_to_wake_up() done state:%d\n", p->state); | ||
2500 | task_rq_unlock(rq, &flags); | 2516 | task_rq_unlock(rq, &flags); |
2501 | put_cpu(); | 2517 | put_cpu(); |
2502 | 2518 | ||
@@ -2814,6 +2830,8 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) | |||
2814 | */ | 2830 | */ |
2815 | prev_state = prev->state; | 2831 | prev_state = prev->state; |
2816 | finish_arch_switch(prev); | 2832 | finish_arch_switch(prev); |
2833 | litmus->finish_switch(prev); | ||
2834 | prev->rt_param.stack_in_use = NO_CPU; | ||
2817 | #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW | 2835 | #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW |
2818 | local_irq_disable(); | 2836 | local_irq_disable(); |
2819 | #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ | 2837 | #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ |
@@ -2843,6 +2861,15 @@ static inline void pre_schedule(struct rq *rq, struct task_struct *prev) | |||
2843 | { | 2861 | { |
2844 | if (prev->sched_class->pre_schedule) | 2862 | if (prev->sched_class->pre_schedule) |
2845 | prev->sched_class->pre_schedule(rq, prev); | 2863 | prev->sched_class->pre_schedule(rq, prev); |
2864 | |||
2865 | /* LITMUS^RT not very clean hack: we need to save the prev task | ||
2866 | * as our scheduling decision rely on it (as we drop the rq lock | ||
2867 | * something in prev can change...); there is no way to escape | ||
2868 | * this ack apart from modifying pick_nex_task(rq, _prev_) or | ||
2869 | * falling back on the previous solution of decoupling | ||
2870 | * scheduling decisions | ||
2871 | */ | ||
2872 | rq->litmus.prev = prev; | ||
2846 | } | 2873 | } |
2847 | 2874 | ||
2848 | /* rq->lock is NOT held, but preemption is disabled */ | 2875 | /* rq->lock is NOT held, but preemption is disabled */ |
@@ -3520,18 +3547,26 @@ void scheduler_tick(void) | |||
3520 | 3547 | ||
3521 | sched_clock_tick(); | 3548 | sched_clock_tick(); |
3522 | 3549 | ||
3550 | TS_TICK_START(current); | ||
3551 | |||
3523 | raw_spin_lock(&rq->lock); | 3552 | raw_spin_lock(&rq->lock); |
3524 | update_rq_clock(rq); | 3553 | update_rq_clock(rq); |
3525 | update_cpu_load(rq); | 3554 | update_cpu_load(rq); |
3526 | curr->sched_class->task_tick(rq, curr, 0); | 3555 | curr->sched_class->task_tick(rq, curr, 0); |
3556 | |||
3557 | /* litmus_tick may force current to resched */ | ||
3558 | litmus_tick(rq, curr); | ||
3559 | |||
3527 | raw_spin_unlock(&rq->lock); | 3560 | raw_spin_unlock(&rq->lock); |
3528 | 3561 | ||
3529 | perf_event_task_tick(curr); | 3562 | perf_event_task_tick(curr); |
3530 | 3563 | ||
3531 | #ifdef CONFIG_SMP | 3564 | #ifdef CONFIG_SMP |
3532 | rq->idle_at_tick = idle_cpu(cpu); | 3565 | rq->idle_at_tick = idle_cpu(cpu); |
3533 | trigger_load_balance(rq, cpu); | 3566 | if (!is_realtime(current)) |
3567 | trigger_load_balance(rq, cpu); | ||
3534 | #endif | 3568 | #endif |
3569 | TS_TICK_END(current); | ||
3535 | } | 3570 | } |
3536 | 3571 | ||
3537 | notrace unsigned long get_parent_ip(unsigned long addr) | 3572 | notrace unsigned long get_parent_ip(unsigned long addr) |
@@ -3672,12 +3707,20 @@ pick_next_task(struct rq *rq) | |||
3672 | /* | 3707 | /* |
3673 | * Optimization: we know that if all tasks are in | 3708 | * Optimization: we know that if all tasks are in |
3674 | * the fair class we can call that function directly: | 3709 | * the fair class we can call that function directly: |
3675 | */ | 3710 | |
3676 | if (likely(rq->nr_running == rq->cfs.nr_running)) { | 3711 | * NOT IN LITMUS^RT! |
3712 | |||
3713 | * This breaks many assumptions in the plugins. | ||
3714 | * Do not uncomment without thinking long and hard | ||
3715 | * about how this affects global plugins such as GSN-EDF. | ||
3716 | |||
3717 | if (rq->nr_running == rq->cfs.nr_running) { | ||
3718 | TRACE("taking shortcut in pick_next_task()\n"); | ||
3677 | p = fair_sched_class.pick_next_task(rq); | 3719 | p = fair_sched_class.pick_next_task(rq); |
3678 | if (likely(p)) | 3720 | if (likely(p)) |
3679 | return p; | 3721 | return p; |
3680 | } | 3722 | } |
3723 | */ | ||
3681 | 3724 | ||
3682 | class = sched_class_highest; | 3725 | class = sched_class_highest; |
3683 | for ( ; ; ) { | 3726 | for ( ; ; ) { |
@@ -3712,6 +3755,8 @@ need_resched: | |||
3712 | 3755 | ||
3713 | release_kernel_lock(prev); | 3756 | release_kernel_lock(prev); |
3714 | need_resched_nonpreemptible: | 3757 | need_resched_nonpreemptible: |
3758 | TS_SCHED_START; | ||
3759 | sched_trace_task_switch_away(prev); | ||
3715 | 3760 | ||
3716 | schedule_debug(prev); | 3761 | schedule_debug(prev); |
3717 | 3762 | ||
@@ -3746,15 +3791,22 @@ need_resched_nonpreemptible: | |||
3746 | rq->curr = next; | 3791 | rq->curr = next; |
3747 | ++*switch_count; | 3792 | ++*switch_count; |
3748 | 3793 | ||
3794 | TS_SCHED_END(next); | ||
3795 | TS_CXS_START(next); | ||
3749 | context_switch(rq, prev, next); /* unlocks the rq */ | 3796 | context_switch(rq, prev, next); /* unlocks the rq */ |
3797 | TS_CXS_END(current); | ||
3750 | /* | 3798 | /* |
3751 | * the context switch might have flipped the stack from under | 3799 | * the context switch might have flipped the stack from under |
3752 | * us, hence refresh the local variables. | 3800 | * us, hence refresh the local variables. |
3753 | */ | 3801 | */ |
3754 | cpu = smp_processor_id(); | 3802 | cpu = smp_processor_id(); |
3755 | rq = cpu_rq(cpu); | 3803 | rq = cpu_rq(cpu); |
3756 | } else | 3804 | } else { |
3805 | TS_SCHED_END(prev); | ||
3757 | raw_spin_unlock_irq(&rq->lock); | 3806 | raw_spin_unlock_irq(&rq->lock); |
3807 | } | ||
3808 | |||
3809 | sched_trace_task_switch_to(current); | ||
3758 | 3810 | ||
3759 | post_schedule(rq); | 3811 | post_schedule(rq); |
3760 | 3812 | ||
@@ -3767,6 +3819,9 @@ need_resched_nonpreemptible: | |||
3767 | preempt_enable_no_resched(); | 3819 | preempt_enable_no_resched(); |
3768 | if (need_resched()) | 3820 | if (need_resched()) |
3769 | goto need_resched; | 3821 | goto need_resched; |
3822 | |||
3823 | if (srp_active()) | ||
3824 | srp_ceiling_block(); | ||
3770 | } | 3825 | } |
3771 | EXPORT_SYMBOL(schedule); | 3826 | EXPORT_SYMBOL(schedule); |
3772 | 3827 | ||
@@ -4043,6 +4098,17 @@ void complete_all(struct completion *x) | |||
4043 | } | 4098 | } |
4044 | EXPORT_SYMBOL(complete_all); | 4099 | EXPORT_SYMBOL(complete_all); |
4045 | 4100 | ||
4101 | void complete_n(struct completion *x, int n) | ||
4102 | { | ||
4103 | unsigned long flags; | ||
4104 | |||
4105 | spin_lock_irqsave(&x->wait.lock, flags); | ||
4106 | x->done += n; | ||
4107 | __wake_up_common(&x->wait, TASK_NORMAL, n, 0, NULL); | ||
4108 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
4109 | } | ||
4110 | EXPORT_SYMBOL(complete_n); | ||
4111 | |||
4046 | static inline long __sched | 4112 | static inline long __sched |
4047 | do_wait_for_common(struct completion *x, long timeout, int state) | 4113 | do_wait_for_common(struct completion *x, long timeout, int state) |
4048 | { | 4114 | { |
@@ -4471,7 +4537,9 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) | |||
4471 | p->normal_prio = normal_prio(p); | 4537 | p->normal_prio = normal_prio(p); |
4472 | /* we are holding p->pi_lock already */ | 4538 | /* we are holding p->pi_lock already */ |
4473 | p->prio = rt_mutex_getprio(p); | 4539 | p->prio = rt_mutex_getprio(p); |
4474 | if (rt_prio(p->prio)) | 4540 | if (p->policy == SCHED_LITMUS) |
4541 | p->sched_class = &litmus_sched_class; | ||
4542 | else if (rt_prio(p->prio)) | ||
4475 | p->sched_class = &rt_sched_class; | 4543 | p->sched_class = &rt_sched_class; |
4476 | else | 4544 | else |
4477 | p->sched_class = &fair_sched_class; | 4545 | p->sched_class = &fair_sched_class; |
@@ -4516,7 +4584,7 @@ recheck: | |||
4516 | 4584 | ||
4517 | if (policy != SCHED_FIFO && policy != SCHED_RR && | 4585 | if (policy != SCHED_FIFO && policy != SCHED_RR && |
4518 | policy != SCHED_NORMAL && policy != SCHED_BATCH && | 4586 | policy != SCHED_NORMAL && policy != SCHED_BATCH && |
4519 | policy != SCHED_IDLE) | 4587 | policy != SCHED_IDLE && policy != SCHED_LITMUS) |
4520 | return -EINVAL; | 4588 | return -EINVAL; |
4521 | } | 4589 | } |
4522 | 4590 | ||
@@ -4531,6 +4599,8 @@ recheck: | |||
4531 | return -EINVAL; | 4599 | return -EINVAL; |
4532 | if (rt_policy(policy) != (param->sched_priority != 0)) | 4600 | if (rt_policy(policy) != (param->sched_priority != 0)) |
4533 | return -EINVAL; | 4601 | return -EINVAL; |
4602 | if (policy == SCHED_LITMUS && policy == p->policy) | ||
4603 | return -EINVAL; | ||
4534 | 4604 | ||
4535 | /* | 4605 | /* |
4536 | * Allow unprivileged RT tasks to decrease priority: | 4606 | * Allow unprivileged RT tasks to decrease priority: |
@@ -4585,6 +4655,12 @@ recheck: | |||
4585 | return retval; | 4655 | return retval; |
4586 | } | 4656 | } |
4587 | 4657 | ||
4658 | if (policy == SCHED_LITMUS) { | ||
4659 | retval = litmus_admit_task(p); | ||
4660 | if (retval) | ||
4661 | return retval; | ||
4662 | } | ||
4663 | |||
4588 | /* | 4664 | /* |
4589 | * make sure no PI-waiters arrive (or leave) while we are | 4665 | * make sure no PI-waiters arrive (or leave) while we are |
4590 | * changing the priority of the task: | 4666 | * changing the priority of the task: |
@@ -4612,10 +4688,19 @@ recheck: | |||
4612 | 4688 | ||
4613 | p->sched_reset_on_fork = reset_on_fork; | 4689 | p->sched_reset_on_fork = reset_on_fork; |
4614 | 4690 | ||
4691 | if (p->policy == SCHED_LITMUS) | ||
4692 | litmus_exit_task(p); | ||
4693 | |||
4615 | oldprio = p->prio; | 4694 | oldprio = p->prio; |
4616 | prev_class = p->sched_class; | 4695 | prev_class = p->sched_class; |
4617 | __setscheduler(rq, p, policy, param->sched_priority); | 4696 | __setscheduler(rq, p, policy, param->sched_priority); |
4618 | 4697 | ||
4698 | if (policy == SCHED_LITMUS) { | ||
4699 | p->rt_param.stack_in_use = running ? rq->cpu : NO_CPU; | ||
4700 | p->rt_param.present = running; | ||
4701 | litmus->task_new(p, on_rq, running); | ||
4702 | } | ||
4703 | |||
4619 | if (running) | 4704 | if (running) |
4620 | p->sched_class->set_curr_task(rq); | 4705 | p->sched_class->set_curr_task(rq); |
4621 | if (on_rq) { | 4706 | if (on_rq) { |
@@ -4785,10 +4870,11 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) | |||
4785 | rcu_read_lock(); | 4870 | rcu_read_lock(); |
4786 | 4871 | ||
4787 | p = find_process_by_pid(pid); | 4872 | p = find_process_by_pid(pid); |
4788 | if (!p) { | 4873 | /* Don't set affinity if task not found and for LITMUS tasks */ |
4874 | if (!p || is_realtime(p)) { | ||
4789 | rcu_read_unlock(); | 4875 | rcu_read_unlock(); |
4790 | put_online_cpus(); | 4876 | put_online_cpus(); |
4791 | return -ESRCH; | 4877 | return p ? -EPERM : -ESRCH; |
4792 | } | 4878 | } |
4793 | 4879 | ||
4794 | /* Prevent p going away */ | 4880 | /* Prevent p going away */ |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 5a5ea2cd924f..b1af6d42c024 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -1708,7 +1708,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ | |||
1708 | int sync = wake_flags & WF_SYNC; | 1708 | int sync = wake_flags & WF_SYNC; |
1709 | int scale = cfs_rq->nr_running >= sched_nr_latency; | 1709 | int scale = cfs_rq->nr_running >= sched_nr_latency; |
1710 | 1710 | ||
1711 | if (unlikely(rt_prio(p->prio))) | 1711 | if (unlikely(rt_prio(p->prio)) || p->policy == SCHED_LITMUS) |
1712 | goto preempt; | 1712 | goto preempt; |
1713 | 1713 | ||
1714 | if (unlikely(p->sched_class != &fair_sched_class)) | 1714 | if (unlikely(p->sched_class != &fair_sched_class)) |
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index b5b920ae2ea7..c2fbb02c1b54 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
@@ -1014,7 +1014,7 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p) | |||
1014 | */ | 1014 | */ |
1015 | static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flags) | 1015 | static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flags) |
1016 | { | 1016 | { |
1017 | if (p->prio < rq->curr->prio) { | 1017 | if (p->prio < rq->curr->prio || p->policy == SCHED_LITMUS) { |
1018 | resched_task(rq->curr); | 1018 | resched_task(rq->curr); |
1019 | return; | 1019 | return; |
1020 | } | 1020 | } |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f992762d7f51..0adc54bd7c7c 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -721,6 +721,46 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) | |||
721 | } | 721 | } |
722 | 722 | ||
723 | /** | 723 | /** |
724 | * tick_set_quanta_type - get the quanta type as a boot option | ||
725 | * Default is standard setup with ticks staggered over first | ||
726 | * half of tick period. | ||
727 | */ | ||
728 | int quanta_type = LINUX_DEFAULT_TICKS; | ||
729 | static int __init tick_set_quanta_type(char *str) | ||
730 | { | ||
731 | if (strcmp("aligned", str) == 0) { | ||
732 | quanta_type = LITMUS_ALIGNED_TICKS; | ||
733 | printk(KERN_INFO "LITMUS^RT: setting aligned quanta\n"); | ||
734 | } | ||
735 | else if (strcmp("staggered", str) == 0) { | ||
736 | quanta_type = LITMUS_STAGGERED_TICKS; | ||
737 | printk(KERN_INFO "LITMUS^RT: setting staggered quanta\n"); | ||
738 | } | ||
739 | return 1; | ||
740 | } | ||
741 | __setup("quanta=", tick_set_quanta_type); | ||
742 | |||
743 | u64 cpu_stagger_offset(int cpu) | ||
744 | { | ||
745 | u64 offset = 0; | ||
746 | switch (quanta_type) { | ||
747 | case LITMUS_ALIGNED_TICKS: | ||
748 | offset = 0; | ||
749 | break; | ||
750 | case LITMUS_STAGGERED_TICKS: | ||
751 | offset = ktime_to_ns(tick_period); | ||
752 | do_div(offset, num_possible_cpus()); | ||
753 | offset *= cpu; | ||
754 | break; | ||
755 | default: | ||
756 | offset = ktime_to_ns(tick_period) >> 1; | ||
757 | do_div(offset, num_possible_cpus()); | ||
758 | offset *= cpu; | ||
759 | } | ||
760 | return offset; | ||
761 | } | ||
762 | |||
763 | /** | ||
724 | * tick_setup_sched_timer - setup the tick emulation timer | 764 | * tick_setup_sched_timer - setup the tick emulation timer |
725 | */ | 765 | */ |
726 | void tick_setup_sched_timer(void) | 766 | void tick_setup_sched_timer(void) |
@@ -737,9 +777,11 @@ void tick_setup_sched_timer(void) | |||
737 | 777 | ||
738 | /* Get the next period (per cpu) */ | 778 | /* Get the next period (per cpu) */ |
739 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); | 779 | hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); |
740 | offset = ktime_to_ns(tick_period) >> 1; | 780 | |
741 | do_div(offset, num_possible_cpus()); | 781 | /* Offset must be set correctly to achieve desired quanta type. */ |
742 | offset *= smp_processor_id(); | 782 | offset = cpu_stagger_offset(smp_processor_id()); |
783 | |||
784 | /* Add the correct offset to expiration time */ | ||
743 | hrtimer_add_expires_ns(&ts->sched_timer, offset); | 785 | hrtimer_add_expires_ns(&ts->sched_timer, offset); |
744 | 786 | ||
745 | for (;;) { | 787 | for (;;) { |