aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-06-14 02:37:32 -0400
committerGlenn Elliott <gelliott@cs.unc.edu>2012-06-14 02:37:32 -0400
commit836633b4ee918091913d701379f814394c939de7 (patch)
tree57f1d564954e7b2454481d4914446ee1dfb57eb8
parent63360ea7ec23f403462e5335d4a3aed9d756a24e (diff)
Scheduling of PGM jobs.wip-rtas12-pgm
-rw-r--r--include/litmus/rt_param.h7
-rw-r--r--litmus/pgm.c93
-rw-r--r--litmus/sched_gsn_edf.c6
3 files changed, 78 insertions, 28 deletions
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index a767e52882f4..5411f1251e57 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -129,8 +129,11 @@ struct pgm_consume
129struct rt_pgm { 129struct rt_pgm {
130 struct pgm_produce *produce; /* output and current state */ 130 struct pgm_produce *produce; /* output and current state */
131 struct pgm_consume *consume; /* input constraints and current state */ 131 struct pgm_consume *consume; /* input constraints and current state */
132 struct task_struct *root; /* root node of the PGM */ 132 struct task_struct *src; /* root node of the PGM */
133// struct task_struct *src; /* only not NULL if task is sink */ 133
134 /* only valid for source nodes */
135 struct completion children_ready;
136 atomic_t nr_children_pending;
134}; 137};
135 138
136#endif /* end PGM */ 139#endif /* end PGM */
diff --git a/litmus/pgm.c b/litmus/pgm.c
index 661fb2065dea..fe67d8f95d17 100644
--- a/litmus/pgm.c
+++ b/litmus/pgm.c
@@ -1,6 +1,8 @@
1 1
2#include <linux/slab.h> 2#include <linux/slab.h>
3#include <linux/spinlock.h> 3#include <linux/spinlock.h>
4#include <linux/completion.h>
5#include <linux/atomic.h>
4 6
5#include <litmus/pgm.h> 7#include <litmus/pgm.h>
6#include <litmus/sched_plugin.h> 8#include <litmus/sched_plugin.h>
@@ -11,7 +13,7 @@
11 13
12static void pgm_consume(struct task_struct *t); 14static void pgm_consume(struct task_struct *t);
13static void pgm_produce_intermediate(struct task_struct *t); 15static void pgm_produce_intermediate(struct task_struct *t);
14static void pgm_produce_root(struct task_struct *t); 16static void pgm_produce_src(struct task_struct *t);
15 17
16 18
17static inline int __is_pgm_satisfied(struct task_struct *t) 19static inline int __is_pgm_satisfied(struct task_struct *t)
@@ -41,10 +43,18 @@ static void pgm_produce(struct task_struct *t)
41 pgm_produce_intermediate(t); 43 pgm_produce_intermediate(t);
42 } 44 }
43 else { 45 else {
44 pgm_produce_root(t); 46 pgm_produce_src(t);
45 } 47 }
46} 48}
47 49
50static void pgm_prepare_to_wake(struct task_struct *t)
51{
52 // 't' is not a source node.
53
54 set_task_state(t, TASK_RUNNING);
55
56 /* TODO: Set our deadline! */
57}
48 58
49static void pgm_produce_intermediate(struct task_struct *t) 59static void pgm_produce_intermediate(struct task_struct *t)
50{ 60{
@@ -111,6 +121,7 @@ static void pgm_produce_intermediate(struct task_struct *t)
111 if(release_child) 121 if(release_child)
112 { 122 {
113 pgm_consume(child); 123 pgm_consume(child);
124 pgm_prepare_to_wake(child);
114 125
115 TRACE_TASK(t, "waking up %s/%d\n", child->comm, child->pid); 126 TRACE_TASK(t, "waking up %s/%d\n", child->comm, child->pid);
116 litmus->task_wake_up(child); 127 litmus->task_wake_up(child);
@@ -119,18 +130,18 @@ static void pgm_produce_intermediate(struct task_struct *t)
119} 130}
120 131
121 132
122static void pgm_produce_root(struct task_struct *t) 133static void pgm_produce_src(struct task_struct *t)
123{ 134{
124 struct task_struct *root; 135 struct task_struct *src;
125 BUG_ON(!is_pgm_sink(t)); 136 BUG_ON(!is_pgm_sink(t));
126 137
127 root = tsk_rt(t)->pgm_params.root; 138 src = tsk_rt(t)->pgm_params.src;
128 139
129 TRACE_TASK(t, "waking up PGM root %s/%d\n", 140 TRACE_TASK(t, "waking up PGM src %s/%d\n",
130 root->comm, root->pid); 141 src->comm, src->pid);
131 142
132 /* wake up the new task, the task will sleep if it is too soon. */ 143 /* wake up the new task, the task will sleep if it is too soon. */
133 litmus->task_wake_up(root); 144 litmus->task_wake_up(src);
134} 145}
135 146
136 147
@@ -183,9 +194,27 @@ int is_pgm_satisfied(struct task_struct *t)
183 194
184void pgm_prepare_for_next_period(struct task_struct *t) 195void pgm_prepare_for_next_period(struct task_struct *t)
185{ 196{
197 BUG_ON(!t);
198
186 TRACE_TASK(t, "pgm_prepage_for_next_period().\n"); 199 TRACE_TASK(t, "pgm_prepage_for_next_period().\n");
187 200
188 prepare_for_next_period(t); 201 if(is_pgm_src(t)) {
202 prepare_for_next_period(t);
203 }
204 else {
205 // We defer setting up release and deadline times
206 // up to wake-time. This makes handling the deadline
207 // of the first job properly.
208
209 tsk_rt(t)->job_params.exec_time = 0;
210 ++(tsk_rt(t)->job_params.job_no);
211 t->rt.time_slice = 1; // don't confuse Linux (??)
212 }
213
214 // DANGER! We're setting an UNINTERRUPTIBLE state
215 // without going on a wait queue! Better hope the
216 // PGM sources do their work...
217 set_task_state(t, TASK_UNINTERRUPTIBLE);
189} 218}
190 219
191 220
@@ -230,7 +259,7 @@ int pgm_complete_job(struct task_struct *t)
230 } 259 }
231 260
232 /* produce new tokens, possibly waking up children, 261 /* produce new tokens, possibly waking up children,
233 * or setup for the next PGM root. 262 * or setup for the next PGM src.
234 */ 263 */
235 pgm_produce(t); 264 pgm_produce(t);
236 265
@@ -245,13 +274,6 @@ int do_pgm_add_edge(struct task_struct *a, int nr_gen,
245 struct pgm_produce *prod; 274 struct pgm_produce *prod;
246 struct pgm_consume *cons; 275 struct pgm_consume *cons;
247 276
248 // validation of parameters takes place upstream.
249
250 if(!is_pgm(a)) {
251 // 'a' is the root. set itself as such.
252 tsk_rt(a)->pgm_params.root = a;
253 }
254
255 if(tsk_rt(a)->pgm_params.produce == NULL) { 277 if(tsk_rt(a)->pgm_params.produce == NULL) {
256 tsk_rt(a)->pgm_params.produce = 278 tsk_rt(a)->pgm_params.produce =
257 kmalloc(sizeof(pgm_produce), GFP_KERNEL); 279 kmalloc(sizeof(pgm_produce), GFP_KERNEL);
@@ -288,9 +310,6 @@ int do_pgm_add_edge(struct task_struct *a, int nr_gen,
288 __set_bit(cons->nr_consumptions, cons->unsatisfied); 310 __set_bit(cons->nr_consumptions, cons->unsatisfied);
289 ++(cons->nr_consumptions); 311 ++(cons->nr_consumptions);
290 312
291 // copy over root node from a to b
292 tsk_rt(b)->pgm_params.root = tsk_rt(a)->pgm_params.root;
293
294 // mark as pgm nodes 313 // mark as pgm nodes
295 tsk_rt(a)->is_pgm_node = 1; 314 tsk_rt(a)->is_pgm_node = 1;
296 tsk_rt(b)->is_pgm_node = 1; 315 tsk_rt(b)->is_pgm_node = 1;
@@ -299,13 +318,25 @@ out:
299 return retval; 318 return retval;
300} 319}
301 320
302int do_pgm_signal_ready(struct task_struct *root) 321int do_pgm_signal_ready(struct task_struct *src)
303{ 322{
304 int retval = -EINVAL; 323 int retval = -EINVAL;
324 int num_remaining;
325 struct task_struct *t = current;
305 326
306 tsk_rt(current)->pgm_params.root = root; 327 tsk_rt(t)->pgm_params.src = src;
328
329 num_remaining =
330 atomic_dec_return(&tsk_rt(src)->pgm_params.nr_children_pending);
331
332 if(num_remaining == 0) {
333 complete(&tsk_rt(src)->pgm_params.children_ready);
334 }
307 335
308 /* decrement the parent's semaphore and then suspend */ 336 // pray that our parent wakes us up.
337 set_task_state(t, TASK_UNINTERRUPTIBLE);
338 schedule();
339 retval = 0;
309 340
310 return retval; 341 return retval;
311} 342}
@@ -313,19 +344,29 @@ int do_pgm_signal_ready(struct task_struct *root)
313int do_pgm_set_nr_children(int nr_children) 344int do_pgm_set_nr_children(int nr_children)
314{ 345{
315 int retval = -EINVAL; 346 int retval = -EINVAL;
347 struct task_struct *src = current;
316 348
317 /* TODO: set up a counting semaphore */ 349 if(!is_pgm_src(src))
350 goto out;
351
352 init_completion(&tsk_rt(src)->pgm_params.children_ready);
353 atomic_set(&tsk_rt(src)->pgm_params.nr_children_pending, nr_children);
318 354
355out:
319 return retval; 356 return retval;
320} 357}
321 358
322int do_pgm_wait_for_children(void) 359int do_pgm_wait_for_children(void)
323{ 360{
324 int retval = -EINVAL; 361 int retval = -EINVAL;
325 struct task_struct *root = current; 362 struct task_struct *src = current;
326 363
327 /* TODO: sleep on a counting semaphore */ 364 if(!is_pgm_src(src))
365 goto out;
366
367 wait_for_completion(&tsk_rt(src)->pgm_params.children_ready);
328 368
369out:
329 return retval; 370 return retval;
330} 371}
331 372
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index c1145fc1dc8c..ca877938f729 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -640,6 +640,8 @@ static void gsnedf_task_wake_up(struct task_struct *task)
640 TRACE_TASK(task, "wake_up at %llu\n", litmus_clock()); 640 TRACE_TASK(task, "wake_up at %llu\n", litmus_clock());
641 641
642 raw_spin_lock_irqsave(&gsnedf_lock, flags); 642 raw_spin_lock_irqsave(&gsnedf_lock, flags);
643
644#if 0
643 /* We need to take suspensions because of semaphores into 645 /* We need to take suspensions because of semaphores into
644 * account! If a job resumes after being suspended due to acquiring 646 * account! If a job resumes after being suspended due to acquiring
645 * a semaphore, it should never be treated as a new job release. 647 * a semaphore, it should never be treated as a new job release.
@@ -661,6 +663,10 @@ static void gsnedf_task_wake_up(struct task_struct *task)
661 } 663 }
662 } 664 }
663 } 665 }
666#else // periodic task model
667 set_rt_flags(task, RT_F_RUNNING);
668#endif
669
664 gsnedf_job_arrival(task); 670 gsnedf_job_arrival(task);
665 raw_spin_unlock_irqrestore(&gsnedf_lock, flags); 671 raw_spin_unlock_irqrestore(&gsnedf_lock, flags);
666} 672}