aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-04-25 23:37:58 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-04-25 23:37:58 -0400
commita030ea79736cd5aa4aef9800f7ce689fbcab5970 (patch)
tree773e79899eaf3c97a1055c68ce2a335e0bd971f1
parent8b936011abd09adcfab5dea0b6fdc7a0c2e5fcce (diff)
sched_color: group locks guarantee timestamp order, have better state checks
-rw-r--r--include/litmus/color.h3
-rw-r--r--include/litmus/dgl.h14
-rw-r--r--include/litmus/rt_param.h4
-rw-r--r--litmus/dgl.c91
-rw-r--r--litmus/sched_color.c26
5 files changed, 102 insertions, 36 deletions
diff --git a/include/litmus/color.h b/include/litmus/color.h
index fb109c4f5b14..8f66bf50d5b7 100644
--- a/include/litmus/color.h
+++ b/include/litmus/color.h
@@ -1,6 +1,9 @@
1#ifndef LITMUS_COLOR_H 1#ifndef LITMUS_COLOR_H
2#define LITMUS_COLOR_H 2#define LITMUS_COLOR_H
3 3
4#define NUM_COLORS 10
5#define NUM_WAYS 5
6
4int color_server_params(int cpu, unsigned long *wcet, unsigned long *period); 7int color_server_params(int cpu, unsigned long *wcet, unsigned long *period);
5 8
6#endif 9#endif
diff --git a/include/litmus/dgl.h b/include/litmus/dgl.h
index 989f6c7d5e8e..2bf61d4a7547 100644
--- a/include/litmus/dgl.h
+++ b/include/litmus/dgl.h
@@ -1,12 +1,15 @@
1#ifndef __DGL_H_ 1#ifndef __DGL_H_
2#define __DGL_H_ 2#define __DGL_H_
3 3
4#include <litmus/color.h>
4#include <linux/list.h> 5#include <linux/list.h>
5 6
6#define NUM_REPLICAS 4 7#define WP(num, word) (num / word + (num % word != 0))
7#define NUM_RESOURCES 4 8
9#define NUM_REPLICAS NUM_WAYS
10#define NUM_RESOURCES NUM_COLORS
8#define MASK_SIZE (sizeof(unsigned long) * 8) 11#define MASK_SIZE (sizeof(unsigned long) * 8)
9#define MASK_WORDS (NUM_RESOURCES/MASK_SIZE + (NUM_RESOURCES%MASK_SIZE != 0)) 12#define MASK_WORDS WP(NUM_RESOURCES, MASK_SIZE)
10 13
11/* 14/*
12 * A request for @replica amount of a single resource. 15 * A request for @replica amount of a single resource.
@@ -24,6 +27,7 @@ struct dgl_group_req {
24 unsigned long requested[MASK_WORDS]; 27 unsigned long requested[MASK_WORDS];
25 unsigned long waiting[MASK_WORDS]; 28 unsigned long waiting[MASK_WORDS];
26 struct dgl_req requests[NUM_RESOURCES]; 29 struct dgl_req requests[NUM_RESOURCES];
30 unsigned long long ts;
27}; 31};
28 32
29/* 33/*
@@ -40,6 +44,10 @@ struct dgl_resource {
40struct dgl { 44struct dgl {
41 struct dgl_resource resources[NUM_RESOURCES]; 45 struct dgl_resource resources[NUM_RESOURCES];
42 struct dgl_group_req* acquired[NR_CPUS]; 46 struct dgl_group_req* acquired[NR_CPUS];
47
48 char requests;
49 char running;
50 unsigned long long ts;
43}; 51};
44 52
45void dgl_init(struct dgl *dgl); 53void dgl_init(struct dgl *dgl);
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h
index e56aab006cc1..2eec39c7678c 100644
--- a/include/litmus/rt_param.h
+++ b/include/litmus/rt_param.h
@@ -5,7 +5,7 @@
5#ifndef _LINUX_RT_PARAM_H_ 5#ifndef _LINUX_RT_PARAM_H_
6#define _LINUX_RT_PARAM_H_ 6#define _LINUX_RT_PARAM_H_
7 7
8#include <litmus/dgl.h> 8#include <litmus/color.h>
9 9
10/* Litmus time type. */ 10/* Litmus time type. */
11typedef unsigned long long lt_t; 11typedef unsigned long long lt_t;
@@ -68,7 +68,7 @@ struct control_page {
68 /* locking overhead tracing: time stamp prior to system call */ 68 /* locking overhead tracing: time stamp prior to system call */
69 uint64_t ts_syscall_start; /* Feather-Trace cycles */ 69 uint64_t ts_syscall_start; /* Feather-Trace cycles */
70 70
71 int requests[NUM_RESOURCES]; 71 int requests[NUM_COLORS];
72}; 72};
73 73
74/* don't export internal data structures to user space (liblitmus) */ 74/* don't export internal data structures to user space (liblitmus) */
diff --git a/litmus/dgl.c b/litmus/dgl.c
index 9749597aa769..e09d57cc2672 100644
--- a/litmus/dgl.c
+++ b/litmus/dgl.c
@@ -27,27 +27,48 @@ static inline void mask_idx(int resource, int *word, int *bit)
27 *bit = resource % MASK_SIZE; 27 *bit = resource % MASK_SIZE;
28} 28}
29 29
30
31static void print_waiting(struct dgl *dgl, struct dgl_resource *resource)
32{
33 struct dgl_req *pos;
34 struct dgl_group_req *greq;
35 int rid = resource_id(dgl, resource);
36 unsigned long long last = 0;
37
38 TRACE("List for rid %d\n", resource_id(dgl, resource));
39 list_for_each_entry(pos, &resource->waiting, list) {
40 greq = req_group(pos, rid);
41 TRACE(" 0x%p with timestamp %llu\n", greq, greq->ts);
42 BUG_ON(greq->ts < last);
43 last = greq->ts;
44 }
45}
46
30void dgl_init(struct dgl *dgl) 47void dgl_init(struct dgl *dgl)
31{ 48{
32 int i; 49 int i;
33 struct dgl_resource *resource; 50 struct dgl_resource *resource;
34 51
35 for (i = 0; i < NR_CPUS; i++) 52 for (i = 0; i < NR_CPUS; ++i)
36 dgl->acquired[i] = NULL; 53 dgl->acquired[i] = NULL;
37 54
38 for (i = 0; i < NUM_RESOURCES; i++) { 55 for (i = 0; i < NUM_RESOURCES; ++i) {
39 resource = &dgl->resources[i]; 56 resource = &dgl->resources[i];
40 57
41 INIT_LIST_HEAD(&resource->waiting); 58 INIT_LIST_HEAD(&resource->waiting);
42 resource->free_replicas = NUM_REPLICAS; 59 resource->free_replicas = NUM_REPLICAS;
43 } 60 }
61
62 dgl->requests = 0;
63 dgl->running = 0;
64 dgl->ts = 0;
44} 65}
45 66
46void dgl_group_req_init(struct dgl_group_req *greq) 67void dgl_group_req_init(struct dgl_group_req *greq)
47{ 68{
48 int i; 69 int i;
49 greq->cpu = NO_CPU; 70 greq->cpu = NO_CPU;
50 for (i = 0; i < MASK_WORDS; i++) { 71 for (i = 0; i < MASK_WORDS; ++i) {
51 greq->requested[i] = 0; 72 greq->requested[i] = 0;
52 greq->waiting[i] = 0; 73 greq->waiting[i] = 0;
53 } 74 }
@@ -64,9 +85,6 @@ void set_req(struct dgl_group_req *greq, int resource, int replicas)
64 BUG_ON(replicas > NUM_REPLICAS); 85 BUG_ON(replicas > NUM_REPLICAS);
65 86
66 mask_idx(resource, &word, &bit); 87 mask_idx(resource, &word, &bit);
67 TRACE("0x%p will request resource %d, word %d, bit %d\n",
68 greq, resource, word, bit);
69
70 __set_bit(bit, &greq->requested[word]); 88 __set_bit(bit, &greq->requested[word]);
71 89
72 req = &greq->requests[resource]; 90 req = &greq->requests[resource];
@@ -82,25 +100,31 @@ void set_req(struct dgl_group_req *greq, int resource, int replicas)
82static unsigned long try_acquire(struct dgl *dgl, struct dgl_resource *resource, 100static unsigned long try_acquire(struct dgl *dgl, struct dgl_resource *resource,
83 struct dgl_req *req) 101 struct dgl_req *req)
84{ 102{
85 int word, bit, rid; 103 int word, bit, rid, head, empty, room;
86 unsigned long waiting; 104 unsigned long waiting;
87 struct dgl_group_req *greq; 105 struct dgl_group_req *greq;
88 106
89 if (resource->free_replicas < req->replicas) { 107 rid = resource_id(dgl, resource);
90 TRACE("0x%p cannot acquire %d replicas, only %d free\n", 108 greq = req_group(req, rid);
91 greq, req->replicas, resource->free_replicas); 109
110 head = resource->waiting.next == &req->list;
111 empty = list_empty(&resource->waiting);
112 room = resource->free_replicas >= req->replicas;
113
114 if (! (room && (head || empty)) ) {
115 TRACE("0x%p cannot acquire %d replicas, %d free\n",
116 greq, req->replicas, resource->free_replicas,
117 room, head, empty);
92 return 0; 118 return 0;
93 } 119 }
94 120
95 resource->free_replicas -= req->replicas; 121 resource->free_replicas -= req->replicas;
122 BUG_ON(resource->free_replicas > NUM_REPLICAS);
96 123
97 rid = resource_id(dgl, resource); 124 TRACE("0x%p acquired %d replicas of rid %d\n",
98 greq = req_group(req, rid); 125 greq, req->replicas, rid);
99 mask_idx(rid, &word, &bit);
100
101 TRACE("0x%p acquired rid %d, word %d, bit %d\n",
102 greq, rid, word, bit);
103 126
127 mask_idx(rid, &word, &bit);
104 clear_bit(bit, &greq->waiting[word]); 128 clear_bit(bit, &greq->waiting[word]);
105 129
106 waiting = 0; 130 waiting = 0;
@@ -115,6 +139,7 @@ static unsigned long try_acquire(struct dgl *dgl, struct dgl_resource *resource,
115 BUG_ON(dgl->acquired[greq->cpu]); 139 BUG_ON(dgl->acquired[greq->cpu]);
116 dgl->acquired[greq->cpu] = greq; 140 dgl->acquired[greq->cpu] = greq;
117 litmus_reschedule(greq->cpu); 141 litmus_reschedule(greq->cpu);
142 dgl->running++;
118 } 143 }
119 144
120 return 1; 145 return 1;
@@ -130,10 +155,13 @@ void add_group_req(struct dgl *dgl, struct dgl_group_req *greq, int cpu)
130 struct dgl_resource *resource; 155 struct dgl_resource *resource;
131 156
132 greq->cpu = cpu; 157 greq->cpu = cpu;
158 greq->ts = dgl->ts++;
133 159
134 TRACE("0x%p group request added for CPU %d\n", greq, cpu); 160 TRACE("0x%p group request added for CPU %d\n", greq, cpu);
135 BUG_ON(dgl->acquired[cpu] == greq); 161 BUG_ON(dgl->acquired[cpu] == greq);
136 162
163 ++dgl->requests;
164
137 for_each_resource(greq->requested, w, b, i) { 165 for_each_resource(greq->requested, w, b, i) {
138 __set_bit(b, &greq->waiting[w]); 166 __set_bit(b, &greq->waiting[w]);
139 } 167 }
@@ -146,10 +174,19 @@ void add_group_req(struct dgl *dgl, struct dgl_group_req *greq, int cpu)
146 all_succ &= succ; 174 all_succ &= succ;
147 175
148 if (!succ) { 176 if (!succ) {
149 TRACE("0x%p waiting on resource %d\n", greq, i); 177 TRACE("0x%p waiting on rid %d\n", greq, i);
150 list_add_tail(&req->list, &resource->waiting); 178 list_add_tail(&req->list, &resource->waiting);
151 } 179 }
152 } 180 }
181
182 /* Grant empty requests */
183 if (all_succ && !dgl->acquired[cpu]) {
184 TRACE("0x%p empty group request acquired cpu %d\n", greq, cpu);
185 dgl->acquired[cpu] = greq;
186 ++dgl->running;
187 }
188
189 BUG_ON(dgl->requests && !dgl->running);
153} 190}
154 191
155/** 192/**
@@ -165,9 +202,12 @@ void remove_group_req(struct dgl *dgl, struct dgl_group_req *greq)
165 202
166 TRACE("0x%p removing group request for CPU %d\n", greq, greq->cpu); 203 TRACE("0x%p removing group request for CPU %d\n", greq, greq->cpu);
167 204
205 --dgl->requests;
206
168 if (dgl->acquired[greq->cpu] == greq) { 207 if (dgl->acquired[greq->cpu] == greq) {
169 TRACE("0x%p no longer acquired on CPU %d\n", greq, greq->cpu); 208 TRACE("0x%p no longer acquired on CPU %d\n", greq, greq->cpu);
170 dgl->acquired[greq->cpu] = NULL; 209 dgl->acquired[greq->cpu] = NULL;
210 --dgl->running;
171 } 211 }
172 212
173 for_each_resource(greq->requested, w, b, i) { 213 for_each_resource(greq->requested, w, b, i) {
@@ -178,20 +218,31 @@ void remove_group_req(struct dgl *dgl, struct dgl_group_req *greq)
178 /* Waiting on resource */ 218 /* Waiting on resource */
179 clear_bit(b, &greq->waiting[w]); 219 clear_bit(b, &greq->waiting[w]);
180 list_del_init(&req->list); 220 list_del_init(&req->list);
181 TRACE("0x%p quit waiting for resource %d\n", greq, i); 221 TRACE("Quitting 0x%p from rid %d\n",
222 req, i);
182 } else { 223 } else {
183 /* Have resource */ 224 /* Have resource */
184 resource->free_replicas += req->replicas; 225 resource->free_replicas += req->replicas;
185 TRACE("0x%p releasing resource %d\n", greq, i); 226 BUG_ON(resource->free_replicas > NUM_REPLICAS);
227 TRACE("0x%p releasing %d of %d replicas, rid %d\n",
228 greq, req->replicas, resource->free_replicas, i);
186 229
187 if (!list_empty(&resource->waiting)) { 230 if (!list_empty(&resource->waiting)) {
188 /* Give it to the next guy */ 231 /* Give it to the next guy */
189 next = list_first_entry(&resource->waiting, 232 next = list_first_entry(&resource->waiting,
190 struct dgl_req, 233 struct dgl_req,
191 list); 234 list);
192 if (try_acquire(dgl, resource, next)) 235
236 BUG_ON(req_group(next, i)->ts < greq->ts);
237
238 if (try_acquire(dgl, resource, next)) {
193 list_del_init(&next->list); 239 list_del_init(&next->list);
240 print_waiting(dgl, resource);
241
242 }
194 } 243 }
195 } 244 }
196 } 245 }
246
247 BUG_ON(dgl->requests && !dgl->running);
197} 248}
diff --git a/litmus/sched_color.c b/litmus/sched_color.c
index 61a28da1ef6c..d5408c645644 100644
--- a/litmus/sched_color.c
+++ b/litmus/sched_color.c
@@ -459,7 +459,8 @@ static struct task_struct* color_schedule(struct task_struct *prev)
459 } else { 459 } else {
460 TRACE_TASK(next, "Does not have lock, 0x%p does\n", 460 TRACE_TASK(next, "Does not have lock, 0x%p does\n",
461 group_lock.acquired[entry->server.cpu]); 461 group_lock.acquired[entry->server.cpu]);
462 sched_trace_task_block(next, 1); 462 if (next != prev)
463 sched_trace_task_block(next, 1);
463 next = NULL; 464 next = NULL;
464 server_running = 0; 465 server_running = 0;
465 } 466 }
@@ -509,20 +510,16 @@ static void color_task_new(struct task_struct *t, int on_rq, int running)
509 req = kmalloc(sizeof(*req), GFP_ATOMIC); 510 req = kmalloc(sizeof(*req), GFP_ATOMIC);
510 dgl_group_req_init(req); 511 dgl_group_req_init(req);
511 for (i = 0; i < NUM_RESOURCES; i++) { 512 for (i = 0; i < NUM_RESOURCES; i++) {
512 /* /\* Testing *\/ */ 513 replicas = get_control_page(t)->requests[i];
513 /* set_req(req, i, 2); */ 514 if (replicas)
514 /* /\* Real *\/ */ 515 set_req(req, i, replicas);
515 /* replicas = get_control_page(t)->requests[i]; */
516 /* if (replicas) { */
517 /* set_req(req, i, replicas); */
518 /* } */
519 } 516 }
520 tsk_rt(t)->req = req; 517 tsk_rt(t)->req = req;
521 518
522 /* Join system */ 519 /* Join system */
523 raw_spin_lock(lock); 520 raw_spin_lock(lock);
524 if (running) { 521 if (running) {
525 TRACE_TASK(t, "Already scheduled on %d\n", entry->cpu); 522 TRACE_TASK(t, "Already scheduled on %d\n", entry->server.cpu);
526 BUG_ON(entry->scheduled); 523 BUG_ON(entry->scheduled);
527 entry->scheduled = t; 524 entry->scheduled = t;
528 tsk_rt(t)->scheduled_on = entry->server.cpu; 525 tsk_rt(t)->scheduled_on = entry->server.cpu;
@@ -630,7 +627,12 @@ static void color_task_exit(struct task_struct * t)
630 */ 627 */
631static long color_admit_task(struct task_struct* t) 628static long color_admit_task(struct task_struct* t)
632{ 629{
633 return is_be(t) || task_cpu(t) == get_partition(t) ? 0 : -EINVAL; 630 int ret = is_be(t) || task_cpu(t) == get_partition(t) ? 0 : -EINVAL;
631 if (!ret) {
632 printk(KERN_WARNING "Task failed to migrate to CPU %d\n",
633 get_partition(t));
634 }
635 return ret;
634} 636}
635 637
636/* 638/*
@@ -668,10 +670,12 @@ static long color_activate_plugin(void)
668 670
669 /* Make runnable */ 671 /* Make runnable */
670 release_at(server_task, now); 672 release_at(server_task, now);
671 requeue(&entry->edf_domain, server_task);
672 entry->fifo_server.start_time = 0; 673 entry->fifo_server.start_time = 0;
673 entry->scheduled = NULL; 674 entry->scheduled = NULL;
674 675
676 if (!is_queued(server_task))
677 requeue(&entry->edf_domain, server_task);
678
675 TRACE_TASK(server_task, "Created server with wcet: %llu, " 679 TRACE_TASK(server_task, "Created server with wcet: %llu, "
676 "period: %llu\n", tp.exec_cost, tp.period); 680 "period: %llu\n", tp.exec_cost, tp.period);
677 681