diff options
author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2016-02-14 09:12:22 -0500 |
---|---|---|
committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2016-03-08 10:12:50 -0500 |
commit | ff0e731b2a9789c78349659602b485d38de78bde (patch) | |
tree | df47f0cb37e90705f498e53e9ec890cfce4d0381 | |
parent | a83a958e62cb903e14bc458a5ace4b9f380fc802 (diff) |
LITMUS^RT core: add next_became_invalid() callback
-rw-r--r-- | include/litmus/sched_plugin.h | 8 | ||||
-rw-r--r-- | kernel/sched/litmus.c | 42 | ||||
-rw-r--r-- | litmus/sched_plugin.c | 5 |
3 files changed, 22 insertions, 33 deletions
diff --git a/include/litmus/sched_plugin.h b/include/litmus/sched_plugin.h index 1906a139e6e9..2021e817b243 100644 --- a/include/litmus/sched_plugin.h +++ b/include/litmus/sched_plugin.h | |||
@@ -35,6 +35,11 @@ typedef void (*finish_switch_t)(struct task_struct *prev); | |||
35 | * the scheduler is invoked again. */ | 35 | * the scheduler is invoked again. */ |
36 | typedef bool (*should_wait_for_stack_t)(struct task_struct *next); | 36 | typedef bool (*should_wait_for_stack_t)(struct task_struct *next); |
37 | 37 | ||
38 | /* After dropping the lock to facilitate a pull migration, the task | ||
39 | * state may have changed. In this case, the core notifies the plugin | ||
40 | * with this callback and then invokes the scheduler again. */ | ||
41 | typedef void (*next_became_invalid_t)(struct task_struct *next); | ||
42 | |||
38 | /********************* task state changes ********************/ | 43 | /********************* task state changes ********************/ |
39 | 44 | ||
40 | /* Called to setup a new real-time task. | 45 | /* Called to setup a new real-time task. |
@@ -109,7 +114,10 @@ struct sched_plugin { | |||
109 | /* scheduler invocation */ | 114 | /* scheduler invocation */ |
110 | schedule_t schedule; | 115 | schedule_t schedule; |
111 | finish_switch_t finish_switch; | 116 | finish_switch_t finish_switch; |
117 | |||
118 | /* control over pull migrations */ | ||
112 | should_wait_for_stack_t should_wait_for_stack; | 119 | should_wait_for_stack_t should_wait_for_stack; |
120 | next_became_invalid_t next_became_invalid; | ||
113 | 121 | ||
114 | /* syscall backend */ | 122 | /* syscall backend */ |
115 | complete_job_t complete_job; | 123 | complete_job_t complete_job; |
diff --git a/kernel/sched/litmus.c b/kernel/sched/litmus.c index 4fa5a941a284..8eb9df31ea01 100644 --- a/kernel/sched/litmus.c +++ b/kernel/sched/litmus.c | |||
@@ -121,45 +121,21 @@ litmus_schedule(struct rq *rq, struct task_struct *prev) | |||
121 | } | 121 | } |
122 | #endif | 122 | #endif |
123 | double_rq_lock(rq, other_rq); | 123 | double_rq_lock(rq, other_rq); |
124 | mb(); | ||
125 | if (is_realtime(current) && is_current_running() != was_running) { | ||
126 | TRACE_TASK(prev, | ||
127 | "state changed while we dropped" | ||
128 | " the lock: is_running=%d, was_running=%d\n", | ||
129 | is_current_running(), was_running); | ||
130 | if (is_current_running() && !was_running) { | ||
131 | /* prev task became unblocked | ||
132 | * we need to simulate normal sequence of events | ||
133 | * to scheduler plugins. | ||
134 | */ | ||
135 | litmus->task_block(prev); | ||
136 | litmus->task_wake_up(prev); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | set_task_cpu(next, smp_processor_id()); | 124 | set_task_cpu(next, smp_processor_id()); |
141 | |||
142 | /* DEBUG: now that we have the lock we need to make sure a | ||
143 | * couple of things still hold: | ||
144 | * - it is still a real-time task | ||
145 | * - it is still runnable (could have been stopped) | ||
146 | * If either is violated, then the active plugin is | ||
147 | * doing something wrong. | ||
148 | */ | ||
149 | if (!is_realtime(next) || !tsk_rt(next)->present) { | ||
150 | /* BAD BAD BAD */ | ||
151 | TRACE_TASK(next,"BAD: migration invariant FAILED: " | ||
152 | "rt=%d present=%d\n", | ||
153 | is_realtime(next), | ||
154 | tsk_rt(next)->present); | ||
155 | /* drop the task */ | ||
156 | next = NULL; | ||
157 | } | ||
158 | /* release the other CPU's runqueue, but keep ours */ | 125 | /* release the other CPU's runqueue, but keep ours */ |
159 | raw_spin_unlock(&other_rq->lock); | 126 | raw_spin_unlock(&other_rq->lock); |
160 | } | 127 | } |
161 | #endif | 128 | #endif |
162 | 129 | ||
130 | /* check if the task became invalid while we dropped the lock */ | ||
131 | if (next && (!is_realtime(next) || !tsk_rt(next)->present)) { | ||
132 | TRACE_TASK(next, | ||
133 | "BAD: next (no longer?) valid\n"); | ||
134 | litmus->next_became_invalid(next); | ||
135 | litmus_reschedule_local(); | ||
136 | next = NULL; | ||
137 | } | ||
138 | |||
163 | if (next) { | 139 | if (next) { |
164 | #ifdef CONFIG_SMP | 140 | #ifdef CONFIG_SMP |
165 | next->rt_param.stack_in_use = rq->cpu; | 141 | next->rt_param.stack_in_use = rq->cpu; |
diff --git a/litmus/sched_plugin.c b/litmus/sched_plugin.c index 4007e5129e80..1ff9516cbbfc 100644 --- a/litmus/sched_plugin.c +++ b/litmus/sched_plugin.c | |||
@@ -75,6 +75,10 @@ static bool litmus_dummy_should_wait_for_stack(struct task_struct *next) | |||
75 | return true; /* by default, wait indefinitely */ | 75 | return true; /* by default, wait indefinitely */ |
76 | } | 76 | } |
77 | 77 | ||
78 | static void litmus_dummy_next_became_invalid(struct task_struct *next) | ||
79 | { | ||
80 | } | ||
81 | |||
78 | static long litmus_dummy_admit_task(struct task_struct* tsk) | 82 | static long litmus_dummy_admit_task(struct task_struct* tsk) |
79 | { | 83 | { |
80 | printk(KERN_CRIT "LITMUS^RT: Linux plugin rejects %s/%d.\n", | 84 | printk(KERN_CRIT "LITMUS^RT: Linux plugin rejects %s/%d.\n", |
@@ -192,6 +196,7 @@ int register_sched_plugin(struct sched_plugin* plugin) | |||
192 | CHECK(finish_switch); | 196 | CHECK(finish_switch); |
193 | CHECK(schedule); | 197 | CHECK(schedule); |
194 | CHECK(should_wait_for_stack); | 198 | CHECK(should_wait_for_stack); |
199 | CHECK(next_became_invalid); | ||
195 | CHECK(task_wake_up); | 200 | CHECK(task_wake_up); |
196 | CHECK(task_exit); | 201 | CHECK(task_exit); |
197 | CHECK(task_cleanup); | 202 | CHECK(task_cleanup); |