summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--unit_trace/viz/convert.py4
-rw-r--r--unit_trace/viz/draw.py42
-rw-r--r--unit_trace/viz/schedule.py236
-rw-r--r--unit_trace/viz/viewer.py1
4 files changed, 177 insertions, 106 deletions
diff --git a/unit_trace/viz/convert.py b/unit_trace/viz/convert.py
index f37dd27..8ebdbdc 100644
--- a/unit_trace/viz/convert.py
+++ b/unit_trace/viz/convert.py
@@ -54,8 +54,8 @@ def convert_trace_to_schedule(stream):
54 job.add_event(DeadlineEvent(record.deadline, cpu)))), 54 job.add_event(DeadlineEvent(record.deadline, cpu)))),
55 'switch_to' : (lambda : 55 'switch_to' : (lambda :
56 job.add_event(SwitchToEvent(record.when, cpu))), 56 job.add_event(SwitchToEvent(record.when, cpu))),
57 'switch_away' : lambda : 57 'switch_away' : (lambda :
58 job.add_event(SwitchAwayEvent(record.when, cpu)), 58 job.add_event(SwitchAwayEvent(record.when, cpu))),
59 'assign' : (noop), 59 'assign' : (noop),
60 'completion' : (lambda : 60 'completion' : (lambda :
61 job.add_event(CompleteEvent(record.when, cpu))), 61 job.add_event(CompleteEvent(record.when, cpu))),
diff --git a/unit_trace/viz/draw.py b/unit_trace/viz/draw.py
index e28ed24..8c48744 100644
--- a/unit_trace/viz/draw.py
+++ b/unit_trace/viz/draw.py
@@ -316,7 +316,17 @@ class Canvas(object):
316 self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS) 316 self.draw_line((x, y), (x, y + line_height), GraphFormat.GRID_COLOR, GraphFormat.GRID_THICKNESS)
317 x += maj_sep 317 x += maj_sep
318 318
319 def draw_bar(self, x, y, width, height, n, selected): 319 def _draw_bar_border_common(self, x, y, width, height, color, thickness, clip_side):
320 if clip_side is None:
321 self.draw_rect(x, y, width, height, color, thickness)
322 elif clip_side == AlignMode.LEFT:
323 self.draw_polyline([(x, y), (x + width, y), (x + width, y + height), (x, y + height)],
324 color, thickness)
325 elif clip_side == AlignMode.RIGHT:
326 self.draw_polyline([(x + width, y), (x, y), (x, y + height), (x + width, y + height)],
327 color, thickness)
328
329 def draw_bar(self, x, y, width, height, n, clip_side, selected):
320 """Draws a bar with a certain set of dimensions, using pattern ``n'' from the 330 """Draws a bar with a certain set of dimensions, using pattern ``n'' from the
321 bar pattern list.""" 331 bar pattern list."""
322 332
@@ -325,12 +335,13 @@ class Canvas(object):
325 335
326 # use a pattern to be pretty 336 # use a pattern to be pretty
327 self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) 337 self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True)
328 self.draw_rect(x, y, width, height, color, thickness) 338
339 self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side)
329 340
330 def add_sel_bar(self, x, y, width, height, event): 341 def add_sel_bar(self, x, y, width, height, event):
331 self.add_sel_region(SelectableRegion(x, y, width, height, event)) 342 self.add_sel_region(SelectableRegion(x, y, width, height, event))
332 343
333 def draw_mini_bar(self, x, y, width, height, n, selected): 344 def draw_mini_bar(self, x, y, width, height, n, clip_side, selected):
334 """Like the above, except it draws a miniature version. This is usually used for 345 """Like the above, except it draws a miniature version. This is usually used for
335 secondary purposes (i.e. to show jobs that _should_ have been running at a certain time). 346 secondary purposes (i.e. to show jobs that _should_ have been running at a certain time).
336 347
@@ -342,7 +353,8 @@ class Canvas(object):
342 True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected] 353 True : (GraphFormat.HIGHLIGHT_COLOR, GraphFormat.BORDER_THICKNESS * 1.5)}[selected]
343 354
344 self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True) 355 self.get_bar_pattern(n).render_on_canvas(self, x, y, width, height, True)
345 self.draw_rect(x, y, width, height, color, thickness) 356
357 self._draw_bar_border_common(x, y, width, height, color, thickness, clip_side)
346 358
347 def add_sel_mini_bar(self, x, y, width, height, event): 359 def add_sel_mini_bar(self, x, y, width, height, event):
348 self.add_sel_region(SelectableRegion(x, y, width, height, event)) 360 self.add_sel_region(SelectableRegion(x, y, width, height, event))
@@ -970,7 +982,7 @@ class Graph(object):
970 a certain time.""" 982 a certain time."""
971 raise NotImplementedError 983 raise NotImplementedError
972 984
973 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None): 985 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None):
974 """Draws a bar over a certain time period for some task, optionally labelling it.""" 986 """Draws a bar over a certain time period for some task, optionally labelling it."""
975 raise NotImplementedError 987 raise NotImplementedError
976 988
@@ -979,7 +991,7 @@ class Graph(object):
979 a certain time.""" 991 a certain time."""
980 raise NotImplementedError 992 raise NotImplementedError
981 993
982 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None): 994 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, clip_side=None, job_no=None):
983 """Draws a mini bar over a certain time period for some task, optionally labelling it.""" 995 """Draws a mini bar over a certain time period for some task, optionally labelling it."""
984 raise NotImplementedError 996 raise NotImplementedError
985 997
@@ -1099,7 +1111,7 @@ class TaskGraph(Graph):
1099 1111
1100 self.canvas.add_sel_deadline_arrow_big(x, y, height, event) 1112 self.canvas.add_sel_deadline_arrow_big(x, y, height, event)
1101 1113
1102 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): 1114 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
1103 if start_time > end_time: 1115 if start_time > end_time:
1104 raise ValueError("Litmus is not a time machine") 1116 raise ValueError("Litmus is not a time machine")
1105 1117
@@ -1108,7 +1120,7 @@ class TaskGraph(Graph):
1108 width = self._get_bar_width(start_time, end_time) 1120 width = self._get_bar_width(start_time, end_time)
1109 height = self._get_bar_height() 1121 height = self._get_bar_height()
1110 1122
1111 self.canvas.draw_bar(x, y, width, height, cpu_no, selected) 1123 self.canvas.draw_bar(x, y, width, height, cpu_no, clip_side, selected)
1112 1124
1113 # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively 1125 # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively
1114 if job_no is not None: 1126 if job_no is not None:
@@ -1128,7 +1140,7 @@ class TaskGraph(Graph):
1128 1140
1129 self.canvas.add_sel_bar(x, y, width, height, event) 1141 self.canvas.add_sel_bar(x, y, width, height, event)
1130 1142
1131 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): 1143 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
1132 if start_time > end_time: 1144 if start_time > end_time:
1133 raise ValueError("Litmus is not a time machine") 1145 raise ValueError("Litmus is not a time machine")
1134 1146
@@ -1137,7 +1149,7 @@ class TaskGraph(Graph):
1137 width = self._get_bar_width(start_time, end_time) 1149 width = self._get_bar_width(start_time, end_time)
1138 height = self._get_mini_bar_height() 1150 height = self._get_mini_bar_height()
1139 1151
1140 self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, selected) 1152 self.canvas.draw_mini_bar(x, y, width, height, Canvas.NULL_PATTERN, clip_side, selected)
1141 1153
1142 if job_no is not None: 1154 if job_no is not None:
1143 x += GraphFormat.MINI_BAR_LABEL_OFS 1155 x += GraphFormat.MINI_BAR_LABEL_OFS
@@ -1245,7 +1257,7 @@ class CpuGraph(Graph):
1245 x = self._get_time_xpos(time) 1257 x = self._get_time_xpos(time)
1246 y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0 1258 y = self._get_item_ypos(cpu_no) + self._get_bar_height() / 2.0 - height / 2.0
1247 1259
1248 self.canvas.add_sel_suspend_triangle(x, y, height, event) 1260 self.canvas.add_sel_resume_triangle(x, y, height, event)
1249 1261
1250 def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False): 1262 def draw_completion_marker_at_time(self, time, task_no, cpu_no, selected=False):
1251 height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR 1263 height = self._get_bar_height() * GraphFormat.COMPLETION_MARKER_FACTOR
@@ -1312,7 +1324,7 @@ class CpuGraph(Graph):
1312 1324
1313 self.canvas.add_sel_deadline_arrow_small(x, y, height, event) 1325 self.canvas.add_sel_deadline_arrow_small(x, y, height, event)
1314 1326
1315 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): 1327 def draw_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
1316 if start_time > end_time: 1328 if start_time > end_time:
1317 raise ValueError("Litmus is not a time machine") 1329 raise ValueError("Litmus is not a time machine")
1318 1330
@@ -1321,7 +1333,7 @@ class CpuGraph(Graph):
1321 width = self._get_bar_width(start_time, end_time) 1333 width = self._get_bar_width(start_time, end_time)
1322 height = self._get_bar_height() 1334 height = self._get_bar_height()
1323 1335
1324 self.canvas.draw_bar(x, y, width, height, task_no, selected) 1336 self.canvas.draw_bar(x, y, width, height, task_no, clip_side, selected)
1325 1337
1326 # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively 1338 # if a job number is specified, we want to draw a superscript and subscript for the task and job number, respectively
1327 if job_no is not None: 1339 if job_no is not None:
@@ -1339,7 +1351,7 @@ class CpuGraph(Graph):
1339 1351
1340 self.canvas.add_sel_bar(x, y, width, height, event) 1352 self.canvas.add_sel_bar(x, y, width, height, event)
1341 1353
1342 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, selected=False): 1354 def draw_mini_bar_at_time(self, start_time, end_time, task_no, cpu_no, job_no=None, clip_side=None, selected=False):
1343 if start_time > end_time: 1355 if start_time > end_time:
1344 raise ValueError("Litmus is not a time machine") 1356 raise ValueError("Litmus is not a time machine")
1345 1357
@@ -1348,7 +1360,7 @@ class CpuGraph(Graph):
1348 width = self._get_bar_width(start_time, end_time) 1360 width = self._get_bar_width(start_time, end_time)
1349 height = self._get_mini_bar_height() 1361 height = self._get_mini_bar_height()
1350 1362
1351 self.canvas.draw_mini_bar(x, y, width, height, task_no, selected) 1363 self.canvas.draw_mini_bar(x, y, width, height, task_no, clip_side, selected)
1352 1364
1353 if job_no is not None: 1365 if job_no is not None:
1354 x += GraphFormat.MINI_BAR_LABEL_OFS 1366 x += GraphFormat.MINI_BAR_LABEL_OFS
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py
index 4277f1a..5efee7d 100644
--- a/unit_trace/viz/schedule.py
+++ b/unit_trace/viz/schedule.py
@@ -11,6 +11,7 @@ import util
11import copy 11import copy
12 12
13EVENT_LIST = None 13EVENT_LIST = None
14SPAN_EVENTS = None
14 15
15class TimeSlotArray(object): 16class TimeSlotArray(object):
16 """Represents another way of organizing the events. This structure organizes events by 17 """Represents another way of organizing the events. This structure organizes events by
@@ -55,20 +56,47 @@ class TimeSlotArray(object):
55 56
56 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event) 57 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, event.__class__, time_slot, event)
57 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event) 58 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, event.__class__, time_slot, event)
59
60 if event.__class__ in SPAN_END_EVENTS:
61 self.fill_span_event_from_end(event)
62
63 def fill_span_event_from_end(self, event):
64 start_slot = None
65 if event.corresp_start_event is None:
66 start_slot = self.get_time_slot(event.get_job().get_task().get_schedule().start) - 1
67 else:
68 start_slot = self.get_time_slot(event.corresp_start_event.get_time())
69 end_slot = self.get_time_slot(event.get_time())
70
71 for slot in range(start_slot + 1, end_slot):
72 task_no = event.get_job().get_task().get_task_no()
73 cpu = event.get_cpu()
58 74
59 span_events = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy} 75 dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu)
60 76 dummy.corresp_start_event = event.corresp_start_event
61 for span_event in span_events: 77 dummy.corresp_end_event = event
62 if isinstance(event, span_event) and event.corresp_start_event is not None:
63 start_slot = self.get_time_slot(event.corresp_start_event.get_time())
64 end_slot = time_slot
65 for slot in range(start_slot + 1, end_slot):
66 dummy = span_events[span_event](task_no, cpu)
67 dummy.corresp_start_event = event.corresp_start_event
68 dummy.corresp_end_event = event
69 78
70 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) 79 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy)
71 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy) 80 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy)
81
82 def fill_span_event_from_start(self, event):
83 end_slot = None
84 if event.corresp_end_event is None:
85 end_slot = self.get_time_slot(event.get_job().get_task().get_schedule().end) + 1
86 else:
87 end_slot = self.get_time_slot(event.corresp_end_event.get_time())
88 start_slot = self.get_time_slot(event.get_time())
89
90 for slot in range(start_slot + 1, end_slot):
91 task_no = event.get_job().get_task().get_task_no()
92 cpu = event.get_cpu()
93
94 dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu)
95 dummy.corresp_start_event = event
96 dummy.corresp_end_event = event.corresp_end_event
97
98 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy)
99 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy)
72 100
73 def iter_over_period(self, start, end, start_no, end_no, list_type, event_types): 101 def iter_over_period(self, start, end, start_no, end_no, list_type, event_types):
74 if self.array is None: 102 if self.array is None:
@@ -142,18 +170,28 @@ class Schedule(object):
142 self.set_time_params(time_per_maj) 170 self.set_time_params(time_per_maj)
143 171
144 # we scan the graph task by task, and job by job 172 # we scan the graph task by task, and job by job
145 switches = {}
146 for event in EVENT_LIST:
147 switches[event] = None
148 for task_no, task in enumerate(self.get_task_list()): 173 for task_no, task in enumerate(self.get_task_list()):
174 switches = {}
175 for event in EVENT_LIST:
176 switches[event] = None
149 cur_cpu = [Event.NO_CPU] 177 cur_cpu = [Event.NO_CPU]
150 for job_no in sorted(task.get_jobs().keys()): 178 for job_no in sorted(task.get_jobs().keys()):
151 job = task.get_jobs()[job_no] 179 job = task.get_jobs()[job_no]
152 for event_time in sorted(job.get_events().keys()): 180 for event_time in sorted(job.get_events().keys()):
153 # could have multiple events at the same time (unlikely but possible) 181 # could have multiple events at the same time (unlikely but possible)
154 for event in job.get_events()[event_time]: 182 for event in job.get_events()[event_time]:
155 #print 'task, job, event:', task.name, job.job_no, event.__class__.__name__ 183 print 'task, job, event:', task.name, job.job_no, event.__class__.__name__
156 event.scan(cur_cpu, switches) 184 event.scan(cur_cpu, switches)
185
186 # What if one of the initial "span events" (switch to or inversion starting) never got a
187 # corresponding end event? Well, then we assume that the end event was simply outside of
188 # the range of whatever we read in. So we need to fill dummies starting from the initial
189 # event all the way to the end of the graph, so that the renderer can see the event no matter
190 # how far the user scrolls to the right.
191 for span_event in SPAN_START_EVENTS:
192 event = switches[span_event]
193 if event is not None:
194 self.time_slot_array.fill_span_event_from_start(event)
157 195
158 def add_task(self, task): 196 def add_task(self, task):
159 if task.name in self.tasks: 197 if task.name in self.tasks:
@@ -311,7 +349,7 @@ class Event(DummyEvent):
311 sched.start = time 349 sched.start = time
312 if sched.end is None or time > sched.end: 350 if sched.end is None or time > sched.end:
313 sched.end = time 351 sched.end = time
314 352
315 sched.get_time_slot_array().add_event_to_time_slot(self) 353 sched.get_time_slot_array().add_event_to_time_slot(self)
316 354
317class ErrorEvent(Event): 355class ErrorEvent(Event):
@@ -387,11 +425,59 @@ class CompleteEvent(Event):
387 else: 425 else:
388 graph.draw_completion_marker_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 426 graph.draw_completion_marker_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
389 self.get_cpu(), self.is_selected()) 427 self.get_cpu(), self.is_selected())
428
429class SwitchToEvent(Event):
430 def __init__(self, time, cpu):
431 super(SwitchToEvent, self).__init__(time, cpu)
432 self.layer = Canvas.BOTTOM_LAYER
433 self.corresp_end_event = None
434
435 def __str__(self):
436 if self.corresp_end_event is None:
437 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \
438 + str(self.get_time())
439 return 'Scheduled' + self._common_str() + ', START=' \
440 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
441 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
442
443 def scan(self, cur_cpu, switches):
444 old_cur_cpu = cur_cpu[0]
445 cur_cpu[0] = self.get_cpu()
446 switches[SwitchToEvent] = self
447 self.corresp_end_event = None
390 448
449 if old_cur_cpu != Event.NO_CPU:
450 self.erroneous = True
451 print "currently scheduled somewhere, can't switch to a CPU"
452
453 super(SwitchToEvent, self).scan(cur_cpu, switches)
454
455 def render(self, graph, layer, prev_events, selectable=False):
456 if layer == self.layer:
457 end_time = None
458 clip = None
459 if self.corresp_end_event is None:
460 end_time = self.get_job().get_task().get_schedule().end
461 clip = AlignMode.RIGHT
462 else:
463 end_time = self.corresp_end_event.get_time()
464
465 prev_events[self] = None
466 cpu = self.get_cpu()
467 task_no = self.get_job().get_task().get_task_no()
468 if selectable:
469 graph.add_sel_bar_at_time(self.get_time(), end_time,
470 task_no, cpu, self)
471 else:
472 graph.draw_bar_at_time(self.get_time(), end_time,
473 task_no, cpu, self.get_job().get_job_no(),
474 clip, self.is_selected())
475
391class SwitchAwayEvent(Event): 476class SwitchAwayEvent(Event):
392 def __init__(self, time, cpu): 477 def __init__(self, time, cpu):
393 super(SwitchAwayEvent, self).__init__(time, cpu) 478 super(SwitchAwayEvent, self).__init__(time, cpu)
394 self.layer = Canvas.BOTTOM_LAYER 479 self.layer = Canvas.BOTTOM_LAYER
480 self.corresp_start_event = None
395 481
396 def __str__(self): 482 def __str__(self):
397 if self.corresp_start_event is None: 483 if self.corresp_start_event is None:
@@ -431,63 +517,19 @@ class SwitchAwayEvent(Event):
431 prev_events[self] = None 517 prev_events[self] = None
432 cpu = self.get_cpu() 518 cpu = self.get_cpu()
433 task_no = self.get_job().get_task().get_task_no() 519 task_no = self.get_job().get_task().get_task_no()
520 start = self.get_job().get_task().get_schedule().start
434 if selectable: 521 if selectable:
435 start = self.get_job().get_task().get_schedule().start
436 graph.add_sel_bar_at_time(start, self.get_time(), 522 graph.add_sel_bar_at_time(start, self.get_time(),
437 task_no, cpu, self) 523 task_no, cpu, self)
438 else: 524 else:
439 graph.draw_bar_at_time(start, self.get_time(), 525 graph.draw_bar_at_time(start, self.get_time(),
440 task_no, cpu, self.get_job().get_job_no(), self.is_selected()) 526 task_no, cpu, self.get_job().get_job_no(),
527 AlignMode.LEFT, self.is_selected())
441 else: 528 else:
442 if self.corresp_start_event in prev_events: 529 if self.corresp_start_event in prev_events:
443 return # already rendered the bar 530 return # already rendered the bar
444 self.corresp_start_event.render(graph, layer, prev_events, selectable) 531 self.corresp_start_event.render(graph, layer, prev_events, selectable)
445 532
446class SwitchToEvent(Event):
447 def __init__(self, time, cpu):
448 super(SwitchToEvent, self).__init__(time, cpu)
449 self.layer = Canvas.BOTTOM_LAYER
450
451 def __str__(self):
452 if self.corresp_end_event is None:
453 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \
454 + str(self.get_time())
455 return 'Scheduled' + self._common_str() + ', START=' \
456 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
457 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
458
459 def scan(self, cur_cpu, switches):
460 old_cur_cpu = cur_cpu[0]
461 cur_cpu[0] = self.get_cpu()
462 switches[SwitchToEvent] = self
463 self.corresp_end_event = None
464
465 if old_cur_cpu != Event.NO_CPU:
466 self.erroneous = True
467 print "currently scheduled somewhere, can't switch to a CPU"
468
469 super(SwitchToEvent, self).scan(cur_cpu, switches)
470
471 def render(self, graph, layer, prev_events, selectable=False):
472 if self.corresp_end_event is None:
473 return # fatally erroneous switch to
474 if layer == self.layer:
475 end_time = None
476 if self.corresp_end_event is None:
477 end_time = self.get_job().get_task().get_schedule().end
478 else:
479 end_time = self.corresp_end_event.get_time()
480
481 prev_events[self] = None
482 cpu = self.get_cpu()
483 task_no = self.get_job().get_task().get_task_no()
484 if selectable:
485 graph.add_sel_bar_at_time(self.get_time(), end_time,
486 task_no, cpu, self)
487 else:
488 graph.draw_bar_at_time(self.get_time(), end_time,
489 task_no, cpu, self.get_job().get_job_no(), self.is_selected())
490
491class ReleaseEvent(Event): 533class ReleaseEvent(Event):
492 def __init__(self, time, cpu): 534 def __init__(self, time, cpu):
493 super(ReleaseEvent, self).__init__(time, cpu) 535 super(ReleaseEvent, self).__init__(time, cpu)
@@ -536,6 +578,7 @@ class InversionStartEvent(ErrorEvent):
536 def __init__(self, time): 578 def __init__(self, time):
537 super(InversionStartEvent, self).__init__(time, Event.NO_CPU) 579 super(InversionStartEvent, self).__init__(time, Event.NO_CPU)
538 self.layer = Canvas.BOTTOM_LAYER 580 self.layer = Canvas.BOTTOM_LAYER
581 self.corresp_end_event = None
539 582
540 def __str__(self): 583 def __str__(self):
541 if self.corresp_end_event is None: 584 if self.corresp_end_event is None:
@@ -553,28 +596,33 @@ class InversionStartEvent(ErrorEvent):
553 super(InversionStartEvent, self).scan(cur_cpu, switches) 596 super(InversionStartEvent, self).scan(cur_cpu, switches)
554 597
555 def render(self, graph, layer, prev_events, selectable=False): 598 def render(self, graph, layer, prev_events, selectable=False):
556 end_time = None
557 if self.corresp_end_event is None:
558 end_time = self.get_job().get_task().get_schedule().end
559 else:
560 end_time = self.corresp_end_event.get_time()
561
562 if layer == self.layer: 599 if layer == self.layer:
563 prev_events[self] = None 600 end_time = None
564 cpu = self.get_cpu() 601 clip = None
565 task_no = self.get_job().get_task().get_task_no() 602 if self.corresp_end_event is None:
566 if selectable: 603 end_time = self.get_job().get_task().get_schedule().end
567 graph.add_sel_mini_bar_at_time(self.get_time(), end_time, 604 clip = AlignMode.RIGHT
568 task_no, cpu, self)
569 else: 605 else:
570 graph.draw_mini_bar_at_time(self.get_time(), end_time, 606 end_time = self.corresp_end_event.get_time()
571 task_no, cpu, self.get_job().get_job_no(), self.is_selected()) 607
608 if layer == self.layer:
609 prev_events[self] = None
610 cpu = self.get_cpu()
611 task_no = self.get_job().get_task().get_task_no()
612 if selectable:
613 graph.add_sel_mini_bar_at_time(self.get_time(), end_time,
614 task_no, cpu, self)
615 else:
616 graph.draw_mini_bar_at_time(self.get_time(), end_time,
617 task_no, cpu, self.get_job().get_job_no(),
618 clip, self.is_selected())
572 619
573 620
574class InversionEndEvent(ErrorEvent): 621class InversionEndEvent(ErrorEvent):
575 def __init__(self, time): 622 def __init__(self, time):
576 super(InversionEndEvent, self).__init__(time, Event.NO_CPU) 623 super(InversionEndEvent, self).__init__(time, Event.NO_CPU)
577 self.layer = Canvas.BOTTOM_LAYER 624 self.layer = Canvas.BOTTOM_LAYER
625 self.corresp_start_event = None
578 626
579 def __str__(self): 627 def __str__(self):
580 if self.corresp_start_event is None: 628 if self.corresp_start_event is None:
@@ -607,13 +655,14 @@ class InversionEndEvent(ErrorEvent):
607 prev_events[self] = None 655 prev_events[self] = None
608 cpu = self.get_cpu() 656 cpu = self.get_cpu()
609 task_no = self.get_job().get_task().get_task_no() 657 task_no = self.get_job().get_task().get_task_no()
658 start = self.get_job().get_task().get_schedule().start
610 if selectable: 659 if selectable:
611 start = self.get_job().get_task().get_schedule().start
612 graph.add_sel_mini_bar_at_time(start, self.get_time(), 660 graph.add_sel_mini_bar_at_time(start, self.get_time(),
613 task_no, cpu, self) 661 task_no, cpu, self)
614 else: 662 else:
615 graph.draw_mini_bar_at_time(start, self.get_time(), 663 graph.draw_mini_bar_at_time(start, self.get_time(),
616 task_no, cpu, self.get_job().get_job_no(), self.is_selected()) 664 task_no, cpu, self.get_job().get_job_no(),
665 AlignMode.LEFT, self.is_selected())
617 else: 666 else:
618 if self.corresp_start_event in prev_events: 667 if self.corresp_start_event in prev_events:
619 return # already rendered the bar 668 return # already rendered the bar
@@ -625,11 +674,14 @@ class InversionDummy(DummyEvent):
625 self.layer = Canvas.BOTTOM_LAYER 674 self.layer = Canvas.BOTTOM_LAYER
626 675
627 def render(self, graph, layer, prev_events, selectable=False): 676 def render(self, graph, layer, prev_events, selectable=False):
628 if self.corresp_start_event is not None and self.corresp_start_event in prev_events: 677 if self.corresp_start_event is None:
629 return # we have already been rendered 678 if self.corresp_end_event in prev_events:
630 if self.corresp_end_event is not None and self.corresp_end_event in prev_events: 679 return # we have already been rendered
631 return 680 self.corresp_end_event.render(graph, layer, prev_events, selectable)
632 self.corresp_start_event.render(graph, layer, prev_events, selectable) 681 else:
682 if self.corresp_start_event in prev_events:
683 return # we have already been rendered
684 self.corresp_start_event.render(graph, layer, prev_events, selectable)
633 685
634class IsRunningDummy(DummyEvent): 686class IsRunningDummy(DummyEvent):
635 def __init__(self, time, cpu): 687 def __init__(self, time, cpu):
@@ -637,12 +689,20 @@ class IsRunningDummy(DummyEvent):
637 self.layer = Canvas.BOTTOM_LAYER 689 self.layer = Canvas.BOTTOM_LAYER
638 690
639 def render(self, graph, layer, prev_events, selectable=False): 691 def render(self, graph, layer, prev_events, selectable=False):
640 if self.corresp_start_event is None or self.corresp_start_event in prev_events: 692 if self.corresp_start_event is None:
641 return # we have already been rendered 693 if self.corresp_end_event in prev_events:
642 self.corresp_start_event.render(graph, layer, prev_events, selectable) 694 return # we have already been rendered
695 self.corresp_end_event.render(graph, layer, prev_events, selectable)
696 else:
697 if self.corresp_start_event in prev_events:
698 return # we have already been rendered
699 self.corresp_start_event.render(graph, layer, prev_events, selectable)
643 700
644EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None, 701EVENT_LIST = {SuspendEvent : None, ResumeEvent : None, CompleteEvent : None,
645 SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None, 702 SwitchAwayEvent : None, SwitchToEvent : None, ReleaseEvent : None,
646 DeadlineEvent : None, IsRunningDummy : None, 703 DeadlineEvent : None, IsRunningDummy : None,
647 InversionStartEvent : None, InversionEndEvent : None, 704 InversionStartEvent : None, InversionEndEvent : None,
648 InversionDummy : None} 705 InversionDummy : None}
706
707SPAN_START_EVENTS = { SwitchToEvent : IsRunningDummy, InversionStartEvent : InversionDummy }
708SPAN_END_EVENTS = { SwitchAwayEvent : IsRunningDummy, InversionEndEvent : InversionDummy}
diff --git a/unit_trace/viz/viewer.py b/unit_trace/viz/viewer.py
index 236a467..909da76 100644
--- a/unit_trace/viz/viewer.py
+++ b/unit_trace/viz/viewer.py
@@ -68,7 +68,6 @@ class GraphArea(gtk.DrawingArea):
68 # window manager must have caused the expose event. So just update the 68 # window manager must have caused the expose event. So just update the
69 # expose_event's bounding area. 69 # expose_event's bounding area.
70 if not self.dirtied_regions or expose_event.send_event: 70 if not self.dirtied_regions or expose_event.send_event:
71 print 'forced expose'
72 self.dirtied_regions = [(expose_event.area.x, expose_event.area.y, 71 self.dirtied_regions = [(expose_event.area.x, expose_event.area.y,
73 expose_event.area.width, expose_event.area.height)] 72 expose_event.area.width, expose_event.area.height)]
74 73