diff options
author | chsun <chsun@mid-campus-02989.wireless.unc.edu> | 2011-04-17 16:57:04 -0400 |
---|---|---|
committer | chsun <chsun@mid-campus-02989.wireless.unc.edu> | 2011-04-17 16:57:04 -0400 |
commit | ce153b063854e9cca8ebc042f0cc08c411c8d5a1 (patch) | |
tree | 0f2aad096b43749760fff266ac07ea545166c8f8 /unit_trace | |
parent | c364f1d807eeb246ca67184246fd2c8d7933b8b6 (diff) |
Supprot C-EDF Task Priorty Inversion, Tasklet Priorty Inversion, and Work Priorty Inversion.
Support New Feather Trace Event:
ST_TASKLET_RELEASE, ST_TASKLET_BEGIN, ST_TASKLET_END,
ST_WORK_RELEASE, ST_WORK_BEGIN, ST_WORK_END,
and, ST_EFF_PRIO_CHANGE
Diffstat (limited to 'unit_trace')
-rw-r--r-- | unit_trace/gedf_inversion_stat_printer.py | 14 | ||||
-rw-r--r-- | unit_trace/gedf_test.py | 345 | ||||
-rw-r--r-- | unit_trace/stdout_printer.py | 24 | ||||
-rw-r--r-- | unit_trace/trace_reader.py | 53 |
4 files changed, 406 insertions, 30 deletions
diff --git a/unit_trace/gedf_inversion_stat_printer.py b/unit_trace/gedf_inversion_stat_printer.py index c35632a..5ea7916 100644 --- a/unit_trace/gedf_inversion_stat_printer.py +++ b/unit_trace/gedf_inversion_stat_printer.py | |||
@@ -8,7 +8,7 @@ | |||
8 | # Public Functions | 8 | # Public Functions |
9 | ############################################################################### | 9 | ############################################################################### |
10 | 10 | ||
11 | def gedf_inversion_stat_printer(stream,num): | 11 | def gedf_inversion_stat_printer(stream,num,pi_type): |
12 | 12 | ||
13 | # State | 13 | # State |
14 | min_inversion = -1 | 14 | min_inversion = -1 |
@@ -19,7 +19,7 @@ def gedf_inversion_stat_printer(stream,num): | |||
19 | 19 | ||
20 | # Iterate over records, updating state | 20 | # Iterate over records, updating state |
21 | for record in stream: | 21 | for record in stream: |
22 | if record.type_name == 'inversion_end': | 22 | if record.type_name == pi_type+'_inversion_end': |
23 | length = record.job.inversion_end - record.job.inversion_start | 23 | length = record.job.inversion_end - record.job.inversion_start |
24 | if length > 0: | 24 | if length > 0: |
25 | num_inversions += 1 | 25 | num_inversions += 1 |
@@ -53,13 +53,13 @@ def gedf_inversion_stat_printer(stream,num): | |||
53 | # Print out our information | 53 | # Print out our information |
54 | # NOTE: Here, we assume nanoseconds as the time unit. | 54 | # NOTE: Here, we assume nanoseconds as the time unit. |
55 | # May have to be changed in the future. | 55 | # May have to be changed in the future. |
56 | print "Num inversions: %d" % (num_inversions) | 56 | print "Num "+pi_type+ "_inversions: %d" % (num_inversions) |
57 | print "Min inversion: %f ms" % (float(min_inversion) / 1000000) | 57 | print "Min "+pi_type+ "_inversion: %f ms" % (float(min_inversion) / 1000000) |
58 | print "Max inversion: %f ms" % (float(max_inversion) / 1000000) | 58 | print "Max "+pi_type+ "_inversion: %f ms" % (float(max_inversion) / 1000000) |
59 | print "Avg inversion: %f ms" % (float(avg_inversion) / 1000000) | 59 | print "Avg "+pi_type+ "_inversion: %f ms" % (float(avg_inversion) / 1000000) |
60 | for inv in longest_inversions: | 60 | for inv in longest_inversions: |
61 | print "" | 61 | print "" |
62 | print "Inversion record IDs: (%d, %d)" % (inv.inversion_start_id, | 62 | print pi_type+"_Inversion record IDs: (%d, %d)" % (inv.inversion_start_id, |
63 | inv.id) | 63 | inv.id) |
64 | print("Triggering Event IDs: (%d, %d)" % | 64 | print("Triggering Event IDs: (%d, %d)" % |
65 | (inv.inversion_start_triggering_event_id, | 65 | (inv.inversion_start_triggering_event_id, |
diff --git a/unit_trace/gedf_test.py b/unit_trace/gedf_test.py index 478a852..7c2ed14 100644 --- a/unit_trace/gedf_test.py +++ b/unit_trace/gedf_test.py | |||
@@ -21,6 +21,13 @@ def gedf_test(stream): | |||
21 | # System model | 21 | # System model |
22 | on_cpu = [] # Tasks on a CPU | 22 | on_cpu = [] # Tasks on a CPU |
23 | off_cpu = [] # Tasks not on a CPU | 23 | off_cpu = [] # Tasks not on a CPU |
24 | |||
25 | tasklet_off_cpu = [] # Tasklets on a CPU | ||
26 | tasklet_on_cpu = [] # Tasklets on a CPU | ||
27 | |||
28 | work_off_cpu = [] # Work items on a CPU | ||
29 | work_on_cpu = [] # Work items on a CPU | ||
30 | |||
24 | m = None # CPUs | 31 | m = None # CPUs |
25 | 32 | ||
26 | # Time of the last record we saw. Only run the G-EDF test when the time | 33 | # Time of the last record we saw. Only run the G-EDF test when the time |
@@ -45,16 +52,23 @@ def gedf_test(stream): | |||
45 | # so we only check when the time has moved forward) | 52 | # so we only check when the time has moved forward) |
46 | # Also, need to update the first_event_this_timestamp variable | 53 | # Also, need to update the first_event_this_timestamp variable |
47 | if last_time is not None and last_time != record.when: | 54 | if last_time is not None and last_time != record.when: |
48 | errors = _gedf_check(off_cpu,on_cpu,last_time,m, | 55 | errors = _gedf_check(off_cpu,on_cpu,last_time,m, |
49 | first_event_this_timestamp) | 56 | first_event_this_timestamp) |
50 | first_event_this_timestamp = record.id | 57 | errors += _gedf_check_tasklet(off_cpu,on_cpu, |
51 | for error in errors: | 58 | tasklet_off_cpu,tasklet_on_cpu,last_time,m, |
52 | yield error | 59 | first_event_this_timestamp) |
60 | errors += _gedf_check_work(off_cpu,on_cpu, | ||
61 | work_off_cpu,work_on_cpu,last_time,m, | ||
62 | first_event_this_timestamp) | ||
63 | |||
64 | first_event_this_timestamp = record.id | ||
65 | for error in errors: | ||
66 | yield error | ||
53 | 67 | ||
54 | # Add a newly-released Job to the off_cpu queue | 68 | # Add a newly-released Job to the off_cpu queue |
55 | if record.type_name == 'release': | 69 | if record.type_name == 'release': |
56 | off_cpu.append(Job(record)) | 70 | off_cpu.append(Job(record)) |
57 | 71 | ||
58 | # Move a Job from the off_cpu queue to on_cpu | 72 | # Move a Job from the off_cpu queue to on_cpu |
59 | elif record.type_name == 'switch_to': | 73 | elif record.type_name == 'switch_to': |
60 | pos = _find_job(record,off_cpu) | 74 | pos = _find_job(record,off_cpu) |
@@ -93,6 +107,8 @@ def gedf_test(stream): | |||
93 | del on_cpu[pos] | 107 | del on_cpu[pos] |
94 | if job.is_complete == False: | 108 | if job.is_complete == False: |
95 | off_cpu.append(job) | 109 | off_cpu.append(job) |
110 | |||
111 | |||
96 | 112 | ||
97 | # A job has been blocked. | 113 | # A job has been blocked. |
98 | elif record.type_name == 'block': | 114 | elif record.type_name == 'block': |
@@ -114,6 +130,94 @@ def gedf_test(stream): | |||
114 | 130 | ||
115 | last_time = record.when | 131 | last_time = record.when |
116 | yield record | 132 | yield record |
133 | |||
134 | # Add a newly-released Takslet to the tasklet_off_cpu queue | ||
135 | if record.type_name == 'tasklet_release': | ||
136 | tasklet_off_cpu.append(Job(record)) | ||
137 | |||
138 | # Move a Takslet from the tasklet_off_cpu queue to tasklet_on_cpu | ||
139 | elif record.type_name == 'tasklet_begin': | ||
140 | pos = _find_job(record,tasklet_off_cpu) | ||
141 | if pos is None: | ||
142 | msg = "Event %d tried to begin to a tasklet that was not on the" | ||
143 | msg += " tasklet_off_cpu queue\n" | ||
144 | msg = msg % (record.id) | ||
145 | sys.stderr.write(msg) | ||
146 | exit() | ||
147 | job = tasklet_off_cpu[pos] | ||
148 | del tasklet_off_cpu[pos] | ||
149 | tasklet_on_cpu.append(job) | ||
150 | |||
151 | |||
152 | # A Takslet is end from a CPU. | ||
153 | elif record.type_name == 'tasklet_end': | ||
154 | pos = _find_job(record,tasklet_on_cpu) | ||
155 | if pos is None: | ||
156 | msg = ("Event %d tried to end a tasklet" + | ||
157 | " that was not running\n") | ||
158 | msg = msg % (record.id) | ||
159 | sys.stderr.write(msg) | ||
160 | exit() | ||
161 | job = tasklet_on_cpu[pos] | ||
162 | del tasklet_on_cpu[pos] | ||
163 | |||
164 | # Add a newly-released Work item to the work_off_cpu queue | ||
165 | if record.type_name == 'work_release': | ||
166 | work_off_cpu.append(Job(record)) | ||
167 | |||
168 | # Register a klitirqd threadto a Work item in the work_off_cpu | ||
169 | elif record.type_name == 'work_begin': | ||
170 | pos = _find_job(record,work_off_cpu) | ||
171 | if pos is None: | ||
172 | msg = "Event %d tried to begin to a work item that was not on the" | ||
173 | msg += " work_off_cpu queue\n" | ||
174 | msg = msg % (record.id) | ||
175 | sys.stderr.write(msg) | ||
176 | exit() | ||
177 | job = work_off_cpu[pos] | ||
178 | job.exe_pid = record.exe_pid | ||
179 | del work_off_cpu[pos] | ||
180 | work_on_cpu.append(job) | ||
181 | |||
182 | # A Work item is end from a CPU. | ||
183 | elif record.type_name == 'work_end': | ||
184 | pos = _find_job(record,work_on_cpu) | ||
185 | if pos is not None: | ||
186 | del work_on_cpu[pos] | ||
187 | else: | ||
188 | pos = _find_job(record,work_off_cpu) | ||
189 | if pos is not None: | ||
190 | msg = ("Event %d tried to end a work item" + | ||
191 | " that hasn't not executed\n") | ||
192 | msg = msg % (record.id) | ||
193 | sys.stderr.write(msg) | ||
194 | exit() | ||
195 | |||
196 | # a Tasklet has Priority inheritance | ||
197 | elif record.type_name == 'eff_prio_change': | ||
198 | pos = _find_job(record,on_cpu) | ||
199 | |||
200 | if pos is None: | ||
201 | msg = ("Event %d tried to change a jobs priority " + | ||
202 | " that was not running\n") | ||
203 | msg = msg % (record.id) | ||
204 | sys.stderr.write(msg) | ||
205 | exit() | ||
206 | |||
207 | inh_pos = _find_inh_job(record,off_cpu) | ||
208 | if inh_pos is None: | ||
209 | inh_pos = _find_inh_job(record,on_cpu) | ||
210 | inh_job = on_cpu[pos] | ||
211 | else: | ||
212 | inh_job = off_cpu[pos] | ||
213 | |||
214 | if inh_pos is not None: | ||
215 | on_cpu[pos].is_prio_inh=True | ||
216 | on_cpu[pos].inh_deadline = inh_job.deadline | ||
217 | else: | ||
218 | on_cpu[pos].is_prio_inh=False | ||
219 | on_cpu[pos].inh_deadline =job.deadline | ||
220 | |||
117 | 221 | ||
118 | ############################################################################### | 222 | ############################################################################### |
119 | # Private Functions | 223 | # Private Functions |
@@ -125,6 +229,9 @@ class Job(object): | |||
125 | self.pid = record.pid | 229 | self.pid = record.pid |
126 | self.job = record.job | 230 | self.job = record.job |
127 | self.deadline = record.deadline | 231 | self.deadline = record.deadline |
232 | self.inh_deadline = record.deadline | ||
233 | self.exe_pid = None | ||
234 | self.is_prio_inh = False | ||
128 | self.is_complete = False | 235 | self.is_complete = False |
129 | self.is_blocked = False | 236 | self.is_blocked = False |
130 | self.inversion_start = None | 237 | self.inversion_start = None |
@@ -137,7 +244,7 @@ class Job(object): | |||
137 | # G-EDF errors: the start or end of an inversion | 244 | # G-EDF errors: the start or end of an inversion |
138 | class Error(object): | 245 | class Error(object): |
139 | id = 0 | 246 | id = 0 |
140 | def __init__(self, job, off_cpu, on_cpu,first_event_this_timestamp): | 247 | def __init__(self, job, off_cpu, on_cpu,first_event_this_timestamp,pi_type): |
141 | Error.id += 1 | 248 | Error.id += 1 |
142 | self.id = Error.id | 249 | self.id = Error.id |
143 | self.job = copy.copy(job) | 250 | self.job = copy.copy(job) |
@@ -146,13 +253,15 @@ class Error(object): | |||
146 | self.record_type = 'error' | 253 | self.record_type = 'error' |
147 | self.triggering_event_id = first_event_this_timestamp | 254 | self.triggering_event_id = first_event_this_timestamp |
148 | if job.inversion_end is None: | 255 | if job.inversion_end is None: |
149 | self.type_name = 'inversion_start' | 256 | self.type_name = pi_type+'_inversion_start' |
150 | job.inversion_start_id = self.id | 257 | job.inversion_start_id = self.id |
151 | job.inversion_start_triggering_event_id = self.triggering_event_id | 258 | job.inversion_start_triggering_event_id = self.triggering_event_id |
152 | else: | 259 | else: |
153 | self.type_name = 'inversion_end' | 260 | self.type_name = pi_type+'_inversion_end' |
154 | self.inversion_start_id = job.inversion_start_id | 261 | self.inversion_start_id = job.inversion_start_id |
155 | self.inversion_start_triggering_event_id = job.inversion_start_triggering_event_id | 262 | self.inversion_start_triggering_event_id = job.inversion_start_triggering_event_id |
263 | |||
264 | |||
156 | 265 | ||
157 | # Returns the position of a Job in a list, or None | 266 | # Returns the position of a Job in a list, or None |
158 | def _find_job(record,list): | 267 | def _find_job(record,list): |
@@ -161,6 +270,20 @@ def _find_job(record,list): | |||
161 | return i | 270 | return i |
162 | return None | 271 | return None |
163 | 272 | ||
273 | # Returns the position of a Job in a list, or None | ||
274 | def _find_work_carrier(record,list): | ||
275 | for i in range(0,len(list)): | ||
276 | if list[i].pid == exe_pid: | ||
277 | return i | ||
278 | return None | ||
279 | |||
280 | # Returns the position of a inheritanced Job in a list, or None | ||
281 | def _find_inh_job(record,list): | ||
282 | for i in range(0,len(list)): | ||
283 | if list[i].pid == record.inh_pid: | ||
284 | return i | ||
285 | return None | ||
286 | |||
164 | # Return records for any inversion_starts and inversion_ends | 287 | # Return records for any inversion_starts and inversion_ends |
165 | def _gedf_check(off_cpu,on_cpu,when,m,first_event_this_timestamp): | 288 | def _gedf_check(off_cpu,on_cpu,when,m,first_event_this_timestamp): |
166 | 289 | ||
@@ -192,14 +315,14 @@ def _gedf_check(off_cpu,on_cpu,when,m,first_event_this_timestamp): | |||
192 | if job not in on_cpu and job.inversion_start is None: | 315 | if job not in on_cpu and job.inversion_start is None: |
193 | job.inversion_start = when | 316 | job.inversion_start = when |
194 | errors.append(Error(job, off_cpu, on_cpu, | 317 | errors.append(Error(job, off_cpu, on_cpu, |
195 | first_event_this_timestamp)) | 318 | first_event_this_timestamp,"Task")) |
196 | 319 | ||
197 | # It is running and an inversion_start exists (i.e. it it still | 320 | # It is running and an inversion_start exists (i.e. it it still |
198 | # marked as being inverted) | 321 | # marked as being inverted) |
199 | elif job in on_cpu and job.inversion_start is not None: | 322 | elif job in on_cpu and job.inversion_start is not None: |
200 | job.inversion_end = when | 323 | job.inversion_end = when |
201 | errors.append(Error(job, off_cpu, on_cpu, | 324 | errors.append(Error(job, off_cpu, on_cpu, |
202 | first_event_this_timestamp)) | 325 | first_event_this_timestamp,"Task")) |
203 | job.inversion_start = None | 326 | job.inversion_start = None |
204 | job.inversion_end = None | 327 | job.inversion_end = None |
205 | 328 | ||
@@ -210,7 +333,7 @@ def _gedf_check(off_cpu,on_cpu,when,m,first_event_this_timestamp): | |||
210 | if job not in on_cpu and job.inversion_start is not None: | 333 | if job not in on_cpu and job.inversion_start is not None: |
211 | job.inversion_end = when | 334 | job.inversion_end = when |
212 | errors.append(Error(job, off_cpu, on_cpu, | 335 | errors.append(Error(job, off_cpu, on_cpu, |
213 | first_event_this_timestamp)) | 336 | first_event_this_timestamp,"Task")) |
214 | job.inversion_start = None | 337 | job.inversion_start = None |
215 | job.inversion_end = None | 338 | job.inversion_end = None |
216 | 339 | ||
@@ -220,8 +343,204 @@ def _gedf_check(off_cpu,on_cpu,when,m,first_event_this_timestamp): | |||
220 | for job in all: | 343 | for job in all: |
221 | job.inversion_end = when | 344 | job.inversion_end = when |
222 | errors.append(Error(job, off_cpu, on_cpu, | 345 | errors.append(Error(job, off_cpu, on_cpu, |
223 | first_event_this_timestamp)) | 346 | first_event_this_timestamp,"Task")) |
224 | job.inversion_start = None | 347 | job.inversion_start = None |
225 | job.inversion_end = None | 348 | job.inversion_end = None |
226 | 349 | ||
227 | return errors | 350 | return errors |
351 | |||
352 | # Return records for any inversion_starts and inversion_ends | ||
353 | def _gedf_check_work(off_cpu,on_cpu, | ||
354 | work_off_cpu,work_on_cpu, | ||
355 | when,m,first_event_this_timestamp): | ||
356 | |||
357 | # List of error records to be returned | ||
358 | errors = [] | ||
359 | |||
360 | # List of all jobs | ||
361 | all_prio = [] | ||
362 | for x in on_cpu: | ||
363 | all_prio.append(x) | ||
364 | for x in off_cpu: | ||
365 | all_prio.append(x) | ||
366 | |||
367 | # Sort all task by then by deadline (inh_deadline). | ||
368 | all_prio.sort(key=lambda x: x.inh_deadline) | ||
369 | |||
370 | #Look for all tasklet is tasklet_off_cpu (not running) | ||
371 | for work in work_off_cpu: | ||
372 | _on = _find_job(work,on_cpu) | ||
373 | pos = _find_job(work,all_prio) | ||
374 | # owner task must be completed!! weird | ||
375 | if pos is None: | ||
376 | continue | ||
377 | # if the owner task is running | ||
378 | if _on is not None: | ||
379 | # if the owner task is not blocked | ||
380 | if on_cpu[_on].is_blocked==False and work.inversion_start is not None: | ||
381 | work.inversion_end = when | ||
382 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
383 | first_event_this_timestamp,"Work_Item")) | ||
384 | work.inversion_start = None | ||
385 | work.inversion_end = None | ||
386 | # if the owner task is blocked | ||
387 | elif on_cpu[_on].is_blocked==True: | ||
388 | # if the owner task prioirty is smaller than m | ||
389 | if pos<m and work.inversion_start is None: | ||
390 | work.inversion_start = when | ||
391 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
392 | first_event_this_timestamp,"Work_Item")) | ||
393 | # if the owner task prioirty is bigger than m | ||
394 | elif pos>=m and work.inversion_start is not None: | ||
395 | work.inversion_end = when | ||
396 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
397 | first_event_this_timestamp,"Work_Item")) | ||
398 | work.inversion_start = None | ||
399 | work.inversion_end = None | ||
400 | # if the owner task is not running | ||
401 | else: | ||
402 | # if the owner task prioirty is smaller than m | ||
403 | if pos<m and work.inversion_start is None: | ||
404 | work.inversion_start = when | ||
405 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
406 | first_event_this_timestamp,"Work_Item")) | ||
407 | # if the owner task prioirty is bigger than m | ||
408 | elif pos >= m and work.inversion_start is not None: | ||
409 | work.inversion_end = when | ||
410 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
411 | first_event_this_timestamp,"Work_Item")) | ||
412 | work.inversion_start = None | ||
413 | work.inversion_end = None | ||
414 | |||
415 | # have klitirqd take care of | ||
416 | for work in work_on_cpu: | ||
417 | _on = _find_job(work,on_cpu) | ||
418 | pos = _find_job(work,all_prio) | ||
419 | # owner task must be completed!! weird | ||
420 | if pos is None: | ||
421 | continue | ||
422 | klit_pos = _find_work_carrier(work,on_cpu) | ||
423 | # if the klitirqd task is running and is not blocked | ||
424 | if klit_pos is not None and on_cpu[klit_pos].is_blocked == False and work.inversion_start is not None: | ||
425 | work.inversion_end = when | ||
426 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
427 | first_event_this_timestamp,"Work_Item")) | ||
428 | work.inversion_start = None | ||
429 | work.inversion_end = None | ||
430 | else: | ||
431 | # if the owner task is running | ||
432 | if _on is not None: | ||
433 | # if the owner task is not blocked | ||
434 | if on_cpu[_on].is_blocked==False and work.inversion_start is not None: | ||
435 | work.inversion_end = when | ||
436 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
437 | first_event_this_timestamp,"Work_Item")) | ||
438 | work.inversion_start = None | ||
439 | work.inversion_end = None | ||
440 | # if the owner task is blocked | ||
441 | elif on_cpu[_on].is_blocked==True : | ||
442 | # if the owner task prioirty is smaller than m | ||
443 | if pos<m and work.inversion_start is None: | ||
444 | work.inversion_start = when | ||
445 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
446 | first_event_this_timestamp,"Work_Item")) | ||
447 | # if the owner task prioirty is bigger than m | ||
448 | elif pos>=m and work.inversion_start is not None: | ||
449 | work.inversion_end = when | ||
450 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
451 | first_event_this_timestamp,"Work_Item")) | ||
452 | work.inversion_start = None | ||
453 | work.inversion_end = None | ||
454 | # if the owner task is not running | ||
455 | else: | ||
456 | # if the owner task prioirty is smaller than m | ||
457 | if pos<m and work.inversion_start is None: | ||
458 | work.inversion_start = when | ||
459 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
460 | first_event_this_timestamp,"Work_Item")) | ||
461 | # if the owner task prioirty is bigger than m | ||
462 | elif pos>=m and work.inversion_start is not None: | ||
463 | work.inversion_end = when | ||
464 | errors.append(Error(work, work_off_cpu, work_on_cpu, | ||
465 | first_event_this_timestamp,"Work_Item")) | ||
466 | work.inversion_start = None | ||
467 | work.inversion_end = None | ||
468 | |||
469 | |||
470 | return errors | ||
471 | |||
472 | |||
473 | |||
474 | # Return records for any inversion_starts and inversion_ends | ||
475 | def _gedf_check_tasklet(off_cpu,on_cpu, | ||
476 | tasklet_off_cpu, tasklet_on_cpu, | ||
477 | when,m,first_event_this_timestamp): | ||
478 | |||
479 | # List of error records to be returned | ||
480 | errors = [] | ||
481 | |||
482 | # List of all jobs | ||
483 | all = [] | ||
484 | for x in on_cpu: | ||
485 | all.append(x) | ||
486 | for x in off_cpu: | ||
487 | all.append(x) | ||
488 | |||
489 | # Sort all task by then by deadline (inh_deadline). | ||
490 | all.sort(key=lambda x: x.inh_deadline) | ||
491 | |||
492 | #Look for all tasklet is tasklet_off_cpu (not running) | ||
493 | for tasklet in tasklet_off_cpu: | ||
494 | _on = _find_job(tasklet,on_cpu) | ||
495 | pos = _find_job(tasklet,all) | ||
496 | # owner task must be completed!! weird | ||
497 | if pos is None: | ||
498 | continue | ||
499 | # if the owner task is running | ||
500 | if _on is not None: | ||
501 | # if the owner task is not blocked | ||
502 | if on_cpu[_on].is_blocked==False and tasklet.inversion_start is not None: | ||
503 | tasklet.inversion_end = when | ||
504 | errors.append(Error(tasklet, tasklet_off_cpu, tasklet_on_cpu, | ||
505 | first_event_this_timestamp,"Tasklet")) | ||
506 | tasklet.inversion_start = None | ||
507 | tasklet.inversion_end = None | ||
508 | # if the owner task is blocked | ||
509 | elif on_cpu[_on].is_blocked==True : | ||
510 | # if the owner task prioirty is smaller than m | ||
511 | if pos<m and tasklet.inversion_start is None: | ||
512 | tasklet.inversion_start = when | ||
513 | errors.append(Error(tasklet, tasklet_off_cpu, tasklet_on_cpu, | ||
514 | first_event_this_timestamp,"Tasklet")) | ||
515 | # if the owner task prioirty is bigger than m | ||
516 | elif pos>=m and tasklet.inversion_start is not None: | ||
517 | tasklet.inversion_end = when | ||
518 | errors.append(Error(tasklet, tasklet_off_cpu, tasklet_on_cpu, | ||
519 | first_event_this_timestamp,"Tasklet")) | ||
520 | tasklet.inversion_start = None | ||
521 | tasklet.inversion_end = None | ||
522 | # if the owner task is not running | ||
523 | else: | ||
524 | # if the owner task prioirty is smaller than m | ||
525 | if pos<m and tasklet.inversion_start is None: | ||
526 | tasklet.inversion_start = when | ||
527 | errors.append(Error(tasklet, tasklet_off_cpu, tasklet_on_cpu, | ||
528 | first_event_this_timestamp,"Tasklet")) | ||
529 | # if the owner task prioirty is bigger than m | ||
530 | elif pos>=m and tasklet.inversion_start is not None: | ||
531 | tasklet.inversion_end = when | ||
532 | errors.append(Error(tasklet, tasklet_off_cpu, tasklet_on_cpu, | ||
533 | first_event_this_timestamp,"Tasklet")) | ||
534 | tasklet.inversion_start = None | ||
535 | tasklet.inversion_end = None | ||
536 | |||
537 | #Look for all tasklet is tasklet_on_cpu (running) | ||
538 | for tasklet in tasklet_on_cpu: | ||
539 | if tasklet.inversion_start is not None: | ||
540 | tasklet.inversion_end = when | ||
541 | errors.append(Error(tasklet, tasklet_off_cpu, tasklet_on_cpu, | ||
542 | first_event_this_timestamp,"Tasklet")) | ||
543 | tasklet.inversion_start = None | ||
544 | tasklet.inversion_end = None | ||
545 | |||
546 | return errors | ||
diff --git a/unit_trace/stdout_printer.py b/unit_trace/stdout_printer.py index b70b31a..c8fba1f 100644 --- a/unit_trace/stdout_printer.py +++ b/unit_trace/stdout_printer.py | |||
@@ -14,10 +14,18 @@ def stdout_printer(stream): | |||
14 | _print_event(record) | 14 | _print_event(record) |
15 | elif record.record_type == "meta" and record.type_name == "stats": | 15 | elif record.record_type == "meta" and record.type_name == "stats": |
16 | _print_stats(record) | 16 | _print_stats(record) |
17 | elif record.record_type == "error" and record.type_name == 'inversion_start': | 17 | elif record.record_type == "error" and record.type_name == 'Task_inversion_start': |
18 | _print_inversion_start(record) | 18 | _print_inversion_start(record,"Task_") |
19 | elif record.record_type == "error" and record.type_name == 'inversion_end': | 19 | elif record.record_type == "error" and record.type_name == 'Task_inversion_end': |
20 | _print_inversion_end(record) | 20 | _print_inversion_end(record,"Task_") |
21 | elif record.record_type == "error" and record.type_name == 'Tasklet_inversion_start': | ||
22 | _print_inversion_start(record,"Tasklet_") | ||
23 | elif record.record_type == "error" and record.type_name == 'Tasklet_inversion_end': | ||
24 | _print_inversion_end(record,"Tasklet_") | ||
25 | elif record.record_type == "error" and record.type_name == 'Work_Item_inversion_start': | ||
26 | _print_inversion_start(record,"Work_Item_") | ||
27 | elif record.record_type == "error" and record.type_name == 'Work_Item_inversion_end': | ||
28 | _print_inversion_end(record,"Work_Item_") | ||
21 | else: | 29 | else: |
22 | continue | 30 | continue |
23 | print "" | 31 | print "" |
@@ -32,8 +40,8 @@ def _print_event(record): | |||
32 | print "Type: %s" % (record.type_name) | 40 | print "Type: %s" % (record.type_name) |
33 | print "Time: %d" % (record.when) | 41 | print "Time: %d" % (record.when) |
34 | 42 | ||
35 | def _print_inversion_start(record): | 43 | def _print_inversion_start(record,pi_type): |
36 | print "Type: %s" % ("Inversion start") | 44 | print "Type: %s" % (pi_type+"Inversion start") |
37 | print "Inversion Record IDs: (%d, U)" % (record.id) | 45 | print "Inversion Record IDs: (%d, U)" % (record.id) |
38 | print "Triggering Event IDs: (%d, U)" % (record.triggering_event_id) | 46 | print "Triggering Event IDs: (%d, U)" % (record.triggering_event_id) |
39 | print "Time: %d" % (record.job.inversion_start) | 47 | print "Time: %d" % (record.job.inversion_start) |
@@ -48,8 +56,8 @@ def _print_inversion_start(record): | |||
48 | print str(job) + " ", | 56 | print str(job) + " ", |
49 | print #newline | 57 | print #newline |
50 | 58 | ||
51 | def _print_inversion_end(record): | 59 | def _print_inversion_end(record,pi_type): |
52 | print "Type: %s" % ("Inversion end") | 60 | print "Type: %s" % (pi_type+"Inversion end") |
53 | print "Inversion record IDs: (%d, %d)" % (record.inversion_start_id, | 61 | print "Inversion record IDs: (%d, %d)" % (record.inversion_start_id, |
54 | record.id) | 62 | record.id) |
55 | print("Triggering Event IDs: (%d, %d)" % | 63 | print("Triggering Event IDs: (%d, %d)" % |
diff --git a/unit_trace/trace_reader.py b/unit_trace/trace_reader.py index db36c13..45b29e1 100644 --- a/unit_trace/trace_reader.py +++ b/unit_trace/trace_reader.py | |||
@@ -266,12 +266,58 @@ class StSysReleaseData: | |||
266 | formatStr = struct.Struct(StHeader.format + format) | 266 | formatStr = struct.Struct(StHeader.format + format) |
267 | keys = StHeader.keys + ['when','release'] | 267 | keys = StHeader.keys + ['when','release'] |
268 | message = 'All tasks have checked in, task system released by user' | 268 | message = 'All tasks have checked in, task system released by user' |
269 | |||
270 | class StTaskletReleaseData: | ||
271 | format = 'Q' | ||
272 | formatStr = struct.Struct(StHeader.format + format) | ||
273 | keys = StHeader.keys + ['when'] | ||
274 | message = 'A tasklet is queued' | ||
275 | |||
276 | class StTaskletBeginData: | ||
277 | format = 'Q' | ||
278 | formatStr = struct.Struct(StHeader.format + format) | ||
279 | keys = StHeader.keys + ['when'] | ||
280 | message = 'A tasklet begins execution' | ||
281 | |||
282 | class StTaskletEndData: | ||
283 | format = 'Qc' | ||
284 | formatStr = struct.Struct(StHeader.format + format) | ||
285 | keys = StHeader.keys + ['when','flushed'] | ||
286 | message = 'A tasklet completes execution' | ||
287 | |||
288 | class StWorkReleaseData: | ||
289 | format = 'Q' | ||
290 | formatStr = struct.Struct(StHeader.format + format) | ||
291 | keys = StHeader.keys + ['when'] | ||
292 | message = 'A work item is queued' | ||
293 | |||
294 | class StWorkBeginData: | ||
295 | format = 'Qh' | ||
296 | formatStr = struct.Struct(StHeader.format + format) | ||
297 | keys = StHeader.keys + ['when','exe_pid'] | ||
298 | message = 'A work item begins execution' | ||
299 | |||
300 | class StWorkEndData: | ||
301 | format = 'Qhc' | ||
302 | formatStr = struct.Struct(StHeader.format + format) | ||
303 | keys = StHeader.keys + ['when','exe_pid','flushed'] | ||
304 | message = 'A work item completes execution' | ||
305 | |||
306 | |||
307 | class StEffPrioChangeData: | ||
308 | format = 'Qh' | ||
309 | formatStr = struct.Struct(StHeader.format + format) | ||
310 | keys = StHeader.keys + ['when','inh_pid'] | ||
311 | message = 'A tasklet priorty gets changed by inheritance' | ||
269 | 312 | ||
270 | # Return the binary data type, given the type_num | 313 | # Return the binary data type, given the type_num |
271 | def _get_type(type_num): | 314 | def _get_type(type_num): |
272 | types = [None,StNameData,StParamData,StReleaseData,StAssignedData, | 315 | types = [None,StNameData,StParamData,StReleaseData,StAssignedData, |
273 | StSwitchToData,StSwitchAwayData,StCompletionData,StBlockData, | 316 | StSwitchToData,StSwitchAwayData,StCompletionData,StBlockData, |
274 | StResumeData,StSysReleaseData] | 317 | StResumeData,StSysReleaseData, |
318 | StTaskletReleaseData,StTaskletBeginData,StTaskletEndData, | ||
319 | StWorkReleaseData,StWorkBeginData,StWorkEndData, | ||
320 | StEffPrioChangeData] | ||
275 | if type_num > len(types)-1 or type_num < 1: | 321 | if type_num > len(types)-1 or type_num < 1: |
276 | raise Exception | 322 | raise Exception |
277 | return types[type_num] | 323 | return types[type_num] |
@@ -280,5 +326,8 @@ def _get_type(type_num): | |||
280 | # programmers of other modules) | 326 | # programmers of other modules) |
281 | def _get_type_name(type_num): | 327 | def _get_type_name(type_num): |
282 | type_names = [None,"name","params","release","assign","switch_to", | 328 | type_names = [None,"name","params","release","assign","switch_to", |
283 | "switch_away","completion","block","resume","sys_release"] | 329 | "switch_away","completion","block","resume","sys_release", |
330 | "tasklet_release","tasklet_begin","tasklet_end", | ||
331 | "work_release","work_begin","work_end", | ||
332 | "eff_prio_change"] | ||
284 | return type_names[type_num] | 333 | return type_names[type_num] |