summaryrefslogtreecommitdiffstats
path: root/unit_trace/viz/schedule.py
diff options
context:
space:
mode:
Diffstat (limited to 'unit_trace/viz/schedule.py')
-rw-r--r--unit_trace/viz/schedule.py252
1 files changed, 126 insertions, 126 deletions
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py
index f134562..71f42ec 100644
--- a/unit_trace/viz/schedule.py
+++ b/unit_trace/viz/schedule.py
@@ -18,19 +18,19 @@ class TimeSlotArray(object):
18 the (approximate) time at which they occur. Events that occur at approximately the same 18 the (approximate) time at which they occur. Events that occur at approximately the same
19 time are assigned the same ``slot'', and each slot organizes its events by task number 19 time are assigned the same ``slot'', and each slot organizes its events by task number
20 as well as by CPU.""" 20 as well as by CPU."""
21 21
22 TASK_LIST = 0 22 TASK_LIST = 0
23 CPU_LIST = 1 23 CPU_LIST = 1
24 24
25 def __init__(self, time_per_maj=None, num_tasks=0, num_cpus=0): 25 def __init__(self, time_per_maj=None, num_tasks=0, num_cpus=0):
26 if time_per_maj is None: 26 if time_per_maj is None:
27 self.array = None 27 self.array = None
28 return 28 return
29 29
30 self.time_per_maj = time_per_maj 30 self.time_per_maj = time_per_maj
31 self.list_sizes = { TimeSlotArray.TASK_LIST : num_tasks, TimeSlotArray.CPU_LIST : num_cpus } 31 self.list_sizes = { TimeSlotArray.TASK_LIST : num_tasks, TimeSlotArray.CPU_LIST : num_cpus }
32 self.array = {} 32 self.array = {}
33 33
34 for type in self.list_sizes: 34 for type in self.list_sizes:
35 num = self.list_sizes[type] 35 num = self.list_sizes[type]
36 self.array[type] = [] 36 self.array[type] = []
@@ -40,26 +40,26 @@ class TimeSlotArray(object):
40 # by task). 40 # by task).
41 self.array[type].append(dict(zip(EVENT_LIST, \ 41 self.array[type].append(dict(zip(EVENT_LIST, \
42 [{} for j in range(0, len(EVENT_LIST))]))) 42 [{} for j in range(0, len(EVENT_LIST))])))
43 43
44 def get_time_slot(self, time): 44 def get_time_slot(self, time):
45 return int(time // self.time_per_maj) 45 return int(time // self.time_per_maj)
46 46
47 def _put_event_in_slot(self, list_type, no, klass, slot, event): 47 def _put_event_in_slot(self, list_type, no, klass, slot, event):
48 if slot not in self.array[list_type][no][klass]: 48 if slot not in self.array[list_type][no][klass]:
49 self.array[list_type][no][klass][slot] = [] 49 self.array[list_type][no][klass][slot] = []
50 self.array[list_type][no][klass][slot].append(event) 50 self.array[list_type][no][klass][slot].append(event)
51 51
52 def add_event_to_time_slot(self, event): 52 def add_event_to_time_slot(self, event):
53 task_no = event.get_job().get_task().get_task_no() 53 task_no = event.get_job().get_task().get_task_no()
54 cpu = event.get_cpu() 54 cpu = event.get_cpu()
55 time_slot = self.get_time_slot(event.get_time()) 55 time_slot = self.get_time_slot(event.get_time())
56 56
57 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)
58 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 59
60 if event.__class__ in SPAN_END_EVENTS: 60 if event.__class__ in SPAN_END_EVENTS:
61 self.fill_span_event_from_end(event) 61 self.fill_span_event_from_end(event)
62 62
63 def fill_span_event_from_end(self, event): 63 def fill_span_event_from_end(self, event):
64 start_slot = None 64 start_slot = None
65 if event.corresp_start_event is None: 65 if event.corresp_start_event is None:
@@ -67,18 +67,18 @@ class TimeSlotArray(object):
67 else: 67 else:
68 start_slot = self.get_time_slot(event.corresp_start_event.get_time()) 68 start_slot = self.get_time_slot(event.corresp_start_event.get_time())
69 end_slot = self.get_time_slot(event.get_time()) 69 end_slot = self.get_time_slot(event.get_time())
70 70
71 for slot in range(start_slot + 1, end_slot): 71 for slot in range(start_slot + 1, end_slot):
72 task_no = event.get_job().get_task().get_task_no() 72 task_no = event.get_job().get_task().get_task_no()
73 cpu = event.get_cpu() 73 cpu = event.get_cpu()
74 74
75 dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu) 75 dummy = SPAN_END_EVENTS[event.__class__](task_no, cpu)
76 dummy.corresp_start_event = event.corresp_start_event 76 dummy.corresp_start_event = event.corresp_start_event
77 dummy.corresp_end_event = event 77 dummy.corresp_end_event = event
78 78
79 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)
80 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 81
82 def fill_span_event_from_start(self, event): 82 def fill_span_event_from_start(self, event):
83 end_slot = None 83 end_slot = None
84 if event.corresp_end_event is None: 84 if event.corresp_end_event is None:
@@ -86,44 +86,44 @@ class TimeSlotArray(object):
86 else: 86 else:
87 end_slot = self.get_time_slot(event.corresp_end_event.get_time()) 87 end_slot = self.get_time_slot(event.corresp_end_event.get_time())
88 start_slot = self.get_time_slot(event.get_time()) 88 start_slot = self.get_time_slot(event.get_time())
89 89
90 for slot in range(start_slot + 1, end_slot): 90 for slot in range(start_slot + 1, end_slot):
91 task_no = event.get_job().get_task().get_task_no() 91 task_no = event.get_job().get_task().get_task_no()
92 cpu = event.get_cpu() 92 cpu = event.get_cpu()
93 93
94 dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu) 94 dummy = SPAN_START_EVENTS[event.__class__](task_no, cpu)
95 dummy.corresp_start_event = event 95 dummy.corresp_start_event = event
96 dummy.corresp_end_event = event.corresp_end_event 96 dummy.corresp_end_event = event.corresp_end_event
97 97
98 self._put_event_in_slot(TimeSlotArray.TASK_LIST, task_no, dummy.__class__, slot, dummy) 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) 99 self._put_event_in_slot(TimeSlotArray.CPU_LIST, cpu, dummy.__class__, slot, dummy)
100 100
101 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):
102 if self.array is None: 102 if self.array is None:
103 return # empty schedule 103 return # empty schedule
104 104
105 if start > end: 105 if start > end:
106 raise ValueError('Litmus is not a time machine') 106 raise ValueError('Litmus is not a time machine')
107 if start_no > end_no: 107 if start_no > end_no:
108 raise ValueError('start no should be less than end no') 108 raise ValueError('start no should be less than end no')
109 109
110 start_slot = self.get_time_slot(start) 110 start_slot = self.get_time_slot(start)
111 end_slot = self.get_time_slot(end) + 2 111 end_slot = self.get_time_slot(end) + 2
112 112
113 start_no = max(0, start_no) 113 start_no = max(0, start_no)
114 end_no = min(self.list_sizes[list_type] - 1, end_no) 114 end_no = min(self.list_sizes[list_type] - 1, end_no)
115 115
116 for no in range(start_no, end_no + 1): 116 for no in range(start_no, end_no + 1):
117 for type in event_types: 117 for type in event_types:
118 for slot in range(start_slot, end_slot): 118 for slot in range(start_slot, end_slot):
119 if slot in self.array[list_type][no][type]: 119 if slot in self.array[list_type][no][type]:
120 for event in self.array[list_type][no][type][slot]: 120 for event in self.array[list_type][no][type][slot]:
121 yield event 121 yield event
122 122
123class Schedule(object): 123class Schedule(object):
124 """The total schedule (task system), consisting of a certain number of 124 """The total schedule (task system), consisting of a certain number of
125 tasks.""" 125 tasks."""
126 126
127 def __init__(self, name, num_cpus, task_list=[]): 127 def __init__(self, name, num_cpus, task_list=[]):
128 self.name = name 128 self.name = name
129 self.tasks = {} 129 self.tasks = {}
@@ -134,41 +134,41 @@ class Schedule(object):
134 self.num_cpus = num_cpus 134 self.num_cpus = num_cpus
135 for task in task_list: 135 for task in task_list:
136 self.add_task(task) 136 self.add_task(task)
137 137
138 def get_selected(self): 138 def get_selected(self):
139 return self.selected 139 return self.selected
140 140
141 def set_selected(self, new_selected): 141 def set_selected(self, new_selected):
142 for event in self.selected: 142 for event in self.selected:
143 event.selected = False 143 event.selected = False
144 for event in new_selected: 144 for event in new_selected:
145 event.selected = True 145 event.selected = True
146 self.selected = new_selected 146 self.selected = new_selected
147 147
148 def get_selected(self): 148 def get_selected(self):
149 return copy.copy(self.selected) 149 return copy.copy(self.selected)
150 150
151 def set_time_params(self, time_per_maj=None): 151 def set_time_params(self, time_per_maj=None):
152 self.time_per_maj = time_per_maj 152 self.time_per_maj = time_per_maj
153 if self.time_per_maj is None: 153 if self.time_per_maj is None:
154 self.time_slot_array = TimeSlotArray() 154 self.time_slot_array = TimeSlotArray()
155 return 155 return
156 156
157 self.time_slot_array = TimeSlotArray(self.time_per_maj, \ 157 self.time_slot_array = TimeSlotArray(self.time_per_maj, \
158 len(self.task_list), self.num_cpus) 158 len(self.task_list), self.num_cpus)
159 159
160 def get_time_slot_array(self): 160 def get_time_slot_array(self):
161 return self.time_slot_array 161 return self.time_slot_array
162 162
163 def get_time_bounds(self): 163 def get_time_bounds(self):
164 return (self.start, self.end) 164 return (self.start, self.end)
165 165
166 def scan(self, time_per_maj): 166 def scan(self, time_per_maj):
167 self.start = None 167 self.start = None
168 self.end = None 168 self.end = None
169 169
170 self.set_time_params(time_per_maj) 170 self.set_time_params(time_per_maj)
171 171
172 # we scan the graph task by task, and job by job 172 # we scan the graph task by task, and job by job
173 for task_no, task in enumerate(self.get_task_list()): 173 for task_no, task in enumerate(self.get_task_list()):
174 switches = {} 174 switches = {}
@@ -176,12 +176,12 @@ class Schedule(object):
176 switches[event] = None 176 switches[event] = None
177 cur_cpu = [Event.NO_CPU] 177 cur_cpu = [Event.NO_CPU]
178 for job_no in sorted(task.get_jobs().keys()): 178 for job_no in sorted(task.get_jobs().keys()):
179 job = task.get_jobs()[job_no] 179 job = task.get_jobs()[job_no]
180 for event_time in sorted(job.get_events().keys()): 180 for event_time in sorted(job.get_events().keys()):
181 # could have multiple events at the same time (unlikely but possible) 181 # could have multiple events at the same time (unlikely but possible)
182 for event in job.get_events()[event_time]: 182 for event in job.get_events()[event_time]:
183 event.scan(cur_cpu, switches) 183 event.scan(cur_cpu, switches)
184 184
185 # What if one of the initial "span events" (switch to or inversion starting) never got a 185 # What if one of the initial "span events" (switch to or inversion starting) never got a
186 # corresponding end event? Well, then we assume that the end event was simply outside of 186 # corresponding end event? Well, then we assume that the end event was simply outside of
187 # the range of whatever we read in. So we need to fill dummies starting from the initial 187 # the range of whatever we read in. So we need to fill dummies starting from the initial
@@ -191,7 +191,7 @@ class Schedule(object):
191 event = switches[span_event] 191 event = switches[span_event]
192 if event is not None: 192 if event is not None:
193 self.time_slot_array.fill_span_event_from_start(event) 193 self.time_slot_array.fill_span_event_from_start(event)
194 194
195 def add_task(self, task): 195 def add_task(self, task):
196 if task.name in self.tasks: 196 if task.name in self.tasks:
197 raise ValueError("task already in list!") 197 raise ValueError("task already in list!")
@@ -200,23 +200,23 @@ class Schedule(object):
200 task.schedule = self 200 task.schedule = self
201 task.task_no = self.cur_task_no 201 task.task_no = self.cur_task_no
202 self.cur_task_no += 1 202 self.cur_task_no += 1
203 203
204 def get_tasks(self): 204 def get_tasks(self):
205 return self.tasks 205 return self.tasks
206 206
207 def get_task_list(self): 207 def get_task_list(self):
208 return self.task_list 208 return self.task_list
209 209
210 def get_name(self): 210 def get_name(self):
211 return self.name 211 return self.name
212 212
213 def get_num_cpus(self): 213 def get_num_cpus(self):
214 return self.num_cpus 214 return self.num_cpus
215 215
216class Task(object): 216class Task(object):
217 """Represents a task, including the set of jobs that were run under 217 """Represents a task, including the set of jobs that were run under
218 this task.""" 218 this task."""
219 219
220 def __init__(self, name, job_list=[]): 220 def __init__(self, name, job_list=[]):
221 self.name = name 221 self.name = name
222 self.jobs = {} 222 self.jobs = {}
@@ -224,25 +224,25 @@ class Task(object):
224 self.schedule = None 224 self.schedule = None
225 for job in job_list: 225 for job in job_list:
226 self.add_job(job) 226 self.add_job(job)
227 227
228 def add_job(self, job): 228 def add_job(self, job):
229 if job.job_no in self.jobs: 229 if job.job_no in self.jobs:
230 raise ScheduleError("a job is already being released at this time for this task") 230 raise ScheduleError("a job is already being released at this time for this task")
231 self.jobs[job.job_no] = job 231 self.jobs[job.job_no] = job
232 job.task = self 232 job.task = self
233 233
234 def get_schedule(self): 234 def get_schedule(self):
235 return self.schedule 235 return self.schedule
236 236
237 def get_jobs(self): 237 def get_jobs(self):
238 return self.jobs 238 return self.jobs
239 239
240 def get_task_no(self): 240 def get_task_no(self):
241 return self.task_no 241 return self.task_no
242 242
243 def get_name(self): 243 def get_name(self):
244 return self.name 244 return self.name
245 245
246class Job(object): 246class Job(object):
247 """Represents a job, including everything that happens related to the job""" 247 """Represents a job, including everything that happens related to the job"""
248 def __init__(self, job_no, event_list=[]): 248 def __init__(self, job_no, event_list=[]):
@@ -251,19 +251,19 @@ class Job(object):
251 self.task = None 251 self.task = None
252 for event in event_list: 252 for event in event_list:
253 self.add_event(event) 253 self.add_event(event)
254 254
255 def add_event(self, event): 255 def add_event(self, event):
256 if event.time not in self.events: 256 if event.time not in self.events:
257 self.events[event.time] = [] 257 self.events[event.time] = []
258 self.events[event.time].append(event) 258 self.events[event.time].append(event)
259 event.job = self 259 event.job = self
260 260
261 def get_events(self): 261 def get_events(self):
262 return self.events 262 return self.events
263 263
264 def get_task(self): 264 def get_task(self):
265 return self.task 265 return self.task
266 266
267 def get_job_no(self): 267 def get_job_no(self):
268 return self.job_no 268 return self.job_no
269 269
@@ -279,61 +279,61 @@ class DummyEvent(object):
279 self.cpu = cpu 279 self.cpu = cpu
280 self.job = None 280 self.job = None
281 self.layer = None 281 self.layer = None
282 282
283 def __str__(self): 283 def __str__(self):
284 return '[Dummy Event]' 284 return '[Dummy Event]'
285 285
286 def get_time(self): 286 def get_time(self):
287 return self.time 287 return self.time
288 288
289 def get_cpu(self): 289 def get_cpu(self):
290 return self.cpu 290 return self.cpu
291 291
292 def get_job(self): 292 def get_job(self):
293 return self.job 293 return self.job
294 294
295 def get_layer(self): 295 def get_layer(self):
296 return self.layer 296 return self.layer
297 297
298 def render(self, graph, layer, prev_events, selectable=False): 298 def render(self, graph, layer, prev_events, selectable=False):
299 """Method that the visualizer calls to tell the event to render itself 299 """Method that the visualizer calls to tell the event to render itself
300 Obviously only implemented by subclasses (actual event types) 300 Obviously only implemented by subclasses (actual event types)
301 301
302 ``Rendering'' can mean either actually drawing the event or just 302 ``Rendering'' can mean either actually drawing the event or just
303 adding it as a selectable region. This is controlled by the 303 adding it as a selectable region. This is controlled by the
304 ``selectable'' parameter""" 304 ``selectable'' parameter"""
305 raise NotImplementdError 305 raise NotImplementdError
306 306
307class Event(DummyEvent): 307class Event(DummyEvent):
308 """Represents an event that occurs while a job is running (e.g. get scheduled 308 """Represents an event that occurs while a job is running (e.g. get scheduled
309 on a CPU, block, ...)""" 309 on a CPU, block, ...)"""
310 NO_CPU = -1 310 NO_CPU = -1
311 NUM_DEC_PLACES = 2 311 NUM_DEC_PLACES = 2
312 312
313 def __init__(self, time, cpu): 313 def __init__(self, time, cpu):
314 super(Event, self).__init__(time, cpu) 314 super(Event, self).__init__(time, cpu)
315 self.erroneous = False 315 self.erroneous = False
316 self.selected = False 316 self.selected = False
317 317
318 def __str__(self): 318 def __str__(self):
319 return '[Event]' 319 return '[Event]'
320 320
321 def _common_str(self): 321 def _common_str(self):
322 job = self.get_job() 322 job = self.get_job()
323 task = job.get_task() 323 task = job.get_task()
324 return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \ 324 return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \
325 job.get_job_no())) + ', CPU=' + str(self.get_cpu()) 325 job.get_job_no())) + ', CPU=' + str(self.get_cpu())
326 326
327 def is_erroneous(self): 327 def is_erroneous(self):
328 """An erroneous event is where something with the event is not quite right, 328 """An erroneous event is where something with the event is not quite right,
329 something significantly wrong that we don't have logical information telling 329 something significantly wrong that we don't have logical information telling
330 us how we should render the event.""" 330 us how we should render the event."""
331 return self.erroneous 331 return self.erroneous
332 332
333 def is_selected(self): 333 def is_selected(self):
334 """Returns whether the event has been selected by the user. (needed for rendering)""" 334 """Returns whether the event has been selected by the user. (needed for rendering)"""
335 return self.selected 335 return self.selected
336 336
337 def scan(self, cur_cpu, switches): 337 def scan(self, cur_cpu, switches):
338 """Part of the procedure that walks through all the events and sets 338 """Part of the procedure that walks through all the events and sets
339 some parameters that are unknown at first. For instance, a SwitchAwayEvent 339 some parameters that are unknown at first. For instance, a SwitchAwayEvent
@@ -348,26 +348,26 @@ class Event(DummyEvent):
348 sched.start = time 348 sched.start = time
349 if sched.end is None or time > sched.end: 349 if sched.end is None or time > sched.end:
350 sched.end = time 350 sched.end = time
351 351
352 sched.get_time_slot_array().add_event_to_time_slot(self) 352 sched.get_time_slot_array().add_event_to_time_slot(self)
353 353
354class ErrorEvent(Event): 354class ErrorEvent(Event):
355 pass 355 pass
356 356
357class SuspendEvent(Event): 357class SuspendEvent(Event):
358 def __init__(self, time, cpu): 358 def __init__(self, time, cpu):
359 super(SuspendEvent, self).__init__(time, cpu) 359 super(SuspendEvent, self).__init__(time, cpu)
360 self.layer = Canvas.MIDDLE_LAYER 360 self.layer = Canvas.MIDDLE_LAYER
361 361
362 def __str__(self): 362 def __str__(self):
363 return 'Suspend' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 363 return 'Suspend' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
364 364
365 def scan(self, cur_cpu, switches): 365 def scan(self, cur_cpu, switches):
366 if self.get_cpu() != cur_cpu[0]: 366 if self.get_cpu() != cur_cpu[0]:
367 self.erroneous = True 367 self.erroneous = True
368 #fprint "suspending on a CPU different from the CPU we are on!" 368 #fprint "suspending on a CPU different from the CPU we are on!"
369 super(SuspendEvent, self).scan(cur_cpu, switches) 369 super(SuspendEvent, self).scan(cur_cpu, switches)
370 370
371 def render(self, graph, layer, prev_events, selectable=False): 371 def render(self, graph, layer, prev_events, selectable=False):
372 if layer == self.layer: 372 if layer == self.layer:
373 prev_events[self] = None 373 prev_events[self] = None
@@ -377,22 +377,22 @@ class SuspendEvent(Event):
377 else: 377 else:
378 graph.draw_suspend_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 378 graph.draw_suspend_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
379 self.get_cpu(), self.is_selected()) 379 self.get_cpu(), self.is_selected())
380 380
381 381
382class ResumeEvent(Event): 382class ResumeEvent(Event):
383 def __init__(self, time, cpu): 383 def __init__(self, time, cpu):
384 super(ResumeEvent, self).__init__(time, cpu) 384 super(ResumeEvent, self).__init__(time, cpu)
385 self.layer = Canvas.MIDDLE_LAYER 385 self.layer = Canvas.MIDDLE_LAYER
386 386
387 def __str__(self): 387 def __str__(self):
388 return 'Resume' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 388 return 'Resume' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
389 389
390 def scan(self, cur_cpu, switches): 390 def scan(self, cur_cpu, switches):
391 if cur_cpu[0] != Event.NO_CPU and cur_cpu[0] != self.get_cpu(): 391 if cur_cpu[0] != Event.NO_CPU and cur_cpu[0] != self.get_cpu():
392 self.erroneous = True 392 self.erroneous = True
393 #print "Resuming when currently scheduled on a CPU, but on a different CPU from the current CPU!" 393 #print "Resuming when currently scheduled on a CPU, but on a different CPU from the current CPU!"
394 super(ResumeEvent, self).scan(cur_cpu, switches) 394 super(ResumeEvent, self).scan(cur_cpu, switches)
395 395
396 def render(self, graph, layer, prev_events, selectable=False): 396 def render(self, graph, layer, prev_events, selectable=False):
397 if layer == self.layer: 397 if layer == self.layer:
398 prev_events[self] = None 398 prev_events[self] = None
@@ -402,19 +402,19 @@ class ResumeEvent(Event):
402 else: 402 else:
403 graph.draw_resume_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 403 graph.draw_resume_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
404 self.get_cpu(), self.is_selected()) 404 self.get_cpu(), self.is_selected())
405 405
406 406
407class CompleteEvent(Event): 407class CompleteEvent(Event):
408 def __init__(self, time, cpu): 408 def __init__(self, time, cpu):
409 super(CompleteEvent, self).__init__(time, cpu) 409 super(CompleteEvent, self).__init__(time, cpu)
410 self.layer = Canvas.TOP_LAYER 410 self.layer = Canvas.TOP_LAYER
411 411
412 def __str__(self): 412 def __str__(self):
413 return 'Complete' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 413 return 'Complete' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
414 414
415 def scan(self, cur_cpu, switches): 415 def scan(self, cur_cpu, switches):
416 super(CompleteEvent, self).scan(cur_cpu, switches) 416 super(CompleteEvent, self).scan(cur_cpu, switches)
417 417
418 def render(self, graph, layer, prev_events, selectable=False): 418 def render(self, graph, layer, prev_events, selectable=False):
419 if layer == Canvas.TOP_LAYER: 419 if layer == Canvas.TOP_LAYER:
420 prev_events[self] = None 420 prev_events[self] = None
@@ -430,7 +430,7 @@ class SwitchToEvent(Event):
430 super(SwitchToEvent, self).__init__(time, cpu) 430 super(SwitchToEvent, self).__init__(time, cpu)
431 self.layer = Canvas.BOTTOM_LAYER 431 self.layer = Canvas.BOTTOM_LAYER
432 self.corresp_end_event = None 432 self.corresp_end_event = None
433 433
434 def __str__(self): 434 def __str__(self):
435 if self.corresp_end_event is None: 435 if self.corresp_end_event is None:
436 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \ 436 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \
@@ -438,19 +438,19 @@ class SwitchToEvent(Event):
438 return 'Scheduled' + self._common_str() + ', START=' \ 438 return 'Scheduled' + self._common_str() + ', START=' \
439 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ 439 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
440 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) 440 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
441 441
442 def scan(self, cur_cpu, switches): 442 def scan(self, cur_cpu, switches):
443 old_cur_cpu = cur_cpu[0] 443 old_cur_cpu = cur_cpu[0]
444 cur_cpu[0] = self.get_cpu() 444 cur_cpu[0] = self.get_cpu()
445 switches[SwitchToEvent] = self 445 switches[SwitchToEvent] = self
446 self.corresp_end_event = None 446 self.corresp_end_event = None
447 447
448 if old_cur_cpu != Event.NO_CPU: 448 if old_cur_cpu != Event.NO_CPU:
449 self.erroneous = True 449 self.erroneous = True
450 #print "currently scheduled somewhere, can't switch to a CPU" 450 #print "currently scheduled somewhere, can't switch to a CPU"
451 451
452 super(SwitchToEvent, self).scan(cur_cpu, switches) 452 super(SwitchToEvent, self).scan(cur_cpu, switches)
453 453
454 def render(self, graph, layer, prev_events, selectable=False): 454 def render(self, graph, layer, prev_events, selectable=False):
455 if layer == self.layer: 455 if layer == self.layer:
456 end_time = None 456 end_time = None
@@ -460,7 +460,7 @@ class SwitchToEvent(Event):
460 clip = AlignMode.RIGHT 460 clip = AlignMode.RIGHT
461 else: 461 else:
462 end_time = self.corresp_end_event.get_time() 462 end_time = self.corresp_end_event.get_time()
463 463
464 prev_events[self] = None 464 prev_events[self] = None
465 cpu = self.get_cpu() 465 cpu = self.get_cpu()
466 task_no = self.get_job().get_task().get_task_no() 466 task_no = self.get_job().get_task().get_task_no()
@@ -471,30 +471,30 @@ class SwitchToEvent(Event):
471 graph.draw_bar_at_time(self.get_time(), end_time, 471 graph.draw_bar_at_time(self.get_time(), end_time,
472 task_no, cpu, self.get_job().get_job_no(), 472 task_no, cpu, self.get_job().get_job_no(),
473 clip, self.is_selected()) 473 clip, self.is_selected())
474 474
475class SwitchAwayEvent(Event): 475class SwitchAwayEvent(Event):
476 def __init__(self, time, cpu): 476 def __init__(self, time, cpu):
477 super(SwitchAwayEvent, self).__init__(time, cpu) 477 super(SwitchAwayEvent, self).__init__(time, cpu)
478 self.layer = Canvas.BOTTOM_LAYER 478 self.layer = Canvas.BOTTOM_LAYER
479 self.corresp_start_event = None 479 self.corresp_start_event = None
480 480
481 def __str__(self): 481 def __str__(self):
482 if self.corresp_start_event is None: 482 if self.corresp_start_event is None:
483 return 'Switch Away (w/o Switch To)' + self._common_str() + 'TIME=' \ 483 return 'Switch Away (w/o Switch To)' + self._common_str() + 'TIME=' \
484 + str(self.get_time()) 484 + str(self.get_time())
485 return str(self.corresp_start_event) 485 return str(self.corresp_start_event)
486 486
487 def scan(self, cur_cpu, switches): 487 def scan(self, cur_cpu, switches):
488 old_cur_cpu = cur_cpu[0] 488 old_cur_cpu = cur_cpu[0]
489 489
490 self.corresp_start_event = switches[SwitchToEvent] 490 self.corresp_start_event = switches[SwitchToEvent]
491 491
492 cur_cpu[0] = Event.NO_CPU 492 cur_cpu[0] = Event.NO_CPU
493 switches[SwitchToEvent] = None 493 switches[SwitchToEvent] = None
494 494
495 if self.corresp_start_event is not None: 495 if self.corresp_start_event is not None:
496 self.corresp_start_event.corresp_end_event = self 496 self.corresp_start_event.corresp_end_event = self
497 497
498 if self.get_cpu() != old_cur_cpu: 498 if self.get_cpu() != old_cur_cpu:
499 self.erroneous = True 499 self.erroneous = True
500 #print "switching away from a CPU different from the CPU we are currently on" 500 #print "switching away from a CPU different from the CPU we are currently on"
@@ -504,9 +504,9 @@ class SwitchAwayEvent(Event):
504 elif self.get_time() < self.corresp_start_event.get_time(): 504 elif self.get_time() < self.corresp_start_event.get_time():
505 self.erroneous = True 505 self.erroneous = True
506 #print "switching away from a processor before we switched to it?!" 506 #print "switching away from a processor before we switched to it?!"
507 507
508 super(SwitchAwayEvent, self).scan(cur_cpu, switches) 508 super(SwitchAwayEvent, self).scan(cur_cpu, switches)
509 509
510 def render(self, graph, layer, prev_events, selectable=False): 510 def render(self, graph, layer, prev_events, selectable=False):
511 if self.corresp_start_event is None: 511 if self.corresp_start_event is None:
512 # We never found a corresponding start event. In that case, we can assume it lies 512 # We never found a corresponding start event. In that case, we can assume it lies
@@ -528,18 +528,18 @@ class SwitchAwayEvent(Event):
528 if self.corresp_start_event in prev_events: 528 if self.corresp_start_event in prev_events:
529 return # already rendered the bar 529 return # already rendered the bar
530 self.corresp_start_event.render(graph, layer, prev_events, selectable) 530 self.corresp_start_event.render(graph, layer, prev_events, selectable)
531 531
532class ReleaseEvent(Event): 532class ReleaseEvent(Event):
533 def __init__(self, time, cpu): 533 def __init__(self, time, cpu):
534 super(ReleaseEvent, self).__init__(time, cpu) 534 super(ReleaseEvent, self).__init__(time, cpu)
535 self.layer = Canvas.TOP_LAYER 535 self.layer = Canvas.TOP_LAYER
536 536
537 def __str__(self): 537 def __str__(self):
538 return 'Release' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 538 return 'Release' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
539 539
540 def scan(self, cur_cpu, switches): 540 def scan(self, cur_cpu, switches):
541 super(ReleaseEvent, self).scan(cur_cpu, switches) 541 super(ReleaseEvent, self).scan(cur_cpu, switches)
542 542
543 def render(self, graph, layer, prev_events, selectable=False): 543 def render(self, graph, layer, prev_events, selectable=False):
544 prev_events[self] = None 544 prev_events[self] = None
545 if layer == Canvas.TOP_LAYER: 545 if layer == Canvas.TOP_LAYER:
@@ -549,19 +549,19 @@ class ReleaseEvent(Event):
549 else: 549 else:
550 graph.draw_release_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 550 graph.draw_release_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
551 self.get_job().get_job_no(), self.is_selected()) 551 self.get_job().get_job_no(), self.is_selected())
552 552
553 553
554class DeadlineEvent(Event): 554class DeadlineEvent(Event):
555 def __init__(self, time, cpu): 555 def __init__(self, time, cpu):
556 super(DeadlineEvent, self).__init__(time, cpu) 556 super(DeadlineEvent, self).__init__(time, cpu)
557 self.layer = Canvas.TOP_LAYER 557 self.layer = Canvas.TOP_LAYER
558 558
559 def __str__(self): 559 def __str__(self):
560 return 'Deadline' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 560 return 'Deadline' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
561 561
562 def scan(self, cur_cpu, switches): 562 def scan(self, cur_cpu, switches):
563 super(DeadlineEvent, self).scan(cur_cpu, switches) 563 super(DeadlineEvent, self).scan(cur_cpu, switches)
564 564
565 def render(self, graph, layer, prev_events, selectable=False): 565 def render(self, graph, layer, prev_events, selectable=False):
566 prev_events[self] = None 566 prev_events[self] = None
567 if layer == Canvas.TOP_LAYER: 567 if layer == Canvas.TOP_LAYER:
@@ -571,14 +571,14 @@ class DeadlineEvent(Event):
571 else: 571 else:
572 graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 572 graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
573 self.get_job().get_job_no(), self.is_selected()) 573 self.get_job().get_job_no(), self.is_selected())
574 574
575 575
576class InversionStartEvent(ErrorEvent): 576class InversionStartEvent(ErrorEvent):
577 def __init__(self, time): 577 def __init__(self, time):
578 super(InversionStartEvent, self).__init__(time, Event.NO_CPU) 578 super(InversionStartEvent, self).__init__(time, Event.NO_CPU)
579 self.layer = Canvas.BOTTOM_LAYER 579 self.layer = Canvas.BOTTOM_LAYER
580 self.corresp_end_event = None 580 self.corresp_end_event = None
581 581
582 def __str__(self): 582 def __str__(self):
583 if self.corresp_end_event is None: 583 if self.corresp_end_event is None:
584 return 'Inversion Start (w/o Inversion End)' + self._common_str() \ 584 return 'Inversion Start (w/o Inversion End)' + self._common_str() \
@@ -586,14 +586,14 @@ class InversionStartEvent(ErrorEvent):
586 return 'Priority Inversion' + self._common_str() + ', START=' \ 586 return 'Priority Inversion' + self._common_str() + ', START=' \
587 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ 587 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
588 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) 588 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
589 589
590 def scan(self, cur_cpu, switches): 590 def scan(self, cur_cpu, switches):
591 switches[InversionStartEvent] = self 591 switches[InversionStartEvent] = self
592 self.corresp_end_event = None 592 self.corresp_end_event = None
593 593
594 # the corresp_end_event should already be set 594 # the corresp_end_event should already be set
595 super(InversionStartEvent, self).scan(cur_cpu, switches) 595 super(InversionStartEvent, self).scan(cur_cpu, switches)
596 596
597 def render(self, graph, layer, prev_events, selectable=False): 597 def render(self, graph, layer, prev_events, selectable=False):
598 if layer == self.layer: 598 if layer == self.layer:
599 end_time = None 599 end_time = None
@@ -603,7 +603,7 @@ class InversionStartEvent(ErrorEvent):
603 clip = AlignMode.RIGHT 603 clip = AlignMode.RIGHT
604 else: 604 else:
605 end_time = self.corresp_end_event.get_time() 605 end_time = self.corresp_end_event.get_time()
606 606
607 if layer == self.layer: 607 if layer == self.layer:
608 prev_events[self] = None 608 prev_events[self] = None
609 cpu = self.get_cpu() 609 cpu = self.get_cpu()
@@ -615,36 +615,36 @@ class InversionStartEvent(ErrorEvent):
615 graph.draw_mini_bar_at_time(self.get_time(), end_time, 615 graph.draw_mini_bar_at_time(self.get_time(), end_time,
616 task_no, cpu, self.get_job().get_job_no(), 616 task_no, cpu, self.get_job().get_job_no(),
617 clip, self.is_selected()) 617 clip, self.is_selected())
618 618
619 619
620class InversionEndEvent(ErrorEvent): 620class InversionEndEvent(ErrorEvent):
621 def __init__(self, time): 621 def __init__(self, time):
622 super(InversionEndEvent, self).__init__(time, Event.NO_CPU) 622 super(InversionEndEvent, self).__init__(time, Event.NO_CPU)
623 self.layer = Canvas.BOTTOM_LAYER 623 self.layer = Canvas.BOTTOM_LAYER
624 self.corresp_start_event = None 624 self.corresp_start_event = None
625 625
626 def __str__(self): 626 def __str__(self):
627 if self.corresp_start_event is None: 627 if self.corresp_start_event is None:
628 return 'Inversion End (w/o Inversion Start)' + self._common_str() \ 628 return 'Inversion End (w/o Inversion Start)' + self._common_str() \
629 + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 629 + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
630 630
631 return str(self.corresp_start_event) 631 return str(self.corresp_start_event)
632 632
633 def scan(self, cur_cpu, switches): 633 def scan(self, cur_cpu, switches):
634 self.corresp_start_event = switches[InversionStartEvent] 634 self.corresp_start_event = switches[InversionStartEvent]
635 635
636 cur_cpu[0] = Event.NO_CPU 636 cur_cpu[0] = Event.NO_CPU
637 switches[InversionStartEvent] = None 637 switches[InversionStartEvent] = None
638 638
639 if self.corresp_start_event is not None: 639 if self.corresp_start_event is not None:
640 self.corresp_start_event.corresp_end_event = self 640 self.corresp_start_event.corresp_end_event = self
641 641
642 if self.corresp_start_event is None: 642 if self.corresp_start_event is None:
643 self.erroneous = True 643 self.erroneous = True
644 print "inversion end was not matched by a corresponding inversion start" 644 print "inversion end was not matched by a corresponding inversion start"
645 645
646 super(InversionEndEvent, self).scan(cur_cpu, switches) 646 super(InversionEndEvent, self).scan(cur_cpu, switches)
647 647
648 def render(self, graph, layer, prev_events, selectable=False): 648 def render(self, graph, layer, prev_events, selectable=False):
649 if self.corresp_start_event is None: 649 if self.corresp_start_event is None:
650 # We never found a corresponding start event. In that case, we can assume it lies 650 # We never found a corresponding start event. In that case, we can assume it lies
@@ -666,27 +666,27 @@ class InversionEndEvent(ErrorEvent):
666 if self.corresp_start_event in prev_events: 666 if self.corresp_start_event in prev_events:
667 return # already rendered the bar 667 return # already rendered the bar
668 self.corresp_start_event.render(graph, layer, prev_events, selectable) 668 self.corresp_start_event.render(graph, layer, prev_events, selectable)
669 669
670class InversionDummy(DummyEvent): 670class InversionDummy(DummyEvent):
671 def __init__(self, time, cpu): 671 def __init__(self, time, cpu):
672 super(InversionDummy, self).__init__(time, Event.NO_CPU) 672 super(InversionDummy, self).__init__(time, Event.NO_CPU)
673 self.layer = Canvas.BOTTOM_LAYER 673 self.layer = Canvas.BOTTOM_LAYER
674 674
675 def render(self, graph, layer, prev_events, selectable=False): 675 def render(self, graph, layer, prev_events, selectable=False):
676 if self.corresp_start_event is None: 676 if self.corresp_start_event is None:
677 if self.corresp_end_event in prev_events: 677 if self.corresp_end_event in prev_events:
678 return # we have already been rendered 678 return # we have already been rendered
679 self.corresp_end_event.render(graph, layer, prev_events, selectable) 679 self.corresp_end_event.render(graph, layer, prev_events, selectable)
680 else: 680 else:
681 if self.corresp_start_event in prev_events: 681 if self.corresp_start_event in prev_events:
682 return # we have already been rendered 682 return # we have already been rendered
683 self.corresp_start_event.render(graph, layer, prev_events, selectable) 683 self.corresp_start_event.render(graph, layer, prev_events, selectable)
684 684
685class IsRunningDummy(DummyEvent): 685class IsRunningDummy(DummyEvent):
686 def __init__(self, time, cpu): 686 def __init__(self, time, cpu):
687 super(IsRunningDummy, self).__init__(time, Event.NO_CPU) 687 super(IsRunningDummy, self).__init__(time, Event.NO_CPU)
688 self.layer = Canvas.BOTTOM_LAYER 688 self.layer = Canvas.BOTTOM_LAYER
689 689
690 def render(self, graph, layer, prev_events, selectable=False): 690 def render(self, graph, layer, prev_events, selectable=False):
691 if self.corresp_start_event is None: 691 if self.corresp_start_event is None:
692 if self.corresp_end_event in prev_events: 692 if self.corresp_end_event in prev_events: