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 | ||