diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-10-18 19:47:16 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-10-18 19:51:43 -0400 |
commit | 76b433993134ed1cd467dfbd99e907816eac1ad9 (patch) | |
tree | 66ba00a577dc7b9f26f4ecfae6faa9c1e6d29d80 | |
parent | e371352875eae24b984ae6675969ad1dfb7b9599 (diff) |
Add debugging to Color Queue and fix a bug in color_info_free.
Signed-off-by: Christopher Kenna <cjk@cs.unc.edu>
-rw-r--r-- | include/litmus/color_queue.h | 20 | ||||
-rw-r--r-- | litmus/color_queue.c | 53 |
2 files changed, 51 insertions, 22 deletions
diff --git a/include/litmus/color_queue.h b/include/litmus/color_queue.h index 80976c539b1..7386b0f569d 100644 --- a/include/litmus/color_queue.h +++ b/include/litmus/color_queue.h | |||
@@ -11,26 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | #define COLOR_QUEUE_REQ_SIZE 2048 | 12 | #define COLOR_QUEUE_REQ_SIZE 2048 |
13 | 13 | ||
14 | struct color_queue { | ||
15 | struct list_head queue; | ||
16 | /* the queue of work */ | ||
17 | |||
18 | int nr_cpus; | ||
19 | /* number of CPUs that have outstanding requests */ | ||
20 | |||
21 | int at_barrier; | ||
22 | /* number of CPUs that are currently waiting at the barrier */ | ||
23 | |||
24 | int way; | ||
25 | /* which way the queue is currently reading in */ | ||
26 | |||
27 | u64 phase; | ||
28 | /* monotonically increasing phase. use 64 bits so it doesn't wrap. */ | ||
29 | |||
30 | raw_spinlock_t lock; | ||
31 | /* protects the above members */ | ||
32 | }; | ||
33 | |||
34 | enum color_queue_request_type { | 14 | enum color_queue_request_type { |
35 | COLOR_QUEUE_IDLE, | 15 | COLOR_QUEUE_IDLE, |
36 | /* Not in the queue. */ | 16 | /* Not in the queue. */ |
diff --git a/litmus/color_queue.c b/litmus/color_queue.c index c266e3aa0da..6543811fd06 100644 --- a/litmus/color_queue.c +++ b/litmus/color_queue.c | |||
@@ -8,6 +8,36 @@ | |||
8 | #include <litmus/color.h> | 8 | #include <litmus/color.h> |
9 | #include <litmus/litmus.h> | 9 | #include <litmus/litmus.h> |
10 | 10 | ||
11 | /* Uncomment to debug. */ | ||
12 | #define QTRACE(q, fmt, args...) TRACE_CUR("q.phase: %llu q.way: %d " \ | ||
13 | "q.nr_cpus: %d q.at_barrier: %d " fmt, \ | ||
14 | q.phase, q.way, q.nr_cpus, q.at_barrier, \ | ||
15 | ## args) | ||
16 | |||
17 | #ifndef QTRACE | ||
18 | #define QTRACE(q, fmt, args...) do { } while (0) | ||
19 | #endif | ||
20 | |||
21 | struct color_queue { | ||
22 | struct list_head queue; | ||
23 | /* the queue of work */ | ||
24 | |||
25 | int nr_cpus; | ||
26 | /* number of CPUs that have outstanding requests */ | ||
27 | |||
28 | int at_barrier; | ||
29 | /* number of CPUs that are currently waiting at the barrier */ | ||
30 | |||
31 | int way; | ||
32 | /* which way the queue is currently reading in */ | ||
33 | |||
34 | u64 phase; | ||
35 | /* monotonically increasing phase. use 64 bits so it doesn't wrap. */ | ||
36 | |||
37 | raw_spinlock_t lock; | ||
38 | /* protects the above members */ | ||
39 | }; | ||
40 | |||
11 | struct cpu_entry { | 41 | struct cpu_entry { |
12 | int phase; | 42 | int phase; |
13 | /* what phase a CPU is in */ | 43 | /* what phase a CPU is in */ |
@@ -53,6 +83,8 @@ static void cpu_add_work(struct color_queue_request *req) | |||
53 | struct list_head *new = &req->list; | 83 | struct list_head *new = &req->list; |
54 | list_add_tail(new, &entry->enqueue); | 84 | list_add_tail(new, &entry->enqueue); |
55 | entry->nr_work++; | 85 | entry->nr_work++; |
86 | TRACE_CUR("cpu->nr_work: %d added work request pointer %p\n", | ||
87 | entry->nr_work, req); | ||
56 | } | 88 | } |
57 | 89 | ||
58 | /* | 90 | /* |
@@ -154,9 +186,11 @@ static void do_work_son(struct color_queue_request *request) | |||
154 | 186 | ||
155 | switch (request->request_type) { | 187 | switch (request->request_type) { |
156 | case COLOR_QUEUE_IDLE: | 188 | case COLOR_QUEUE_IDLE: |
189 | TRACE_CUR("idle work in the queue!\n"); | ||
157 | WARN(1, "Idle work in the queue!\n"); | 190 | WARN(1, "Idle work in the queue!\n"); |
158 | break; | 191 | break; |
159 | case COLOR_QUEUE_READ: | 192 | case COLOR_QUEUE_READ: |
193 | TRACE_CUR("doing work for CPU %d\n", request->cpu); | ||
160 | do_work_read(request); | 194 | do_work_read(request); |
161 | break; | 195 | break; |
162 | } | 196 | } |
@@ -165,6 +199,7 @@ static void do_work_son(struct color_queue_request *request) | |||
165 | entry = &per_cpu(cpu_entries, request->cpu); | 199 | entry = &per_cpu(cpu_entries, request->cpu); |
166 | raw_spin_lock(&entry->lock); | 200 | raw_spin_lock(&entry->lock); |
167 | entry->nr_work--; | 201 | entry->nr_work--; |
202 | TRACE_CUR("after doing work, cpu->nr_work: %d\n", entry->nr_work); | ||
168 | raw_spin_unlock(&entry->lock); | 203 | raw_spin_unlock(&entry->lock); |
169 | 204 | ||
170 | /* work is done, set it idle */ | 205 | /* work is done, set it idle */ |
@@ -183,6 +218,7 @@ static void wait_next_phase(void) | |||
183 | * set up the lockdown value and updated the queue phase. | 218 | * set up the lockdown value and updated the queue phase. |
184 | */ | 219 | */ |
185 | entry->phase = color_queue.phase; | 220 | entry->phase = color_queue.phase; |
221 | QTRACE(color_queue, "moving on to next phase\n"); | ||
186 | raw_spin_unlock(&color_queue.lock); | 222 | raw_spin_unlock(&color_queue.lock); |
187 | return; | 223 | return; |
188 | } | 224 | } |
@@ -190,8 +226,11 @@ static void wait_next_phase(void) | |||
190 | if (color_queue.nr_cpus == color_queue.at_barrier) { | 226 | if (color_queue.nr_cpus == color_queue.at_barrier) { |
191 | int next_way; | 227 | int next_way; |
192 | 228 | ||
229 | QTRACE(color_queue, "everyone reached the barrier\n"); | ||
230 | |||
193 | /* Ready to start the next phase. */ | 231 | /* Ready to start the next phase. */ |
194 | if (unlikely(list_empty(&color_queue.queue))) { | 232 | if (unlikely(list_empty(&color_queue.queue))) { |
233 | QTRACE(color_queue, "The queue was empty (bad)\n"); | ||
195 | /* This should not happen! Will loop forever? */ | 234 | /* This should not happen! Will loop forever? */ |
196 | WARN(1, "color queue list was empty!\n"); | 235 | WARN(1, "color queue list was empty!\n"); |
197 | raw_spin_unlock(&color_queue.lock); | 236 | raw_spin_unlock(&color_queue.lock); |
@@ -204,10 +243,12 @@ static void wait_next_phase(void) | |||
204 | color_queue.way = next_way; | 243 | color_queue.way = next_way; |
205 | color_queue.at_barrier = 0; | 244 | color_queue.at_barrier = 0; |
206 | color_queue.phase++; | 245 | color_queue.phase++; |
246 | QTRACE(color_queue, "moving on to start on the next way\n"); | ||
207 | raw_spin_unlock(&color_queue.lock); | 247 | raw_spin_unlock(&color_queue.lock); |
208 | return; | 248 | return; |
209 | } else { | 249 | } else { |
210 | /* Wait for work from the last phase to complete. */ | 250 | /* Wait for work from the last phase to complete. */ |
251 | QTRACE(color_queue, "still waiting for others\n"); | ||
211 | raw_spin_unlock(&color_queue.lock); | 252 | raw_spin_unlock(&color_queue.lock); |
212 | cpu_relax(); | 253 | cpu_relax(); |
213 | } | 254 | } |
@@ -230,9 +271,11 @@ static void color_queue_loop(void) | |||
230 | raw_spin_lock(&color_queue.lock); | 271 | raw_spin_lock(&color_queue.lock); |
231 | color_queue.nr_cpus--; | 272 | color_queue.nr_cpus--; |
232 | if (0 == color_queue.nr_cpus) { | 273 | if (0 == color_queue.nr_cpus) { |
233 | /* Queue is going idle. Restore lockdown state. */ | 274 | /* Queue is going idle. Restore lockdown. */ |
234 | set_lockdown(lockdown_value_idle); | 275 | set_lockdown(lockdown_value_idle); |
276 | QTRACE(color_queue, "last CPU in queue.\n"); | ||
235 | } | 277 | } |
278 | QTRACE(color_queue, "just left the queue\n"); | ||
236 | raw_spin_unlock(&color_queue.lock); | 279 | raw_spin_unlock(&color_queue.lock); |
237 | return; | 280 | return; |
238 | } | 281 | } |
@@ -242,6 +285,7 @@ static void color_queue_loop(void) | |||
242 | raw_spin_lock(&color_queue.lock); | 285 | raw_spin_lock(&color_queue.lock); |
243 | if (unlikely(list_empty(&color_queue.queue))) { | 286 | if (unlikely(list_empty(&color_queue.queue))) { |
244 | /* can this happen? */ | 287 | /* can this happen? */ |
288 | QTRACE(color_queue, "color queue was empty?\n"); | ||
245 | WARN(1, "color queue list was empty...\n"); | 289 | WARN(1, "color queue list was empty...\n"); |
246 | raw_spin_unlock(&color_queue.lock); | 290 | raw_spin_unlock(&color_queue.lock); |
247 | continue; | 291 | continue; |
@@ -251,11 +295,13 @@ static void color_queue_loop(void) | |||
251 | if (color_queue.way == request->color_page_info->way) { | 295 | if (color_queue.way == request->color_page_info->way) { |
252 | /* we're going to do this work */ | 296 | /* we're going to do this work */ |
253 | list_del(&request->list); | 297 | list_del(&request->list); |
298 | QTRACE(color_queue, "found a piece of work to do: %p\n", request); | ||
254 | raw_spin_unlock(&color_queue.lock); | 299 | raw_spin_unlock(&color_queue.lock); |
255 | do_work_son(request); | 300 | do_work_son(request); |
256 | } else { | 301 | } else { |
257 | /* we need to wait for the next phase */ | 302 | /* we need to wait for the next phase */ |
258 | color_queue.at_barrier++; | 303 | color_queue.at_barrier++; |
304 | QTRACE(color_queue, "begins to wait at barrier...\n"); | ||
259 | raw_spin_unlock(&color_queue.lock); | 305 | raw_spin_unlock(&color_queue.lock); |
260 | wait_next_phase(); | 306 | wait_next_phase(); |
261 | } | 307 | } |
@@ -269,10 +315,13 @@ static void color_queue_submit_work(void) | |||
269 | { | 315 | { |
270 | struct cpu_entry *entry = &__get_cpu_var(cpu_entries); | 316 | struct cpu_entry *entry = &__get_cpu_var(cpu_entries); |
271 | 317 | ||
318 | |||
272 | raw_spin_lock(&color_queue.lock); | 319 | raw_spin_lock(&color_queue.lock); |
320 | QTRACE(color_queue, "start submit work\n"); | ||
273 | entry->phase = color_queue.phase; | 321 | entry->phase = color_queue.phase; |
274 | color_queue.nr_cpus++; | 322 | color_queue.nr_cpus++; |
275 | list_splice_tail_init(&entry->enqueue, &color_queue.queue); | 323 | list_splice_tail_init(&entry->enqueue, &color_queue.queue); |
324 | QTRACE(color_queue, "end submit work\n"); | ||
276 | raw_spin_unlock(&color_queue.lock); | 325 | raw_spin_unlock(&color_queue.lock); |
277 | color_queue_loop(); | 326 | color_queue_loop(); |
278 | } | 327 | } |
@@ -293,7 +342,7 @@ void cleanup_color_page_infos(struct list_head *head) | |||
293 | 342 | ||
294 | list_for_each_entry_safe(cur, tmp, head, list) { | 343 | list_for_each_entry_safe(cur, tmp, head, list) { |
295 | TRACE_CUR("cleanup color_queue_info %p\n", cur); | 344 | TRACE_CUR("cleanup color_queue_info %p\n", cur); |
296 | list_del(cur); | 345 | list_del(&cur->list); |
297 | kfree(cur); | 346 | kfree(cur); |
298 | } | 347 | } |
299 | } | 348 | } |