diff options
author | Gary Bressler <garybressler@nc.rr.com> | 2010-04-08 17:11:08 -0400 |
---|---|---|
committer | Gary Bressler <garybressler@nc.rr.com> | 2010-04-08 17:11:08 -0400 |
commit | ceff6457bfeb5642616f4711f14e0bb652d12164 (patch) | |
tree | d05b4ebd1c3ee6e28884c669d65fd31700941086 /unit_trace/viz/schedule.py | |
parent | 01abc8352aa2fd192678b4066b26ea749a203801 (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.py | 366 |
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 | ||
129 | class Schedule(object): | 129 | class 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 | ||
232 | def deepcopy_selected(selected): | 232 | def 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 | ||
238 | class Task(object): | 238 | class 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 | ||
268 | class Job(object): | 268 | class 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 | ||
329 | class Event(DummyEvent): | 329 | class 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 | ||
376 | class ErrorEvent(Event): | 388 | class ErrorEvent(Event): |
377 | pass | 389 | pass |
378 | 390 | ||
379 | class SuspendEvent(Event): | 391 | class 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 | ||
404 | class ResumeEvent(Event): | 416 | class 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 | ||
429 | class CompleteEvent(Event): | 441 | class 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 | ||
497 | class SwitchAwayEvent(Event): | 526 | class 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 | ||
554 | class ReleaseEvent(Event): | 594 | class 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 | ||
576 | class DeadlineEvent(Event): | 616 | class 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 | ||
598 | class InversionStartEvent(ErrorEvent): | 638 | class 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 | ||
642 | class InversionEndEvent(ErrorEvent): | 699 | class 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 | ||
692 | class InversionDummy(DummyEvent): | 760 | class 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 | ||
707 | class IsRunningDummy(DummyEvent): | 775 | class 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: |