From 4b38febbd59fd33542a343991262119eb9860f5e Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Thu, 17 Dec 2009 21:23:36 -0500 Subject: [ported from 2008.3] Core LITMUS^RT infrastructure Port 2008.3 Core LITMUS^RT infrastructure to Linux 2.6.32 litmus_sched_class implements 4 new methods: - prio_changed: void - switched_to: void - get_rr_interval: return infinity (i.e., 0) - select_task_rq: return current cpu --- kernel/sched.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 8 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 3c11ae0a948..fcaed6b9644 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -77,6 +77,9 @@ #include "sched_cpupri.h" +#include +#include + #define CREATE_TRACE_POINTS #include @@ -571,6 +574,8 @@ struct rq { atomic_t nr_iowait; + struct task_struct *litmus_next; + #ifdef CONFIG_SMP struct root_domain *rd; struct sched_domain *sd; @@ -1815,11 +1820,12 @@ static void calc_load_account_active(struct rq *this_rq); #include "sched_idletask.c" #include "sched_fair.c" #include "sched_rt.c" +#include "../litmus/sched_litmus.c" #ifdef CONFIG_SCHED_DEBUG # include "sched_debug.c" #endif -#define sched_class_highest (&rt_sched_class) +#define sched_class_highest (&litmus_sched_class) #define for_each_class(class) \ for (class = sched_class_highest; class; class = class->next) @@ -2343,6 +2349,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, unsigned long flags; struct rq *rq, *orig_rq; + if (is_realtime(p)) + TRACE_TASK(p, "try_to_wake_up() state:%d\n", p->state); + if (!sched_feat(SYNC_WAKEUPS)) wake_flags &= ~WF_SYNC; @@ -2361,7 +2370,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, orig_cpu = cpu; #ifdef CONFIG_SMP - if (unlikely(task_running(rq, p))) + if (unlikely(task_running(rq, p)) || is_realtime(p)) goto out_activate; /* @@ -2442,6 +2451,8 @@ out_running: p->sched_class->task_wake_up(rq, p); #endif out: + if (is_realtime(p)) + TRACE_TASK(p, "try_to_wake_up() done state:%d\n", p->state); task_rq_unlock(rq, &flags); put_cpu(); @@ -2750,6 +2761,8 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) */ prev_state = prev->state; finish_arch_switch(prev); + litmus->finish_switch(prev); + prev->rt_param.stack_in_use = NO_CPU; perf_event_task_sched_in(current, cpu_of(rq)); finish_lock_switch(rq, prev); @@ -5232,18 +5245,31 @@ void scheduler_tick(void) sched_clock_tick(); + TS_TICK_START(current); + spin_lock(&rq->lock); update_rq_clock(rq); update_cpu_load(rq); curr->sched_class->task_tick(rq, curr, 0); + + /* + * LITMUS_TODO: can we move litmus_tick inside task_tick + * or will deadlock ? + */ + TS_PLUGIN_TICK_START; + litmus_tick(rq, curr); + TS_PLUGIN_TICK_END; + spin_unlock(&rq->lock); perf_event_task_tick(curr, cpu); #ifdef CONFIG_SMP rq->idle_at_tick = idle_cpu(cpu); - trigger_load_balance(rq, cpu); + if (!is_realtime(current)) + trigger_load_balance(rq, cpu); #endif + TS_TICK_END(current); } notrace unsigned long get_parent_ip(unsigned long addr) @@ -5387,11 +5413,17 @@ pick_next_task(struct rq *rq) * Optimization: we know that if all tasks are in * the fair class we can call that function directly: */ + /* + * LITMUS_TODO: can we move processes out of fair class? + * i.e., create a litmus_rq + */ + /* Don't do this for LITMUS if (likely(rq->nr_running == rq->cfs.nr_running)) { p = fair_sched_class.pick_next_task(rq); if (likely(p)) return p; } + */ class = sched_class_highest; for ( ; ; ) { @@ -5426,6 +5458,8 @@ need_resched: release_kernel_lock(prev); need_resched_nonpreemptible: + TS_SCHED_START; + sched_trace_task_switch_away(prev); schedule_debug(prev); @@ -5436,6 +5470,14 @@ need_resched_nonpreemptible: update_rq_clock(rq); clear_tsk_need_resched(prev); + /* + * LITMUS_TODO: can we integrate litmus_schedule in + * pick_next_task? + */ + TS_PLUGIN_SCHED_START; + litmus_schedule(rq, prev); + TS_PLUGIN_SCHED_END; + if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { if (unlikely(signal_pending_state(prev->state, prev))) prev->state = TASK_RUNNING; @@ -5460,22 +5502,35 @@ need_resched_nonpreemptible: rq->curr = next; ++*switch_count; + TS_SCHED_END(next); + TS_CXS_START(next); context_switch(rq, prev, next); /* unlocks the rq */ + TS_CXS_END(current); /* * the context switch might have flipped the stack from under * us, hence refresh the local variables. */ cpu = smp_processor_id(); rq = cpu_rq(cpu); - } else + } else { + TS_SCHED_END(prev); spin_unlock_irq(&rq->lock); + } + + TS_SCHED2_START(current); + sched_trace_task_switch_to(current); post_schedule(rq); - if (unlikely(reacquire_kernel_lock(current) < 0)) + if (unlikely(reacquire_kernel_lock(current) < 0)) { + TS_SCHED2_END(current); goto need_resched_nonpreemptible; + } preempt_enable_no_resched(); + + TS_SCHED2_END(current); + if (need_resched()) goto need_resched; } @@ -6185,6 +6240,9 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) case SCHED_RR: p->sched_class = &rt_sched_class; break; + case SCHED_LITMUS: + p->sched_class = &litmus_sched_class; + break; } p->rt_priority = prio; @@ -6232,7 +6290,7 @@ recheck: if (policy != SCHED_FIFO && policy != SCHED_RR && policy != SCHED_NORMAL && policy != SCHED_BATCH && - policy != SCHED_IDLE) + policy != SCHED_IDLE && policy != SCHED_LITMUS) return -EINVAL; } @@ -6247,6 +6305,8 @@ recheck: return -EINVAL; if (rt_policy(policy) != (param->sched_priority != 0)) return -EINVAL; + if (policy == SCHED_LITMUS && policy == p->policy) + return -EINVAL; /* * Allow unprivileged RT tasks to decrease priority: @@ -6301,6 +6361,12 @@ recheck: return retval; } + if (policy == SCHED_LITMUS) { + retval = litmus_admit_task(p); + if (retval) + return retval; + } + /* * make sure no PI-waiters arrive (or leave) while we are * changing the priority of the task: @@ -6328,9 +6394,18 @@ recheck: p->sched_reset_on_fork = reset_on_fork; + if (p->policy == SCHED_LITMUS) + litmus_exit_task(p); + oldprio = p->prio; __setscheduler(rq, p, policy, param->sched_priority); + if (policy == SCHED_LITMUS) { + p->rt_param.stack_in_use = running ? rq->cpu : NO_CPU; + p->rt_param.present = running; + litmus->task_new(p, on_rq, running); + } + if (running) p->sched_class->set_curr_task(rq); if (on_rq) { @@ -6500,10 +6575,11 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) read_lock(&tasklist_lock); p = find_process_by_pid(pid); - if (!p) { + /* Don't set affinity if task not found and for LITMUS tasks */ + if (!p || is_realtime(p)) { read_unlock(&tasklist_lock); put_online_cpus(); - return -ESRCH; + return p ? -EPERM : -ESRCH; } /* -- cgit v1.2.2 From 59d8d4c53f1e9f6408b87fc22e319e78f664276f Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Thu, 17 Dec 2009 21:29:31 -0500 Subject: [ported from 2008.3] Add complete_n() call --- kernel/sched.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index fcaed6b9644..328a67c5528 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5809,6 +5809,17 @@ void complete_all(struct completion *x) } EXPORT_SYMBOL(complete_all); +void complete_n(struct completion *x, int n) +{ + unsigned long flags; + + spin_lock_irqsave(&x->wait.lock, flags); + x->done += n; + __wake_up_common(&x->wait, TASK_NORMAL, n, 0, NULL); + spin_unlock_irqrestore(&x->wait.lock, flags); +} +EXPORT_SYMBOL(complete_n); + static inline long __sched do_wait_for_common(struct completion *x, long timeout, int state) { -- cgit v1.2.2 From 5442a8adfce93c1cd556e04bfc0a118adc3b683e Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Thu, 17 Dec 2009 21:34:09 -0500 Subject: [ported from 2008.3] Add Stack Resource Policy (SRP) support --- kernel/sched.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 328a67c5528..ee894ee8a0b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5533,6 +5533,9 @@ need_resched_nonpreemptible: if (need_resched()) goto need_resched; + + if (srp_active()) + srp_ceiling_block(); } EXPORT_SYMBOL(schedule); -- cgit v1.2.2 From e68debebdc2983600063cd6b04c6a51c4b7ddcc1 Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Fri, 28 May 2010 10:25:34 -0400 Subject: Integrate litmus_tick() in task_tick_litmus() - remove the call to litmus_tick() from scheduler_tick() just after having performed the class task_tick() and integrate litmus_tick() in task_tick_litmus() - task_tick_litmus() is the handler for the litmus class task_tick() method. It is called in non-queued mode from scheduler_tick() --- kernel/sched.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index ee894ee8a0b..9ad41979c0b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -485,6 +485,11 @@ struct rt_rq { #endif }; +/* Litmus related fields in a runqueue */ +struct litmus_rq { + struct task_struct *prev; +}; + #ifdef CONFIG_SMP /* @@ -549,6 +554,7 @@ struct rq { struct cfs_rq cfs; struct rt_rq rt; + struct litmus_rq litmus; #ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */ @@ -574,8 +580,6 @@ struct rq { atomic_t nr_iowait; - struct task_struct *litmus_next; - #ifdef CONFIG_SMP struct root_domain *rd; struct sched_domain *sd; @@ -2786,6 +2790,15 @@ static inline void pre_schedule(struct rq *rq, struct task_struct *prev) { if (prev->sched_class->pre_schedule) prev->sched_class->pre_schedule(rq, prev); + + /* LITMUS^RT not very clean hack: we need to save the prev task + * as our scheduling decision rely on it (as we drop the rq lock + * something in prev can change...); there is no way to escape + * this ack apart from modifying pick_nex_task(rq, _prev_) or + * falling back on the previous solution of decoupling + * scheduling decisions + */ + rq->litmus.prev = prev; } /* rq->lock is NOT held, but preemption is disabled */ @@ -5252,13 +5265,8 @@ void scheduler_tick(void) update_cpu_load(rq); curr->sched_class->task_tick(rq, curr, 0); - /* - * LITMUS_TODO: can we move litmus_tick inside task_tick - * or will deadlock ? - */ - TS_PLUGIN_TICK_START; + /* litmus_tick may force current to resched */ litmus_tick(rq, curr); - TS_PLUGIN_TICK_END; spin_unlock(&rq->lock); @@ -5470,14 +5478,6 @@ need_resched_nonpreemptible: update_rq_clock(rq); clear_tsk_need_resched(prev); - /* - * LITMUS_TODO: can we integrate litmus_schedule in - * pick_next_task? - */ - TS_PLUGIN_SCHED_START; - litmus_schedule(rq, prev); - TS_PLUGIN_SCHED_END; - if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { if (unlikely(signal_pending_state(prev->state, prev))) prev->state = TASK_RUNNING; -- cgit v1.2.2 From a084c01569bcfe13fd880a0b1e3a9026629a89da Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Fri, 28 May 2010 10:30:29 -0400 Subject: Better explanation of jump-to-CFS optimization removal GSN-EDF and friends rely on being called even if there is currently no runnable real-time task on the runqueue for (at least) two reasons: 1) To initiate migrations. LITMUS^RT pull tasks for migrations; this requires plugins to be called even if no task is currently present. 2) To maintain invariants when jobs block. --- kernel/sched.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 9ad41979c0b..1701eaebb79 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -487,6 +487,7 @@ struct rt_rq { /* Litmus related fields in a runqueue */ struct litmus_rq { + unsigned long nr_running; struct task_struct *prev; }; @@ -5420,13 +5421,15 @@ pick_next_task(struct rq *rq) /* * Optimization: we know that if all tasks are in * the fair class we can call that function directly: - */ - /* - * LITMUS_TODO: can we move processes out of fair class? - * i.e., create a litmus_rq - */ - /* Don't do this for LITMUS - if (likely(rq->nr_running == rq->cfs.nr_running)) { + + * NOT IN LITMUS^RT! + + * This breaks many assumptions in the plugins. + * Do not uncomment without thinking long and hard + * about how this affects global plugins such as GSN-EDF. + + if (rq->nr_running == rq->cfs.nr_running) { + TRACE("taking shortcut in pick_next_task()\n"); p = fair_sched_class.pick_next_task(rq); if (likely(p)) return p; -- cgit v1.2.2 From 8fe2fb8bb1c1cd0194608bc783d0ce7029e8d869 Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Mon, 26 Apr 2010 13:42:00 -0400 Subject: Measure timer re-arming in the proper location hrtimers are properly rearmed during arm_release_timer() and no longer after rescheduling (with the norqlock mechanism of 2008.3). This commit accordingly updates the locations where measures are taken. --- kernel/sched.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 1701eaebb79..adb5e923cc6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5520,20 +5520,16 @@ need_resched_nonpreemptible: spin_unlock_irq(&rq->lock); } - TS_SCHED2_START(current); sched_trace_task_switch_to(current); post_schedule(rq); if (unlikely(reacquire_kernel_lock(current) < 0)) { - TS_SCHED2_END(current); goto need_resched_nonpreemptible; } preempt_enable_no_resched(); - TS_SCHED2_END(current); - if (need_resched()) goto need_resched; -- cgit v1.2.2 From 516b6601bb5f71035e8859735a25dea0da4a0211 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Mon, 8 Nov 2010 20:21:35 -0500 Subject: hook litmus tick function into hrtimer-driven ticks Litmus plugins should also be activated if ticks are triggered by hrtimer. --- kernel/sched.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 6777dc7942a..a9dd6f96c73 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -82,6 +82,8 @@ #include #include +static void litmus_tick(struct rq*, struct task_struct*); + #define CREATE_TRACE_POINTS #include @@ -1052,6 +1054,7 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer) raw_spin_lock(&rq->lock); update_rq_clock(rq); rq->curr->sched_class->task_tick(rq, rq->curr, 1); + litmus_tick(rq, rq->curr); raw_spin_unlock(&rq->lock); return HRTIMER_NORESTART; -- cgit v1.2.2 From fb3df2ec261d8cd6bcb8206d9d985355214d7767 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Wed, 10 Nov 2010 12:10:49 -0500 Subject: Implement proper remote preemption support To date, Litmus has just hooked into the smp_send_reschedule() IPI handler and marked tasks as having to reschedule to implement remote preemptions. This was never particularly clean, but so far we got away with it. However, changes in the underlying Linux, and peculartities of the ARM code (interrupts enabled before context switch) break this naive approach. This patch introduces new state-machine based remote preemption support. By examining the local state before calling set_tsk_need_resched(), we avoid confusing the underlying Linux scheduler. Further, this patch avoids sending unncessary IPIs. --- kernel/sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index a9dd6f96c73..60fbae0c747 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3794,6 +3794,7 @@ asmlinkage void __sched schedule(void) need_resched: preempt_disable(); + sched_state_entered_schedule(); cpu = smp_processor_id(); rq = cpu_rq(cpu); rcu_note_context_switch(cpu); @@ -3872,7 +3873,7 @@ need_resched_nonpreemptible: post_schedule(rq); - if (unlikely(reacquire_kernel_lock(prev))) + if (sched_state_validate_switch() || unlikely(reacquire_kernel_lock(prev))) goto need_resched_nonpreemptible; preempt_enable_no_resched(); -- cgit v1.2.2 From 6fbc3b495cccf2e4ab7d4ab674b5c576e9946bed Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Thu, 11 Nov 2010 16:54:20 -0500 Subject: Workaround: do not set rq->skip_clock_update Disabling the clock update seems to be causing problems even in normal Linux, and causes major bugs under LITMUS^RT. As a workaround, just disable this "optimization" for now. Details: the idle load balancer causes tasks that suspsend to be marked with set_tsk_need_resched(). When such a task resumes, it may wrongly trigger the setting of skip_clock_update. However, a corresponding rescheduling event may not happen immediately, such that the currently-scheduled task is no longer charged for its execution time. --- kernel/sched.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 60fbae0c747..1b13c8e1cfc 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -578,8 +578,14 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags) * A queue event has occurred, and we're going to schedule. In * this case, we can save a useless back to back clock update. */ + /* LITMUS^RT: turning off the clock update is buggy in Linux 2.6.36; + * the scheduler can "forget" to renable the runqueue clock in some + * cases. LITMUS^RT amplifies the effects of this problem. Hence, we + * turn it off to avoid stalling clocks. */ + /* if (test_tsk_need_resched(p)) rq->skip_clock_update = 1; + */ } static inline int cpu_of(struct rq *rq) -- cgit v1.2.2 From 904531a6321964579ab0972a8833616e97dbf582 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Sat, 29 Jan 2011 20:31:57 -0500 Subject: bugfix: don't let children stay Litmus real-time tasks It has always been LITMUS^RT policy that children of real-time tasks may not skip the admissions test, etc. This used to be enforced, but was apparently dropped during some port. This commit re-introduces this policy. This fixes a kernel panic that occurred when "real-time children" exited without proper initilization. --- kernel/sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 1b13c8e1cfc..5beefb2e797 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2557,7 +2557,8 @@ void sched_fork(struct task_struct *p, int clone_flags) * Revert to default priority/policy on fork if requested. */ if (unlikely(p->sched_reset_on_fork)) { - if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) { + if (p->policy == SCHED_FIFO || p->policy == SCHED_RR || + p->policy == SCHED_LITMUS) { p->policy = SCHED_NORMAL; p->normal_prio = p->static_prio; } -- cgit v1.2.2 From cc602187d4466374bca031039e145aa1b89aca96 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Fri, 28 Jan 2011 16:41:16 -0500 Subject: Litmus core: replace FMLP & SRP system calls with generic syscalls This renders the FMLP and SRP unfunctional until they are ported to the new locking API. --- kernel/sched.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 5beefb2e797..c5d77507902 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3887,8 +3887,7 @@ need_resched_nonpreemptible: if (need_resched()) goto need_resched; - if (srp_active()) - srp_ceiling_block(); + srp_ceiling_block(); } EXPORT_SYMBOL(schedule); -- cgit v1.2.2 From fb8d6602af1cbc09115544056b872b976c6349c3 Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Wed, 24 Aug 2011 17:32:21 +0200 Subject: Prevent Linux to send IPI and queue tasks on remote CPUs. Whether to send IPIs and enqueue tasks on remote runqueues is plugin-specific. The recent ttwu_queue() mechanism (by calling ttwu_queue_remote()) interferes with Litmus plugin decisions. --- kernel/sched.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 935f8e8e616..baaca61bc3a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2661,7 +2661,12 @@ static void ttwu_queue(struct task_struct *p, int cpu) struct rq *rq = cpu_rq(cpu); #if defined(CONFIG_SMP) - if (sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) { + /* + * LITMUS^RT: whether to send an IPI to the remote CPU + * is plugin specific. + */ + if (!is_realtime(p) && + sched_feat(TTWU_QUEUE) && cpu != smp_processor_id()) { sched_clock_cpu(cpu); /* sync clocks x-cpu */ ttwu_queue_remote(p, cpu); return; -- cgit v1.2.2 From 26bafa3b7880a323d83b8ea71bdb8e2118a5cba0 Mon Sep 17 00:00:00 2001 From: Andrea Bastoni Date: Sat, 11 Feb 2012 21:41:19 +0100 Subject: Add kernel-style events for sched_trace_XXX() functions Enable kernel-style events (tracepoint) for Litmus. Litmus events trace the same functions as the sched_trace_XXX(), but can be enabled independently. So, why another tracing infrastructure then: - Litmus tracepoints can be recorded and analyzed together (single time reference) with all other kernel tracing events (e.g., sched:sched_switch, etc.). It's easier to correlate the effects of kernel events on litmus tasks. - It enables a quick way to visualize and process schedule traces using trace-cmd utility and kernelshark visualizer. Kernelshark lacks unit-trace's schedule-correctness checks, but it enables a fast view of schedule traces and it has several filtering options (for all kernel events, not only Litmus'). --- kernel/sched.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index baaca61bc3a..2229d0deec4 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -80,14 +80,14 @@ #include "workqueue_sched.h" #include "sched_autogroup.h" +#define CREATE_TRACE_POINTS +#include + #include #include static void litmus_tick(struct rq*, struct task_struct*); -#define CREATE_TRACE_POINTS -#include - /* * Convert user-nice values [ -20 ... 0 ... 19 ] * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], -- cgit v1.2.2 From 9434d607f4ddaf2374dafd86c20ed4336230ecfa Mon Sep 17 00:00:00 2001 From: Glenn Elliott Date: Mon, 17 Sep 2012 09:57:37 -0400 Subject: Do processor state transitions in schedule_tail(). Fixes a bug in Litmus where processor scheduling states could become corrupted. Corruption can occur when a just-forked thread is externally forced to be scheduled by SCHED_LITMUS before this just-forked thread can complete post-fork processing. Specifically, before schedule_tail() has completed. --- kernel/sched.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 2229d0deec4..65aba7ec564 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3163,16 +3163,26 @@ static inline void post_schedule(struct rq *rq) asmlinkage void schedule_tail(struct task_struct *prev) __releases(rq->lock) { - struct rq *rq = this_rq(); - + struct rq *rq; + + preempt_disable(); + + rq = this_rq(); finish_task_switch(rq, prev); + sched_trace_task_switch_to(current); + /* * FIXME: do we need to worry about rq being invalidated by the * task_switch? */ post_schedule(rq); + if (sched_state_validate_switch()) + litmus_reschedule_local(); + + preempt_enable(); + #ifdef __ARCH_WANT_UNLOCKED_CTXSW /* In this case, finish_task_switch does not reenable preemption */ preempt_enable(); -- cgit v1.2.2 From d245619060965c2f379fadf6103e7b69a2d1e951 Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Fri, 7 Sep 2012 14:28:59 +0200 Subject: Remove complete_n() API The LITMUS^RT-specific completion API complete_n() is no longer required by the synchronous release code. Let's remove it; one less modification of a core Linux file to maintain during rebasing. --- kernel/sched.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 65aba7ec564..cbb1b5f5711 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4694,17 +4694,6 @@ void complete_all(struct completion *x) } EXPORT_SYMBOL(complete_all); -void complete_n(struct completion *x, int n) -{ - unsigned long flags; - - spin_lock_irqsave(&x->wait.lock, flags); - x->done += n; - __wake_up_common(&x->wait, TASK_NORMAL, n, 0, NULL); - spin_unlock_irqrestore(&x->wait.lock, flags); -} -EXPORT_SYMBOL(complete_n); - static inline long __sched do_wait_for_common(struct completion *x, long timeout, int state) { -- cgit v1.2.2 From a13904d4b6d04278deb6841020dd7dee9867745e Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Tue, 4 Sep 2012 12:45:54 +0200 Subject: Trace IPI-related IRQs with ft_irq_fired() IPIs have some special cases where irq_enter() is not called. This caused ft_irq_fired() to "miss" some rescheduling-related interrupts, which in turn may cause outliers. This patch makes sure ft_irq_fired() is called on scheduling-related IPIs. --- kernel/sched.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index cbb1b5f5711..1d7b38a7ff2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2597,8 +2597,12 @@ void scheduler_ipi(void) struct rq *rq = this_rq(); struct task_struct *list = xchg(&rq->wake_list, NULL); - if (!list) + if (!list) { + /* If we don't call irq_enter(), we need to trigger the IRQ + * tracing manually. */ + ft_irq_fired(); return; + } /* * Not all reschedule IPI handlers call irq_enter/irq_exit, since -- cgit v1.2.2 From ce313ac8c1531c11d670fd84fe2526bbb5f32f85 Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Thu, 6 Sep 2012 11:15:04 +0200 Subject: Move SCHED2 trace points to post_schedule() Linux's post_schedule() scheduling class hook more closely matches what SCHED2 is supposed to trace, namely any scheduling overhead after the context switch. The prior trace points caught timers being armed from finish_switch(), which is already included in the context switch cost CXS. (This patch essentially reverts 8fe2fb8bb1c1cd0194608bc783d0ce7029e8d869). --- kernel/sched.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'kernel/sched.c') diff --git a/kernel/sched.c b/kernel/sched.c index 1d7b38a7ff2..c4b6bd5151f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4417,14 +4417,20 @@ litmus_need_resched_nonpreemptible: raw_spin_unlock_irq(&rq->lock); } + TS_SCHED2_START(prev); sched_trace_task_switch_to(current); post_schedule(rq); - if (sched_state_validate_switch()) + if (sched_state_validate_switch()) { + TS_SCHED2_END(prev); goto litmus_need_resched_nonpreemptible; + } preempt_enable_no_resched(); + + TS_SCHED2_END(prev); + if (need_resched()) goto need_resched; -- cgit v1.2.2