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