summaryrefslogtreecommitdiffstats
path: root/unit_trace/viz/schedule.py
diff options
context:
space:
mode:
authorGary Bressler <garybressler@nc.rr.com>2010-04-08 17:11:08 -0400
committerGary Bressler <garybressler@nc.rr.com>2010-04-08 17:11:08 -0400
commitceff6457bfeb5642616f4711f14e0bb652d12164 (patch)
treed05b4ebd1c3ee6e28884c669d65fd31700941086 /unit_trace/viz/schedule.py
parent01abc8352aa2fd192678b4066b26ea749a203801 (diff)
Updated the documentation to describe the visualizer, made unit-trace itself not require gtk/cairo, and a few other minor things.
Diffstat (limited to 'unit_trace/viz/schedule.py')
-rw-r--r--unit_trace/viz/schedule.py366
1 files changed, 217 insertions, 149 deletions
diff --git a/unit_trace/viz/schedule.py b/unit_trace/viz/schedule.py
index 81269fa..a44ce8d 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,18 +86,18 @@ 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 get_events(self, slots, list_type, event_types): 101 def get_events(self, slots, list_type, event_types):
102 for type in event_types: 102 for type in event_types:
103 for slot in slots: 103 for slot in slots:
@@ -105,31 +105,31 @@ class TimeSlotArray(object):
105 if slot in self.array[list_type][no][type]: 105 if slot in self.array[list_type][no][type]:
106 for event in self.array[list_type][no][type][slot]: 106 for event in self.array[list_type][no][type][slot]:
107 yield event 107 yield event
108 108
109 def get_slots(self, slots, start, end, start_no, end_no, list_type): 109 def get_slots(self, slots, start, end, start_no, end_no, list_type):
110 if self.array is None: 110 if self.array is None:
111 return # empty schedule 111 return # empty schedule
112 112
113 if start > end: 113 if start > end:
114 raise ValueError('Litmus is not a time machine') 114 raise ValueError('Litmus is not a time machine')
115 if start_no > end_no: 115 if start_no > end_no:
116 raise ValueError('start no should be less than end no') 116 raise ValueError('start no should be less than end no')
117 117
118 start_slot = self.get_time_slot(start) 118 start_slot = self.get_time_slot(start)
119 end_slot = self.get_time_slot(end) + 1 119 end_slot = self.get_time_slot(end) + 1
120 start_no = max(0, start_no) 120 start_no = max(0, start_no)
121 end_no = min(self.list_sizes[list_type] - 1, end_no) 121 end_no = min(self.list_sizes[list_type] - 1, end_no)
122 122
123 for slot in xrange(start_slot, end_slot + 1): 123 for slot in xrange(start_slot, end_slot + 1):
124 if slot not in slots: 124 if slot not in slots:
125 slots[slot] = {} 125 slots[slot] = {}
126 for no in xrange(start_no, end_no + 1): 126 for no in xrange(start_no, end_no + 1):
127 slots[slot][no] = None 127 slots[slot][no] = None
128 128
129class Schedule(object): 129class Schedule(object):
130 """The total schedule (task system), consisting of a certain number of 130 """The total schedule (task system), consisting of a certain number of
131 tasks.""" 131 tasks."""
132 132
133 def __init__(self, name, num_cpus, task_list=[]): 133 def __init__(self, name, num_cpus, task_list=[]):
134 self.name = name 134 self.name = name
135 self.tasks = {} 135 self.tasks = {}
@@ -140,13 +140,13 @@ class Schedule(object):
140 self.num_cpus = num_cpus 140 self.num_cpus = num_cpus
141 for task in task_list: 141 for task in task_list:
142 self.add_task(task) 142 self.add_task(task)
143 143
144 def get_selected(self): 144 def get_selected(self):
145 return self.selected 145 return self.selected
146 146
147 def set_selected(self, selected): 147 def set_selected(self, selected):
148 self.selected = selected 148 self.selected = selected
149 149
150 def add_selected(self, selected): 150 def add_selected(self, selected):
151 for layer in selected: 151 for layer in selected:
152 if layer not in self.selected: 152 if layer not in self.selected:
@@ -156,35 +156,35 @@ class Schedule(object):
156 self.selected[layer][event] = {} 156 self.selected[layer][event] = {}
157 for graph in selected[layer][event]: 157 for graph in selected[layer][event]:
158 self.selected[layer][event][graph] = selected[layer][event][graph] 158 self.selected[layer][event][graph] = selected[layer][event][graph]
159 159
160 def remove_selected(self, selected): 160 def remove_selected(self, selected):
161 for layer in selected: 161 for layer in selected:
162 if layer in self.selected: 162 if layer in self.selected:
163 for event in selected[layer]: 163 for event in selected[layer]:
164 if event in self.selected[layer]: 164 if event in self.selected[layer]:
165 del self.selected[layer][event] 165 del self.selected[layer][event]
166 166
167 def set_time_params(self, time_per_maj=None): 167 def set_time_params(self, time_per_maj=None):
168 self.time_per_maj = time_per_maj 168 self.time_per_maj = time_per_maj
169 if self.time_per_maj is None: 169 if self.time_per_maj is None:
170 self.time_slot_array = TimeSlotArray() 170 self.time_slot_array = TimeSlotArray()
171 return 171 return
172 172
173 self.time_slot_array = TimeSlotArray(self.time_per_maj, \ 173 self.time_slot_array = TimeSlotArray(self.time_per_maj, \
174 len(self.task_list), self.num_cpus) 174 len(self.task_list), self.num_cpus)
175 175
176 def get_time_slot_array(self): 176 def get_time_slot_array(self):
177 return self.time_slot_array 177 return self.time_slot_array
178 178
179 def get_time_bounds(self): 179 def get_time_bounds(self):
180 return (self.start, self.end) 180 return (self.start, self.end)
181 181
182 def scan(self, time_per_maj): 182 def scan(self, time_per_maj):
183 self.start = None 183 self.start = None
184 self.end = None 184 self.end = None
185 185
186 self.set_time_params(time_per_maj) 186 self.set_time_params(time_per_maj)
187 187
188 # we scan the graph task by task, and job by job 188 # we scan the graph task by task, and job by job
189 for task_no, task in enumerate(self.get_task_list()): 189 for task_no, task in enumerate(self.get_task_list()):
190 switches = {} 190 switches = {}
@@ -192,12 +192,12 @@ class Schedule(object):
192 switches[event] = None 192 switches[event] = None
193 cur_cpu = [Event.NO_CPU] 193 cur_cpu = [Event.NO_CPU]
194 for job_no in sorted(task.get_jobs().keys()): 194 for job_no in sorted(task.get_jobs().keys()):
195 job = task.get_jobs()[job_no] 195 job = task.get_jobs()[job_no]
196 for event_time in sorted(job.get_events().keys()): 196 for event_time in sorted(job.get_events().keys()):
197 # could have multiple events at the same time (unlikely but possible) 197 # could have multiple events at the same time (unlikely but possible)
198 for event in job.get_events()[event_time]: 198 for event in job.get_events()[event_time]:
199 event.scan(cur_cpu, switches) 199 event.scan(cur_cpu, switches)
200 200
201 # What if one of the initial "span events" (switch to or inversion starting) never got a 201 # What if one of the initial "span events" (switch to or inversion starting) never got a
202 # corresponding end event? Well, then we assume that the end event was simply outside of 202 # corresponding end event? Well, then we assume that the end event was simply outside of
203 # the range of whatever we read in. So we need to fill dummies starting from the initial 203 # the range of whatever we read in. So we need to fill dummies starting from the initial
@@ -207,7 +207,7 @@ class Schedule(object):
207 event = switches[span_event] 207 event = switches[span_event]
208 if event is not None: 208 if event is not None:
209 self.time_slot_array.fill_span_event_from_start(event) 209 self.time_slot_array.fill_span_event_from_start(event)
210 210
211 def add_task(self, task): 211 def add_task(self, task):
212 if task.name in self.tasks: 212 if task.name in self.tasks:
213 raise ValueError("task already in list!") 213 raise ValueError("task already in list!")
@@ -216,29 +216,29 @@ class Schedule(object):
216 task.schedule = self 216 task.schedule = self
217 task.task_no = self.cur_task_no 217 task.task_no = self.cur_task_no
218 self.cur_task_no += 1 218 self.cur_task_no += 1
219 219
220 def get_tasks(self): 220 def get_tasks(self):
221 return self.tasks 221 return self.tasks
222 222
223 def get_task_list(self): 223 def get_task_list(self):
224 return self.task_list 224 return self.task_list
225 225
226 def get_name(self): 226 def get_name(self):
227 return self.name 227 return self.name
228 228
229 def get_num_cpus(self): 229 def get_num_cpus(self):
230 return self.num_cpus 230 return self.num_cpus
231 231
232def deepcopy_selected(selected): 232def deepcopy_selected(selected):
233 selected_copy = {} 233 selected_copy = {}
234 for layer in selected: 234 for layer in selected:
235 selected_copy[layer] = copy.copy(selected[layer]) 235 selected_copy[layer] = copy.copy(selected[layer])
236 return selected_copy 236 return selected_copy
237 237
238class Task(object): 238class Task(object):
239 """Represents a task, including the set of jobs that were run under 239 """Represents a task, including the set of jobs that were run under
240 this task.""" 240 this task."""
241 241
242 def __init__(self, name, job_list=[]): 242 def __init__(self, name, job_list=[]):
243 self.name = name 243 self.name = name
244 self.jobs = {} 244 self.jobs = {}
@@ -246,25 +246,25 @@ class Task(object):
246 self.schedule = None 246 self.schedule = None
247 for job in job_list: 247 for job in job_list:
248 self.add_job(job) 248 self.add_job(job)
249 249
250 def add_job(self, job): 250 def add_job(self, job):
251 if job.job_no in self.jobs: 251 if job.job_no in self.jobs:
252 raise ScheduleError("a job is already being released at this time for this task") 252 raise ScheduleError("a job is already being released at this time for this task")
253 self.jobs[job.job_no] = job 253 self.jobs[job.job_no] = job
254 job.task = self 254 job.task = self
255 255
256 def get_schedule(self): 256 def get_schedule(self):
257 return self.schedule 257 return self.schedule
258 258
259 def get_jobs(self): 259 def get_jobs(self):
260 return self.jobs 260 return self.jobs
261 261
262 def get_task_no(self): 262 def get_task_no(self):
263 return self.task_no 263 return self.task_no
264 264
265 def get_name(self): 265 def get_name(self):
266 return self.name 266 return self.name
267 267
268class Job(object): 268class Job(object):
269 """Represents a job, including everything that happens related to the job""" 269 """Represents a job, including everything that happens related to the job"""
270 def __init__(self, job_no, event_list=[]): 270 def __init__(self, job_no, event_list=[]):
@@ -273,19 +273,19 @@ class Job(object):
273 self.task = None 273 self.task = None
274 for event in event_list: 274 for event in event_list:
275 self.add_event(event) 275 self.add_event(event)
276 276
277 def add_event(self, event): 277 def add_event(self, event):
278 if event.time not in self.events: 278 if event.time not in self.events:
279 self.events[event.time] = [] 279 self.events[event.time] = []
280 self.events[event.time].append(event) 280 self.events[event.time].append(event)
281 event.job = self 281 event.job = self
282 282
283 def get_events(self): 283 def get_events(self):
284 return self.events 284 return self.events
285 285
286 def get_task(self): 286 def get_task(self):
287 return self.task 287 return self.task
288 288
289 def get_job_no(self): 289 def get_job_no(self):
290 return self.job_no 290 return self.job_no
291 291
@@ -301,61 +301,73 @@ class DummyEvent(object):
301 self.cpu = cpu 301 self.cpu = cpu
302 self.job = None 302 self.job = None
303 self.layer = None 303 self.layer = None
304 304
305 def __str__(self): 305 def __str__(self):
306 return '[Dummy Event]' 306 return '[Dummy Event]'
307 307
308 def get_time(self): 308 def get_time(self):
309 return self.time 309 return self.time
310 310
311 def get_cpu(self): 311 def get_cpu(self):
312 return self.cpu 312 return self.cpu
313 313
314 def get_job(self): 314 def get_job(self):
315 return self.job 315 return self.job
316 316
317 def get_layer(self): 317 def get_layer(self):
318 return self.layer 318 return self.layer
319 319
320 def render(self, graph, layer, prev_events, selectable=False): 320 def render(self, graph, layer, prev_events, selectable=False):
321 """Method that the visualizer calls to tell the event to render itself 321 """Method that the visualizer calls to tell the event to render itself
322 Obviously only implemented by subclasses (actual event types) 322 Obviously only implemented by subclasses (actual event types)
323 323
324 ``Rendering'' can mean either actually drawing the event or just 324 ``Rendering'' can mean either actually drawing the event or just
325 adding it as a selectable region. This is controlled by the 325 adding it as a selectable region. This is controlled by the
326 ``selectable'' parameter""" 326 ``selectable'' parameter"""
327 raise NotImplementdError 327 raise NotImplementdError
328 328
329class Event(DummyEvent): 329class Event(DummyEvent):
330 """Represents an event that occurs while a job is running (e.g. get scheduled 330 """Represents an event that occurs while a job is running (e.g. get scheduled
331 on a CPU, block, ...)""" 331 on a CPU, block, ...)"""
332 NO_CPU = -1 332 NO_CPU = -1
333 NUM_DEC_PLACES = 2 333 NUM_DEC_PLACES = 2
334 334
335 def __init__(self, time, cpu): 335 def __init__(self, time, cpu):
336 super(Event, self).__init__(time, cpu) 336 super(Event, self).__init__(time, cpu)
337 self.erroneous = False 337 self.erroneous = False
338 338
339 def get_name(self):
340 raise NotImplementedError
341
339 def __str__(self): 342 def __str__(self):
340 return '[Event]' 343 return self.get_name() + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES)
341 344
345 def str_long(self):
346 """Prints the event as a string, in ``long'' form."""
347 return 'Event Type: ' + self.get_name() + \
348 '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \
349 '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \
350 self.get_job().get_job_no())) + \
351 '\nCPU: ' + str(self.get_cpu()) + \
352 '\nTime: ' + str(self.get_time())
353
342 def _common_str(self): 354 def _common_str(self):
343 job = self.get_job() 355 job = self.get_job()
344 task = job.get_task() 356 task = job.get_task()
345 return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \ 357 return ' for task ' + str(task.get_name()) + ': (TASK, JOB)=' + str((task.get_task_no(), \
346 job.get_job_no())) + ', CPU=' + str(self.get_cpu()) 358 job.get_job_no())) + ', CPU=' + str(self.get_cpu())
347 359
348 def is_erroneous(self): 360 def is_erroneous(self):
349 """An erroneous event is where something with the event is not quite right, 361 """An erroneous event is where something with the event is not quite right,
350 something significantly wrong that we don't have logical information telling 362 something significantly wrong that we don't have logical information telling
351 us how we should render the event.""" 363 us how we should render the event."""
352 return self.erroneous 364 return self.erroneous
353 365
354 def is_selected(self): 366 def is_selected(self):
355 """Returns whether the event has been selected by the user. (needed for rendering)""" 367 """Returns whether the event has been selected by the user. (needed for rendering)"""
356 selected = self.get_job().get_task().get_schedule().get_selected() 368 selected = self.get_job().get_task().get_schedule().get_selected()
357 return self.get_layer() in selected and self in selected[self.get_layer()] 369 return self.get_layer() in selected and self in selected[self.get_layer()]
358 370
359 def scan(self, cur_cpu, switches): 371 def scan(self, cur_cpu, switches):
360 """Part of the procedure that walks through all the events and sets 372 """Part of the procedure that walks through all the events and sets
361 some parameters that are unknown at first. For instance, a SwitchAwayEvent 373 some parameters that are unknown at first. For instance, a SwitchAwayEvent
@@ -370,26 +382,26 @@ class Event(DummyEvent):
370 sched.start = time 382 sched.start = time
371 if sched.end is None or time > sched.end: 383 if sched.end is None or time > sched.end:
372 sched.end = time 384 sched.end = time
373 385
374 sched.get_time_slot_array().add_event_to_time_slot(self) 386 sched.get_time_slot_array().add_event_to_time_slot(self)
375 387
376class ErrorEvent(Event): 388class ErrorEvent(Event):
377 pass 389 pass
378 390
379class SuspendEvent(Event): 391class SuspendEvent(Event):
380 def __init__(self, time, cpu): 392 def __init__(self, time, cpu):
381 super(SuspendEvent, self).__init__(time, cpu) 393 super(SuspendEvent, self).__init__(time, cpu)
382 self.layer = Canvas.MIDDLE_LAYER 394 self.layer = Canvas.MIDDLE_LAYER
383 395
384 def __str__(self): 396 def get_name(self):
385 return 'Suspend' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 397 return 'Suspend'
386 398
387 def scan(self, cur_cpu, switches): 399 def scan(self, cur_cpu, switches):
388 if self.get_cpu() != cur_cpu[0]: 400 if self.get_cpu() != cur_cpu[0]:
389 self.erroneous = True 401 self.erroneous = True
390 #fprint "suspending on a CPU different from the CPU we are on!" 402 #fprint "suspending on a CPU different from the CPU we are on!"
391 super(SuspendEvent, self).scan(cur_cpu, switches) 403 super(SuspendEvent, self).scan(cur_cpu, switches)
392 404
393 def render(self, graph, layer, prev_events, selectable=False): 405 def render(self, graph, layer, prev_events, selectable=False):
394 if layer == self.layer: 406 if layer == self.layer:
395 prev_events[self] = None 407 prev_events[self] = None
@@ -399,22 +411,22 @@ class SuspendEvent(Event):
399 else: 411 else:
400 graph.draw_suspend_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 412 graph.draw_suspend_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
401 self.get_cpu(), self.is_selected()) 413 self.get_cpu(), self.is_selected())
402 414
403 415
404class ResumeEvent(Event): 416class ResumeEvent(Event):
405 def __init__(self, time, cpu): 417 def __init__(self, time, cpu):
406 super(ResumeEvent, self).__init__(time, cpu) 418 super(ResumeEvent, self).__init__(time, cpu)
407 self.layer = Canvas.MIDDLE_LAYER 419 self.layer = Canvas.MIDDLE_LAYER
408 420
409 def __str__(self): 421 def get_name(self):
410 return 'Resume' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 422 return 'Resume'
411 423
412 def scan(self, cur_cpu, switches): 424 def scan(self, cur_cpu, switches):
413 if cur_cpu[0] != Event.NO_CPU and cur_cpu[0] != self.get_cpu(): 425 if cur_cpu[0] != Event.NO_CPU and cur_cpu[0] != self.get_cpu():
414 self.erroneous = True 426 self.erroneous = True
415 #print "Resuming when currently scheduled on a CPU, but on a different CPU from the current CPU!" 427 #print "Resuming when currently scheduled on a CPU, but on a different CPU from the current CPU!"
416 super(ResumeEvent, self).scan(cur_cpu, switches) 428 super(ResumeEvent, self).scan(cur_cpu, switches)
417 429
418 def render(self, graph, layer, prev_events, selectable=False): 430 def render(self, graph, layer, prev_events, selectable=False):
419 if layer == self.layer: 431 if layer == self.layer:
420 prev_events[self] = None 432 prev_events[self] = None
@@ -424,19 +436,19 @@ class ResumeEvent(Event):
424 else: 436 else:
425 graph.draw_resume_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 437 graph.draw_resume_triangle_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
426 self.get_cpu(), self.is_selected()) 438 self.get_cpu(), self.is_selected())
427 439
428 440
429class CompleteEvent(Event): 441class CompleteEvent(Event):
430 def __init__(self, time, cpu): 442 def __init__(self, time, cpu):
431 super(CompleteEvent, self).__init__(time, cpu) 443 super(CompleteEvent, self).__init__(time, cpu)
432 self.layer = Canvas.TOP_LAYER 444 self.layer = Canvas.TOP_LAYER
433 445
434 def __str__(self): 446 def get_name(self):
435 return 'Complete' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 447 return 'Complete'
436 448
437 def scan(self, cur_cpu, switches): 449 def scan(self, cur_cpu, switches):
438 super(CompleteEvent, self).scan(cur_cpu, switches) 450 super(CompleteEvent, self).scan(cur_cpu, switches)
439 451
440 def render(self, graph, layer, prev_events, selectable=False): 452 def render(self, graph, layer, prev_events, selectable=False):
441 if layer == Canvas.TOP_LAYER: 453 if layer == Canvas.TOP_LAYER:
442 prev_events[self] = None 454 prev_events[self] = None
@@ -452,27 +464,44 @@ class SwitchToEvent(Event):
452 super(SwitchToEvent, self).__init__(time, cpu) 464 super(SwitchToEvent, self).__init__(time, cpu)
453 self.layer = Canvas.BOTTOM_LAYER 465 self.layer = Canvas.BOTTOM_LAYER
454 self.corresp_end_event = None 466 self.corresp_end_event = None
455 467
468 def get_name(self):
469 if self.corresp_end_event is None:
470 return 'Switch To (w/o Switch Away)'
471 else:
472 return 'Scheduled'
473
456 def __str__(self): 474 def __str__(self):
457 if self.corresp_end_event is None: 475 if self.corresp_end_event is None:
458 return 'Switch To (w/o Switch Away)' + self._common_str() + ', TIME=' \ 476 return super(SwitchToEvent, self).__str__()
459 + str(self.get_time()) 477 return self.get_name() + self._common_str() + ', START=' \
460 return 'Scheduled' + self._common_str() + ', START=' \
461 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ 478 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
462 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) 479 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
463 480
481 def str_long(self):
482 if self.corresp_end_event is None:
483 return super(SwitchToEvent, self).str_long()
484 else :
485 return 'Event Type: ' + self.get_name() + \
486 '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \
487 '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \
488 self.get_job().get_job_no())) + \
489 '\nCPU: ' + str(self.get_cpu()) + \
490 '\nStart: ' + str(self.get_time()) + \
491 '\nEnd: ' + str(self.corresp_end_event.get_time())
492
464 def scan(self, cur_cpu, switches): 493 def scan(self, cur_cpu, switches):
465 old_cur_cpu = cur_cpu[0] 494 old_cur_cpu = cur_cpu[0]
466 cur_cpu[0] = self.get_cpu() 495 cur_cpu[0] = self.get_cpu()
467 switches[SwitchToEvent] = self 496 switches[SwitchToEvent] = self
468 self.corresp_end_event = None 497 self.corresp_end_event = None
469 498
470 if old_cur_cpu != Event.NO_CPU: 499 if old_cur_cpu != Event.NO_CPU:
471 self.erroneous = True 500 self.erroneous = True
472 #print "currently scheduled somewhere, can't switch to a CPU" 501 #print "currently scheduled somewhere, can't switch to a CPU"
473 502
474 super(SwitchToEvent, self).scan(cur_cpu, switches) 503 super(SwitchToEvent, self).scan(cur_cpu, switches)
475 504
476 def render(self, graph, layer, prev_events, selectable=False): 505 def render(self, graph, layer, prev_events, selectable=False):
477 if layer == self.layer: 506 if layer == self.layer:
478 end_time = None 507 end_time = None
@@ -482,7 +511,7 @@ class SwitchToEvent(Event):
482 clip = AlignMode.RIGHT 511 clip = AlignMode.RIGHT
483 else: 512 else:
484 end_time = self.corresp_end_event.get_time() 513 end_time = self.corresp_end_event.get_time()
485 514
486 prev_events[self] = None 515 prev_events[self] = None
487 cpu = self.get_cpu() 516 cpu = self.get_cpu()
488 task_no = self.get_job().get_task().get_task_no() 517 task_no = self.get_job().get_task().get_task_no()
@@ -493,30 +522,41 @@ class SwitchToEvent(Event):
493 graph.draw_bar_at_time(self.get_time(), end_time, 522 graph.draw_bar_at_time(self.get_time(), end_time,
494 task_no, cpu, self.get_job().get_job_no(), 523 task_no, cpu, self.get_job().get_job_no(),
495 clip, self.is_selected()) 524 clip, self.is_selected())
496 525
497class SwitchAwayEvent(Event): 526class SwitchAwayEvent(Event):
498 def __init__(self, time, cpu): 527 def __init__(self, time, cpu):
499 super(SwitchAwayEvent, self).__init__(time, cpu) 528 super(SwitchAwayEvent, self).__init__(time, cpu)
500 self.layer = Canvas.BOTTOM_LAYER 529 self.layer = Canvas.BOTTOM_LAYER
501 self.corresp_start_event = None 530 self.corresp_start_event = None
502 531
532 def get_name(self):
533 if self.corresp_start_event is None:
534 return 'Switch Away (w/o Switch To)'
535 else:
536 return 'Scheduled'
537
503 def __str__(self): 538 def __str__(self):
504 if self.corresp_start_event is None: 539 if self.corresp_start_event is None:
505 return 'Switch Away (w/o Switch To)' + self._common_str() + ', TIME=' \ 540 return super(SwitchAwayEvent, self).__str__()
506 + str(self.get_time())
507 return str(self.corresp_start_event) 541 return str(self.corresp_start_event)
508 542
543 def str_long(self):
544 if self.corresp_start_event is None:
545 return super(SwitchAwayEvent, self).str_long()
546
547 return self.corresp_start_event.str_long()
548
509 def scan(self, cur_cpu, switches): 549 def scan(self, cur_cpu, switches):
510 old_cur_cpu = cur_cpu[0] 550 old_cur_cpu = cur_cpu[0]
511 551
512 self.corresp_start_event = switches[SwitchToEvent] 552 self.corresp_start_event = switches[SwitchToEvent]
513 553
514 cur_cpu[0] = Event.NO_CPU 554 cur_cpu[0] = Event.NO_CPU
515 switches[SwitchToEvent] = None 555 switches[SwitchToEvent] = None
516 556
517 if self.corresp_start_event is not None: 557 if self.corresp_start_event is not None:
518 self.corresp_start_event.corresp_end_event = self 558 self.corresp_start_event.corresp_end_event = self
519 559
520 if self.get_cpu() != old_cur_cpu: 560 if self.get_cpu() != old_cur_cpu:
521 self.erroneous = True 561 self.erroneous = True
522 #print "switching away from a CPU different from the CPU we are currently on" 562 #print "switching away from a CPU different from the CPU we are currently on"
@@ -526,9 +566,9 @@ class SwitchAwayEvent(Event):
526 elif self.get_time() < self.corresp_start_event.get_time(): 566 elif self.get_time() < self.corresp_start_event.get_time():
527 self.erroneous = True 567 self.erroneous = True
528 #print "switching away from a processor before we switched to it?!" 568 #print "switching away from a processor before we switched to it?!"
529 569
530 super(SwitchAwayEvent, self).scan(cur_cpu, switches) 570 super(SwitchAwayEvent, self).scan(cur_cpu, switches)
531 571
532 def render(self, graph, layer, prev_events, selectable=False): 572 def render(self, graph, layer, prev_events, selectable=False):
533 if self.corresp_start_event is None: 573 if self.corresp_start_event is None:
534 # We never found a corresponding start event. In that case, we can assume it lies 574 # We never found a corresponding start event. In that case, we can assume it lies
@@ -550,18 +590,18 @@ class SwitchAwayEvent(Event):
550 if self.corresp_start_event in prev_events: 590 if self.corresp_start_event in prev_events:
551 return # already rendered the bar 591 return # already rendered the bar
552 self.corresp_start_event.render(graph, layer, prev_events, selectable) 592 self.corresp_start_event.render(graph, layer, prev_events, selectable)
553 593
554class ReleaseEvent(Event): 594class ReleaseEvent(Event):
555 def __init__(self, time, cpu): 595 def __init__(self, time, cpu):
556 super(ReleaseEvent, self).__init__(time, cpu) 596 super(ReleaseEvent, self).__init__(time, cpu)
557 self.layer = Canvas.TOP_LAYER 597 self.layer = Canvas.TOP_LAYER
558 598
559 def __str__(self): 599 def get_name(self):
560 return 'Release' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 600 return 'Release'
561 601
562 def scan(self, cur_cpu, switches): 602 def scan(self, cur_cpu, switches):
563 super(ReleaseEvent, self).scan(cur_cpu, switches) 603 super(ReleaseEvent, self).scan(cur_cpu, switches)
564 604
565 def render(self, graph, layer, prev_events, selectable=False): 605 def render(self, graph, layer, prev_events, selectable=False):
566 prev_events[self] = None 606 prev_events[self] = None
567 if layer == Canvas.TOP_LAYER: 607 if layer == Canvas.TOP_LAYER:
@@ -571,19 +611,19 @@ class ReleaseEvent(Event):
571 else: 611 else:
572 graph.draw_release_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 612 graph.draw_release_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
573 self.get_job().get_job_no(), self.is_selected()) 613 self.get_job().get_job_no(), self.is_selected())
574 614
575 615
576class DeadlineEvent(Event): 616class DeadlineEvent(Event):
577 def __init__(self, time, cpu): 617 def __init__(self, time, cpu):
578 super(DeadlineEvent, self).__init__(time, cpu) 618 super(DeadlineEvent, self).__init__(time, cpu)
579 self.layer = Canvas.TOP_LAYER 619 self.layer = Canvas.TOP_LAYER
580 620
581 def __str__(self): 621 def get_name(self):
582 return 'Deadline' + self._common_str() + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 622 return 'Deadline'
583 623
584 def scan(self, cur_cpu, switches): 624 def scan(self, cur_cpu, switches):
585 super(DeadlineEvent, self).scan(cur_cpu, switches) 625 super(DeadlineEvent, self).scan(cur_cpu, switches)
586 626
587 def render(self, graph, layer, prev_events, selectable=False): 627 def render(self, graph, layer, prev_events, selectable=False):
588 prev_events[self] = None 628 prev_events[self] = None
589 if layer == Canvas.TOP_LAYER: 629 if layer == Canvas.TOP_LAYER:
@@ -593,29 +633,46 @@ class DeadlineEvent(Event):
593 else: 633 else:
594 graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(), 634 graph.draw_deadline_arrow_at_time(self.get_time(), self.get_job().get_task().get_task_no(),
595 self.get_job().get_job_no(), self.is_selected()) 635 self.get_job().get_job_no(), self.is_selected())
596 636
597 637
598class InversionStartEvent(ErrorEvent): 638class InversionStartEvent(ErrorEvent):
599 def __init__(self, time): 639 def __init__(self, time):
600 super(InversionStartEvent, self).__init__(time, Event.NO_CPU) 640 super(InversionStartEvent, self).__init__(time, Event.NO_CPU)
601 self.layer = Canvas.BOTTOM_LAYER 641 self.layer = Canvas.BOTTOM_LAYER
602 self.corresp_end_event = None 642 self.corresp_end_event = None
603 643
644 def get_name(self):
645 if self.corresp_end_event is None:
646 return 'Inversion Start (w/o Inversion End)'
647 else:
648 return 'Priority Inversion'
649
604 def __str__(self): 650 def __str__(self):
605 if self.corresp_end_event is None: 651 if self.corresp_end_event is None:
606 return 'Inversion Start (w/o Inversion End)' + self._common_str() \ 652 return super(InversionStartEvent, self).__str__()
607 + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 653 return self.get_name() + self._common_str() + ', START=' \
608 return 'Priority Inversion' + self._common_str() + ', START=' \
609 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \ 654 + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) \
610 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES) 655 + ', END=' + util.format_float(self.corresp_end_event.get_time(), Event.NUM_DEC_PLACES)
611 656
657 def str_long(self):
658 if self.corresp_end_event is None:
659 return super(InversionStartEvent, self).str_long()
660 else :
661 return 'Event Type: ' + self.get_name() + \
662 '\nTask Name: ' + str(self.get_job().get_task().get_name()) + \
663 '\n(Task no., Job no.): ' + str((self.get_job().get_task().get_task_no(), \
664 self.get_job().get_job_no())) + \
665 '\nCPU: ' + str(self.get_cpu()) + \
666 '\nStart: ' + str(self.get_time()) + \
667 '\nEnd: ' + str(self.corresp_end_event.get_time())
668
612 def scan(self, cur_cpu, switches): 669 def scan(self, cur_cpu, switches):
613 switches[InversionStartEvent] = self 670 switches[InversionStartEvent] = self
614 self.corresp_end_event = None 671 self.corresp_end_event = None
615 672
616 # the corresp_end_event should already be set 673 # the corresp_end_event should already be set
617 super(InversionStartEvent, self).scan(cur_cpu, switches) 674 super(InversionStartEvent, self).scan(cur_cpu, switches)
618 675
619 def render(self, graph, layer, prev_events, selectable=False): 676 def render(self, graph, layer, prev_events, selectable=False):
620 if layer == self.layer: 677 if layer == self.layer:
621 end_time = None 678 end_time = None
@@ -625,7 +682,7 @@ class InversionStartEvent(ErrorEvent):
625 clip = AlignMode.RIGHT 682 clip = AlignMode.RIGHT
626 else: 683 else:
627 end_time = self.corresp_end_event.get_time() 684 end_time = self.corresp_end_event.get_time()
628 685
629 if layer == self.layer: 686 if layer == self.layer:
630 prev_events[self] = None 687 prev_events[self] = None
631 cpu = self.get_cpu() 688 cpu = self.get_cpu()
@@ -637,36 +694,47 @@ class InversionStartEvent(ErrorEvent):
637 graph.draw_mini_bar_at_time(self.get_time(), end_time, 694 graph.draw_mini_bar_at_time(self.get_time(), end_time,
638 task_no, cpu, self.get_job().get_job_no(), 695 task_no, cpu, self.get_job().get_job_no(),
639 clip, self.is_selected()) 696 clip, self.is_selected())
640 697
641 698
642class InversionEndEvent(ErrorEvent): 699class InversionEndEvent(ErrorEvent):
643 def __init__(self, time): 700 def __init__(self, time):
644 super(InversionEndEvent, self).__init__(time, Event.NO_CPU) 701 super(InversionEndEvent, self).__init__(time, Event.NO_CPU)
645 self.layer = Canvas.BOTTOM_LAYER 702 self.layer = Canvas.BOTTOM_LAYER
646 self.corresp_start_event = None 703 self.corresp_start_event = None
647 704
705 def get_name(self):
706 if self.corresp_start_event is None:
707 return 'Inversion End (w/o Inversion Start)'
708 else:
709 return 'Priority Inversion'
710
648 def __str__(self): 711 def __str__(self):
649 if self.corresp_start_event is None: 712 if self.corresp_start_event is None:
650 return 'Inversion End (w/o Inversion Start)' + self._common_str() \ 713 return super(InversionEndEvent, self).__str__()
651 + ', TIME=' + util.format_float(self.get_time(), Event.NUM_DEC_PLACES) 714
652
653 return str(self.corresp_start_event) 715 return str(self.corresp_start_event)
654 716
717 def str_long(self):
718 if self.corresp_start_event is None:
719 return super(InversionEndEvent, self).str_long()
720
721 return self.corresp_start_event.str_long()
722
655 def scan(self, cur_cpu, switches): 723 def scan(self, cur_cpu, switches):
656 self.corresp_start_event = switches[InversionStartEvent] 724 self.corresp_start_event = switches[InversionStartEvent]
657 725
658 cur_cpu[0] = Event.NO_CPU 726 cur_cpu[0] = Event.NO_CPU
659 switches[InversionStartEvent] = None 727 switches[InversionStartEvent] = None
660 728
661 if self.corresp_start_event is not None: 729 if self.corresp_start_event is not None:
662 self.corresp_start_event.corresp_end_event = self 730 self.corresp_start_event.corresp_end_event = self
663 731
664 if self.corresp_start_event is None: 732 if self.corresp_start_event is None:
665 self.erroneous = True 733 self.erroneous = True
666 #print "inversion end was not matched by a corresponding inversion start" 734 #print "inversion end was not matched by a corresponding inversion start"
667 735
668 super(InversionEndEvent, self).scan(cur_cpu, switches) 736 super(InversionEndEvent, self).scan(cur_cpu, switches)
669 737
670 def render(self, graph, layer, prev_events, selectable=False): 738 def render(self, graph, layer, prev_events, selectable=False):
671 if self.corresp_start_event is None: 739 if self.corresp_start_event is None:
672 # We never found a corresponding start event. In that case, we can assume it lies 740 # We never found a corresponding start event. In that case, we can assume it lies
@@ -688,27 +756,27 @@ class InversionEndEvent(ErrorEvent):
688 if self.corresp_start_event in prev_events: 756 if self.corresp_start_event in prev_events:
689 return # already rendered the bar 757 return # already rendered the bar
690 self.corresp_start_event.render(graph, layer, prev_events, selectable) 758 self.corresp_start_event.render(graph, layer, prev_events, selectable)
691 759
692class InversionDummy(DummyEvent): 760class InversionDummy(DummyEvent):
693 def __init__(self, time, cpu): 761 def __init__(self, time, cpu):
694 super(InversionDummy, self).__init__(time, Event.NO_CPU) 762 super(InversionDummy, self).__init__(time, Event.NO_CPU)
695 self.layer = Canvas.BOTTOM_LAYER 763 self.layer = Canvas.BOTTOM_LAYER
696 764
697 def render(self, graph, layer, prev_events, selectable=False): 765 def render(self, graph, layer, prev_events, selectable=False):
698 if self.corresp_start_event is None: 766 if self.corresp_start_event is None:
699 if self.corresp_end_event in prev_events: 767 if self.corresp_end_event in prev_events:
700 return # we have already been rendered 768 return # we have already been rendered
701 self.corresp_end_event.render(graph, layer, prev_events, selectable) 769 self.corresp_end_event.render(graph, layer, prev_events, selectable)
702 else: 770 else:
703 if self.corresp_start_event in prev_events: 771 if self.corresp_start_event in prev_events:
704 return # we have already been rendered 772 return # we have already been rendered
705 self.corresp_start_event.render(graph, layer, prev_events, selectable) 773 self.corresp_start_event.render(graph, layer, prev_events, selectable)
706 774
707class IsRunningDummy(DummyEvent): 775class IsRunningDummy(DummyEvent):
708 def __init__(self, time, cpu): 776 def __init__(self, time, cpu):
709 super(IsRunningDummy, self).__init__(time, Event.NO_CPU) 777 super(IsRunningDummy, self).__init__(time, Event.NO_CPU)
710 self.layer = Canvas.BOTTOM_LAYER 778 self.layer = Canvas.BOTTOM_LAYER
711 779
712 def render(self, graph, layer, prev_events, selectable=False): 780 def render(self, graph, layer, prev_events, selectable=False):
713 if self.corresp_start_event is None: 781 if self.corresp_start_event is None:
714 if self.corresp_end_event in prev_events: 782 if self.corresp_end_event in prev_events: