diff options
| author | Mac Mollison <mollison@cs.unc.edu> | 2010-03-13 12:09:00 -0500 |
|---|---|---|
| committer | Mac Mollison <mollison@cs.unc.edu> | 2010-03-13 12:09:00 -0500 |
| commit | 14a40b99735f09f6e70b8e897acbb622f9115ca3 (patch) | |
| tree | e8420397374fd31aa36a66d0dc75872142d339e6 /reader/gedf_test.py | |
| parent | a643f0465d608552433ba326847eec5d0bef3108 (diff) | |
Directory restructuring
Reworked directory (and modified some code a bit) to match
intended architecture.
Diffstat (limited to 'reader/gedf_test.py')
| -rw-r--r-- | reader/gedf_test.py | 163 |
1 files changed, 0 insertions, 163 deletions
diff --git a/reader/gedf_test.py b/reader/gedf_test.py deleted file mode 100644 index e31fb19..0000000 --- a/reader/gedf_test.py +++ /dev/null | |||
| @@ -1,163 +0,0 @@ | |||
| 1 | ############################################################################### | ||
| 2 | # Description | ||
| 3 | ############################################################################### | ||
| 4 | |||
| 5 | # G-EDF Test | ||
| 6 | |||
| 7 | ############################################################################### | ||
| 8 | # Imports | ||
| 9 | ############################################################################### | ||
| 10 | |||
| 11 | import copy | ||
| 12 | |||
| 13 | |||
| 14 | ############################################################################## | ||
| 15 | # Public Functions | ||
| 16 | ############################################################################## | ||
| 17 | |||
| 18 | def gedf_test(stream): | ||
| 19 | |||
| 20 | # Two lists to model the system: tasks occupying a CPU and tasks eligible | ||
| 21 | # to do so. Also, m = the number of CPUs. | ||
| 22 | eligible = [] | ||
| 23 | on_cpu = [] | ||
| 24 | m = None | ||
| 25 | |||
| 26 | # Time of the last record we saw. Only run the G-EDF test when the time | ||
| 27 | # is updated. | ||
| 28 | last_time = None | ||
| 29 | |||
| 30 | for record in stream: | ||
| 31 | if record.record_type != "event": | ||
| 32 | if record.record_type == "meta" and record.type_name == "num_cpus": | ||
| 33 | m = record.num_cpus | ||
| 34 | continue | ||
| 35 | |||
| 36 | # Check for inversion starts and ends and yield them. | ||
| 37 | # Only to the check when time has moved forward. | ||
| 38 | # (It is common to have records with simultaneous timestamps.) | ||
| 39 | if last_time is not None and last_time != record.when: | ||
| 40 | errors = _gedf_check(eligible,on_cpu,record.when,m) | ||
| 41 | for error in errors: | ||
| 42 | yield error | ||
| 43 | |||
| 44 | # Add a newly-released Job to the eligible queue | ||
| 45 | if record.type_name == 'release': | ||
| 46 | eligible.append(Job(record)) | ||
| 47 | |||
| 48 | # Move a Job from the eligible queue to on_cpu | ||
| 49 | elif record.type_name == 'switch_to': | ||
| 50 | pos = _find_job(record,eligible) | ||
| 51 | job = eligible[pos] | ||
| 52 | del eligible[pos] | ||
| 53 | on_cpu.append(job) | ||
| 54 | |||
| 55 | # Mark a Job as completed. | ||
| 56 | # The only time a Job completes when it is not on a | ||
| 57 | # CPU is when it is the last job of the task. | ||
| 58 | elif record.type_name == 'completion': | ||
| 59 | pos = _find_job(record,on_cpu) | ||
| 60 | if pos is not None: | ||
| 61 | on_cpu[pos].is_complete = True | ||
| 62 | else: | ||
| 63 | pos = _find_job(record,eligible) | ||
| 64 | del eligible[pos] | ||
| 65 | |||
| 66 | # A job is switched away from a CPU. If it has | ||
| 67 | # been marked as complete, remove it from the model. | ||
| 68 | elif record.type_name == 'switch_away': | ||
| 69 | pos = _find_job(record,on_cpu) | ||
| 70 | job = on_cpu[pos] | ||
| 71 | del on_cpu[pos] | ||
| 72 | if job.is_complete == False: | ||
| 73 | eligible.append(job) | ||
| 74 | |||
| 75 | last_time = record.when | ||
| 76 | yield record | ||
| 77 | |||
| 78 | ############################################################################### | ||
| 79 | # Private Functions | ||
| 80 | ############################################################################### | ||
| 81 | |||
| 82 | # Internal representation of a Job | ||
| 83 | class Job(object): | ||
| 84 | def __init__(self, record): | ||
| 85 | self.pid = record.pid | ||
| 86 | self.job = record.job | ||
| 87 | self.deadline = record.deadline | ||
| 88 | self.is_complete = False | ||
| 89 | self.inversion_start = None | ||
| 90 | self.inversion_end = None | ||
| 91 | def __str__(self): | ||
| 92 | return "(%d.%d:%d)" % (self.pid,self.job,self.deadline) | ||
| 93 | |||
| 94 | # G-EDF errors: the start or end of an inversion | ||
| 95 | class Error(object): | ||
| 96 | def __init__(self, job, eligible, on_cpu): | ||
| 97 | self.job = copy.copy(job) | ||
| 98 | self.eligible = copy.copy(eligible) | ||
| 99 | self.on_cpu = copy.copy(on_cpu) | ||
| 100 | self.record_type = 'error' | ||
| 101 | if job.inversion_end is None: | ||
| 102 | self.type_name = 'inversion_start' | ||
| 103 | else: | ||
| 104 | self.type_name = 'inversion_end' | ||
| 105 | |||
| 106 | # Returns the position of a Job in a list, or None | ||
| 107 | def _find_job(record,list): | ||
| 108 | for i in range(0,len(list)): | ||
| 109 | if list[i].pid == record.pid and list[i].job == record.job: | ||
| 110 | return i | ||
| 111 | return None | ||
| 112 | |||
| 113 | # Return records for any inversion_starts and inversion_ends | ||
| 114 | def _gedf_check(eligible,on_cpu,when,m): | ||
| 115 | |||
| 116 | # List of error records to be returned | ||
| 117 | errors = [] | ||
| 118 | |||
| 119 | # List of all jobs that are not complete | ||
| 120 | all = [] | ||
| 121 | for x in on_cpu: | ||
| 122 | if x.is_complete is not True: | ||
| 123 | all.append(x) | ||
| 124 | all += eligible | ||
| 125 | |||
| 126 | # Sort by on_cpu and then by deadline. sort() is guaranteed to be stable. | ||
| 127 | # Thus, this gives us jobs ordered by deadline with preference to those | ||
| 128 | # actually running. | ||
| 129 | all.sort(key=lambda x: 0 if (x in on_cpu) else 1) | ||
| 130 | all.sort(key=lambda x: x.deadline) | ||
| 131 | |||
| 132 | # Check those that actually should be running | ||
| 133 | for x in range(0,min(m,len(all))): | ||
| 134 | job = all[x] | ||
| 135 | |||
| 136 | # It's not running and an inversion_start has not been recorded | ||
| 137 | if job not in on_cpu and job.inversion_start is None: | ||
| 138 | job.inversion_start = when | ||
| 139 | errors.append(Error(job, eligible, on_cpu)) | ||
| 140 | |||
| 141 | # It is running and an inversion_start exists (i.e. it it still | ||
| 142 | # marked as being inverted) | ||
| 143 | elif job in on_cpu and job.inversion_start is not None: | ||
| 144 | job.inversion_end = when | ||
| 145 | errors.append(Error(job, eligible, on_cpu)) | ||
| 146 | job.inversion_start = None | ||
| 147 | job.inversion_end = None | ||
| 148 | |||
| 149 | # Check those that actually should not be running | ||
| 150 | for x in range(m,len(all)): | ||
| 151 | job = all[x] | ||
| 152 | |||
| 153 | # It actually is running. We don't care. | ||
| 154 | |||
| 155 | # It isn't running, but an inversion_start exists (i.e. it is still | ||
| 156 | # marked as being inverted) | ||
| 157 | if job not in on_cpu and job.inversion_start is not None: | ||
| 158 | job.inversion_end = when | ||
| 159 | errors.append(Error(job, eligible, on_cpu)) | ||
| 160 | job.inversion_start = None | ||
| 161 | job.inversion_end = None | ||
| 162 | |||
| 163 | return errors | ||
