diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-10-24 16:39:04 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-10-24 16:40:21 -0400 |
commit | 0a6081a7798ce1ac61823c41a670beafbafb0435 (patch) | |
tree | fea2547df8b34126f06d037d2d5765b48205d9cc | |
parent | 97f6b3f52bc3059f6e5fb7c6744d6384b4fca95d (diff) |
Add Color Queue tracing.
-rw-r--r-- | include/litmus/trace.h | 34 | ||||
-rw-r--r-- | litmus/color_queue.c | 38 | ||||
-rw-r--r-- | litmus/lockdown.c | 23 |
3 files changed, 91 insertions, 4 deletions
diff --git a/include/litmus/trace.h b/include/litmus/trace.h index c0842247ad8e..a1d68d99c4df 100644 --- a/include/litmus/trace.h +++ b/include/litmus/trace.h | |||
@@ -115,9 +115,41 @@ feather_callback void save_task_latency(unsigned long event, unsigned long when_ | |||
115 | #define TS_PLUGIN_TICK_START /* TIMESTAMP(130) */ | 115 | #define TS_PLUGIN_TICK_START /* TIMESTAMP(130) */ |
116 | #define TS_PLUGIN_TICK_END /* TIMESTAMP(131) */ | 116 | #define TS_PLUGIN_TICK_END /* TIMESTAMP(131) */ |
117 | 117 | ||
118 | /* Color Queue stuff */ | ||
119 | #define TS_CQ_ENQUEUE_READ_START DTIMESTAMP(124, TSK_RT) | ||
120 | #define TS_CQ_ENQUEUE_READ_END DTIMESTAMP(125, TSK_RT) | ||
121 | |||
122 | #define TS_CQ_ENQUEUE_FLUSH_START DTIMESTAMP(126, TSK_RT) | ||
123 | #define TS_CQ_ENQUEUE_FLUSH_END DTIMESTAMP(127, TSK_RT) | ||
124 | |||
125 | #define TS_CQ_SUBMIT_WORK_START DTIMESTAMP(128, TSK_RT) | ||
126 | #define TS_CQ_SUBMIT_WORK_END DTIMESTAMP(129, TSK_RT) | ||
127 | |||
128 | /* Skip 130/131 */ | ||
129 | |||
130 | #define TS_CQ_LOOP_WORK_CHECK_START DTIMESTAMP(132, TSK_RT) | ||
131 | #define TS_CQ_LOOP_WORK_CHECK_END DTIMESTAMP(133, TSK_RT) | ||
132 | |||
133 | #define TS_CQ_LOOP_PEACE_OUT_START DTIMESTAMP(134, TSK_RT) | ||
134 | #define TS_CQ_LOOP_PEACE_OUT_END DTIMESTAMP(135, TSK_RT) | ||
135 | |||
136 | #define TS_CQ_LOOP_BRANCH_START DTIMESTAMP(136, TSK_RT) | ||
137 | #define TS_CQ_LOOP_BRANCH_END DTIMESTAMP(137, TSK_RT) | ||
138 | |||
139 | #define TS_CQ_WORK_DO_WORK_START DTIMESTAMP(138, TSK_RT) | ||
140 | #define TS_CQ_WORK_DO_WORK_END DTIMESTAMP(139, TSK_RT) | ||
141 | |||
142 | /* Not Color Queue */ | ||
118 | #define TS_ENTER_NP_START TIMESTAMP(140) | 143 | #define TS_ENTER_NP_START TIMESTAMP(140) |
119 | #define TS_ENTER_NP_END TIMESTAMP(141) | 144 | #define TS_ENTER_NP_END TIMESTAMP(141) |
120 | 145 | ||
146 | /* Two more Color Queue event */ | ||
147 | #define TS_CQ_WORK_NOTIFY_START DTIMESTAMP(142, TSK_RT) | ||
148 | #define TS_CQ_WORK_NOTIFY_END DTIMESTAMP(143, TSK_RT) | ||
149 | |||
150 | #define TS_CQ_PHASE_WAIT_START DTIMESTAMP(144, TSK_RT) | ||
151 | #define TS_CQ_PHASE_WAIT_END DTIMESTAMP(145, TSK_RT) | ||
152 | |||
121 | #define TS_EXIT_NP_START TIMESTAMP(150) | 153 | #define TS_EXIT_NP_START TIMESTAMP(150) |
122 | #define TS_EXIT_NP_END TIMESTAMP(151) | 154 | #define TS_EXIT_NP_END TIMESTAMP(151) |
123 | 155 | ||
@@ -137,4 +169,6 @@ feather_callback void save_task_latency(unsigned long event, unsigned long when_ | |||
137 | 169 | ||
138 | #define TS_RELEASE_LATENCY(when) LTIMESTAMP(208, &(when)) | 170 | #define TS_RELEASE_LATENCY(when) LTIMESTAMP(208, &(when)) |
139 | 171 | ||
172 | |||
173 | |||
140 | #endif /* !_SYS_TRACE_H_ */ | 174 | #endif /* !_SYS_TRACE_H_ */ |
diff --git a/litmus/color_queue.c b/litmus/color_queue.c index 46c725799308..c37aeb8c1389 100644 --- a/litmus/color_queue.c +++ b/litmus/color_queue.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <litmus/lockdown.h> | 7 | #include <litmus/lockdown.h> |
8 | #include <litmus/color.h> | 8 | #include <litmus/color.h> |
9 | #include <litmus/litmus.h> | 9 | #include <litmus/litmus.h> |
10 | #include <litmus/trace.h> | ||
10 | 11 | ||
11 | /* Uncomment to debug. */ | 12 | /* Uncomment to debug. */ |
12 | #define QTRACE(q, fmt, args...) TRACE_CUR("q.phase: %llu q.way: %d " \ | 13 | #define QTRACE(q, fmt, args...) TRACE_CUR("q.phase: %llu q.way: %d " \ |
@@ -97,6 +98,7 @@ static void cpu_add_work(struct color_queue_request *req) | |||
97 | */ | 98 | */ |
98 | static void color_page_info_add_work(struct color_page_info *info, void *vaddr_start) | 99 | static void color_page_info_add_work(struct color_page_info *info, void *vaddr_start) |
99 | { | 100 | { |
101 | const int cpu = smp_processor_id(); | ||
100 | int i; | 102 | int i; |
101 | 103 | ||
102 | TRACE_CUR("adding work for color_page_info: 0x%p\n", info); | 104 | TRACE_CUR("adding work for color_page_info: 0x%p\n", info); |
@@ -109,7 +111,7 @@ static void color_page_info_add_work(struct color_page_info *info, void *vaddr_s | |||
109 | "request was not idle!\n"); | 111 | "request was not idle!\n"); |
110 | 112 | ||
111 | req->request_type = COLOR_QUEUE_READ; | 113 | req->request_type = COLOR_QUEUE_READ; |
112 | req->cpu = smp_processor_id(); | 114 | req->cpu = cpu; |
113 | req->request_data.read.vaddr = work_vaddr; | 115 | req->request_data.read.vaddr = work_vaddr; |
114 | cpu_add_work(req); | 116 | cpu_add_work(req); |
115 | } | 117 | } |
@@ -127,6 +129,8 @@ int color_queue_enqueue_read(struct task_struct *ts) | |||
127 | { | 129 | { |
128 | struct color_page_info *cur_info; | 130 | struct color_page_info *cur_info; |
129 | 131 | ||
132 | TS_CQ_ENQUEUE_READ_START; | ||
133 | |||
130 | TRACE_CUR("enqueue read prev: %p next: %p\n", | 134 | TRACE_CUR("enqueue read prev: %p next: %p\n", |
131 | tsk_rt(ts)->color_page_info_list.prev, | 135 | tsk_rt(ts)->color_page_info_list.prev, |
132 | tsk_rt(ts)->color_page_info_list.next); | 136 | tsk_rt(ts)->color_page_info_list.next); |
@@ -141,6 +145,8 @@ int color_queue_enqueue_read(struct task_struct *ts) | |||
141 | color_page_info_add_work(cur_info, vaddr_start); | 145 | color_page_info_add_work(cur_info, vaddr_start); |
142 | } | 146 | } |
143 | 147 | ||
148 | TS_CQ_ENQUEUE_READ_END; | ||
149 | |||
144 | return color_queue_submit_work(); | 150 | return color_queue_submit_work(); |
145 | } | 151 | } |
146 | 152 | ||
@@ -155,6 +161,8 @@ int color_queue_enqueue_flush(struct task_struct *ts) | |||
155 | { | 161 | { |
156 | struct color_page_info *cur_info; | 162 | struct color_page_info *cur_info; |
157 | 163 | ||
164 | TS_CQ_ENQUEUE_FLUSH_START; | ||
165 | |||
158 | list_for_each_entry(cur_info, | 166 | list_for_each_entry(cur_info, |
159 | &tsk_rt(ts)->color_page_info_list, | 167 | &tsk_rt(ts)->color_page_info_list, |
160 | list) | 168 | list) |
@@ -165,6 +173,8 @@ int color_queue_enqueue_flush(struct task_struct *ts) | |||
165 | color_page_info_add_work(cur_info, vaddr_start); | 173 | color_page_info_add_work(cur_info, vaddr_start); |
166 | } | 174 | } |
167 | 175 | ||
176 | TS_CQ_ENQUEUE_FLUSH_END; | ||
177 | |||
168 | return color_queue_submit_work(); | 178 | return color_queue_submit_work(); |
169 | } | 179 | } |
170 | 180 | ||
@@ -190,6 +200,7 @@ static void do_work_son(struct color_queue_request *request) | |||
190 | { | 200 | { |
191 | struct cpu_entry *entry; | 201 | struct cpu_entry *entry; |
192 | 202 | ||
203 | TS_CQ_WORK_DO_WORK_START; | ||
193 | switch (request->request_type) { | 204 | switch (request->request_type) { |
194 | case COLOR_QUEUE_IDLE: | 205 | case COLOR_QUEUE_IDLE: |
195 | TRACE_CUR("idle work in the queue!\n"); | 206 | TRACE_CUR("idle work in the queue!\n"); |
@@ -200,7 +211,9 @@ static void do_work_son(struct color_queue_request *request) | |||
200 | do_work_read(request); | 211 | do_work_read(request); |
201 | break; | 212 | break; |
202 | } | 213 | } |
214 | TS_CQ_WORK_DO_WORK_END; | ||
203 | 215 | ||
216 | TS_CQ_WORK_NOTIFY_START; | ||
204 | /* Tell the (possibly remote) CPU that we're a bro and helped out. */ | 217 | /* Tell the (possibly remote) CPU that we're a bro and helped out. */ |
205 | entry = &per_cpu(cpu_entries, request->cpu); | 218 | entry = &per_cpu(cpu_entries, request->cpu); |
206 | raw_spin_lock(&entry->lock); | 219 | raw_spin_lock(&entry->lock); |
@@ -210,6 +223,7 @@ static void do_work_son(struct color_queue_request *request) | |||
210 | 223 | ||
211 | /* work is done, set it idle */ | 224 | /* work is done, set it idle */ |
212 | request->request_type = COLOR_QUEUE_IDLE; | 225 | request->request_type = COLOR_QUEUE_IDLE; |
226 | TS_CQ_WORK_NOTIFY_END; | ||
213 | } | 227 | } |
214 | 228 | ||
215 | static void wait_next_phase(void) | 229 | static void wait_next_phase(void) |
@@ -217,6 +231,8 @@ static void wait_next_phase(void) | |||
217 | struct cpu_entry *entry = &__get_cpu_var(cpu_entries); | 231 | struct cpu_entry *entry = &__get_cpu_var(cpu_entries); |
218 | struct color_queue_request *request; | 232 | struct color_queue_request *request; |
219 | 233 | ||
234 | TS_CQ_PHASE_WAIT_START; | ||
235 | |||
220 | for (;;) { | 236 | for (;;) { |
221 | raw_spin_lock(&color_queue.lock); | 237 | raw_spin_lock(&color_queue.lock); |
222 | if (entry->phase < color_queue.phase) { | 238 | if (entry->phase < color_queue.phase) { |
@@ -228,6 +244,7 @@ static void wait_next_phase(void) | |||
228 | "cpu->phase: %d advances to a higher phase\n", | 244 | "cpu->phase: %d advances to a higher phase\n", |
229 | entry->phase); | 245 | entry->phase); |
230 | raw_spin_unlock(&color_queue.lock); | 246 | raw_spin_unlock(&color_queue.lock); |
247 | TS_CQ_PHASE_WAIT_END; | ||
231 | return; | 248 | return; |
232 | } | 249 | } |
233 | 250 | ||
@@ -271,11 +288,14 @@ static int color_queue_loop(void) | |||
271 | int nr_work, nr_work_done_by_task = 0; | 288 | int nr_work, nr_work_done_by_task = 0; |
272 | 289 | ||
273 | for (;;) { | 290 | for (;;) { |
291 | TS_CQ_LOOP_WORK_CHECK_START; | ||
274 | raw_spin_lock(&entry->lock); | 292 | raw_spin_lock(&entry->lock); |
275 | nr_work = entry->nr_work; | 293 | nr_work = entry->nr_work; |
276 | raw_spin_unlock(&entry->lock); | 294 | raw_spin_unlock(&entry->lock); |
295 | TS_CQ_LOOP_WORK_CHECK_END; | ||
277 | 296 | ||
278 | if (0 == nr_work) { | 297 | if (0 == nr_work) { |
298 | TS_CQ_LOOP_PEACE_OUT_START; | ||
279 | /* All the work is done for this CPU. We can leave. */ | 299 | /* All the work is done for this CPU. We can leave. */ |
280 | raw_spin_lock(&color_queue.lock); | 300 | raw_spin_lock(&color_queue.lock); |
281 | color_queue.nr_cpus--; | 301 | color_queue.nr_cpus--; |
@@ -286,17 +306,20 @@ static int color_queue_loop(void) | |||
286 | } | 306 | } |
287 | QTRACE(color_queue, "just left the queue\n"); | 307 | QTRACE(color_queue, "just left the queue\n"); |
288 | raw_spin_unlock(&color_queue.lock); | 308 | raw_spin_unlock(&color_queue.lock); |
309 | TS_CQ_LOOP_PEACE_OUT_END; | ||
289 | return nr_work_done_by_task; | 310 | return nr_work_done_by_task; |
290 | } | 311 | } |
291 | 312 | ||
292 | /* Our work is not done, so continue processing more work. */ | 313 | /* Our work is not done, so continue processing more work. */ |
293 | 314 | ||
315 | TS_CQ_LOOP_BRANCH_START; | ||
294 | raw_spin_lock(&color_queue.lock); | 316 | raw_spin_lock(&color_queue.lock); |
295 | if (unlikely(list_empty(&color_queue.queue))) { | 317 | if (unlikely(list_empty(&color_queue.queue))) { |
296 | /* can this happen? */ | 318 | /* can this happen? */ |
297 | QTRACE(color_queue, "color queue was empty?\n"); | 319 | QTRACE(color_queue, "color queue was empty?\n"); |
298 | WARN(1, "color queue list was empty...\n"); | 320 | WARN(1, "color queue list was empty...\n"); |
299 | raw_spin_unlock(&color_queue.lock); | 321 | raw_spin_unlock(&color_queue.lock); |
322 | TS_CQ_LOOP_BRANCH_END; | ||
300 | continue; | 323 | continue; |
301 | } | 324 | } |
302 | request = list_first_entry(&color_queue.queue, | 325 | request = list_first_entry(&color_queue.queue, |
@@ -306,6 +329,7 @@ static int color_queue_loop(void) | |||
306 | list_del(&request->list); | 329 | list_del(&request->list); |
307 | QTRACE(color_queue, "found a piece of work to do: %p\n", request); | 330 | QTRACE(color_queue, "found a piece of work to do: %p\n", request); |
308 | raw_spin_unlock(&color_queue.lock); | 331 | raw_spin_unlock(&color_queue.lock); |
332 | TS_CQ_LOOP_BRANCH_END; | ||
309 | do_work_son(request); | 333 | do_work_son(request); |
310 | ++nr_work_done_by_task; | 334 | ++nr_work_done_by_task; |
311 | } else { | 335 | } else { |
@@ -313,6 +337,7 @@ static int color_queue_loop(void) | |||
313 | color_queue.at_barrier++; | 337 | color_queue.at_barrier++; |
314 | QTRACE(color_queue, "begins to wait at barrier...\n"); | 338 | QTRACE(color_queue, "begins to wait at barrier...\n"); |
315 | raw_spin_unlock(&color_queue.lock); | 339 | raw_spin_unlock(&color_queue.lock); |
340 | TS_CQ_LOOP_BRANCH_END; | ||
316 | wait_next_phase(); | 341 | wait_next_phase(); |
317 | } | 342 | } |
318 | } | 343 | } |
@@ -323,7 +348,11 @@ static int color_queue_loop(void) | |||
323 | */ | 348 | */ |
324 | static int color_queue_submit_work(void) | 349 | static int color_queue_submit_work(void) |
325 | { | 350 | { |
326 | struct cpu_entry *entry = &__get_cpu_var(cpu_entries); | 351 | struct cpu_entry *entry; |
352 | |||
353 | TS_CQ_SUBMIT_WORK_START; | ||
354 | |||
355 | entry = &__get_cpu_var(cpu_entries); | ||
327 | 356 | ||
328 | raw_spin_lock(&color_queue.lock); | 357 | raw_spin_lock(&color_queue.lock); |
329 | QTRACE(color_queue, "start submit work\n"); | 358 | QTRACE(color_queue, "start submit work\n"); |
@@ -332,6 +361,9 @@ static int color_queue_submit_work(void) | |||
332 | list_splice_tail_init(&entry->enqueue, &color_queue.queue); | 361 | list_splice_tail_init(&entry->enqueue, &color_queue.queue); |
333 | QTRACE(color_queue, "end submit work\n"); | 362 | QTRACE(color_queue, "end submit work\n"); |
334 | raw_spin_unlock(&color_queue.lock); | 363 | raw_spin_unlock(&color_queue.lock); |
364 | |||
365 | TS_CQ_SUBMIT_WORK_END; | ||
366 | |||
335 | return color_queue_loop(); | 367 | return color_queue_loop(); |
336 | } | 368 | } |
337 | 369 | ||
@@ -427,7 +459,7 @@ static int __init init_color_queue(void) | |||
427 | 459 | ||
428 | BUILD_BUG_ON((PAGE_SIZE % COLOR_QUEUE_REQ_SIZE) != 0); | 460 | BUILD_BUG_ON((PAGE_SIZE % COLOR_QUEUE_REQ_SIZE) != 0); |
429 | 461 | ||
430 | for_each_online_cpu(cpu) { | 462 | for_each_online_cpu(cpu) { |
431 | cpu_entry = &per_cpu(cpu_entries, cpu); | 463 | cpu_entry = &per_cpu(cpu_entries, cpu); |
432 | INIT_LIST_HEAD(&cpu_entry->enqueue); | 464 | INIT_LIST_HEAD(&cpu_entry->enqueue); |
433 | cpu_entry->nr_work = 0; | 465 | cpu_entry->nr_work = 0; |
diff --git a/litmus/lockdown.c b/litmus/lockdown.c index d0dee3ae2d83..bb93690c00c9 100644 --- a/litmus/lockdown.c +++ b/litmus/lockdown.c | |||
@@ -100,6 +100,27 @@ void set_lockdown(u32 lockdown_state) | |||
100 | writel_relaxed(lockdown_state, lockreg_d); | 100 | writel_relaxed(lockdown_state, lockreg_d); |
101 | } | 101 | } |
102 | 102 | ||
103 | u32 color_read_in_mem(u32 lock_val, u32 unlock_val, void *start, void *end) | ||
104 | { | ||
105 | u32 v = 0; | ||
106 | |||
107 | __asm__ __volatile__ ( | ||
108 | " .align 5\n" | ||
109 | " str %[lockval], [%[cachereg]]\n" | ||
110 | "1: ldr %[val], [%[addr]], #32 @ 32 bytes = 1 cache line\n" | ||
111 | " cmp %[end], %[addr] @ subtracts addr from end\n" | ||
112 | " bgt 1b\n @ read more, if necessary\n" | ||
113 | : [addr] "+r" (start), | ||
114 | [val] "+r" (v) | ||
115 | : [end] "r" (end), | ||
116 | [cachereg] "r" (lockreg_d), | ||
117 | [lockval] "r" (lock_val) | ||
118 | : "cc"); | ||
119 | |||
120 | return v; | ||
121 | } | ||
122 | |||
123 | |||
103 | /* | 124 | /* |
104 | * Prefetch by reading the first word of each cache line in a page. | 125 | * Prefetch by reading the first word of each cache line in a page. |
105 | * | 126 | * |
@@ -111,7 +132,7 @@ void set_lockdown(u32 lockdown_state) | |||
111 | * | 132 | * |
112 | * Assumes: addr < end_addr AND addr != end_addr | 133 | * Assumes: addr < end_addr AND addr != end_addr |
113 | */ | 134 | */ |
114 | u32 color_read_in_mem(u32 lock_val, u32 unlock_val, void *start, void *end) | 135 | u32 color_read_in_mem_lock(u32 lock_val, u32 unlock_val, void *start, void *end) |
115 | { | 136 | { |
116 | unsigned long flags; | 137 | unsigned long flags; |
117 | u32 v = 0; | 138 | u32 v = 0; |