-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprocess.py
214 lines (180 loc) · 5.53 KB
/
process.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/python
# -*- coding: utf-8 -*-
# @File Name: process.py
import glb
class Process():
"""Class that simulates a process"""
def __init__(self, A, B, C, M, i):
self.A = A #Arrival Time
self.B = B #CPU-burst time (block after)
self.C = C #total CPU time needed
self.M = M #ioburst = multiplier * cpuburst (block for)
self.i = i #order in list (id)
self.state = 'unstarted' #unstarted, ready, running, blocked, terminated
self.burst = 0 #time left for any state
self.prevBurst = 0 #length of previous burst (used for calculating ioburst)
self.remC = C #CPU time remaining
self.countDown = glb.q #quantum left for RR
self.timeEnteredReady = None #to find the earliest one
self.finishTime = None #time when process finishes
self.turnaroundTime = 0 #finishing time - A
self.ioTime = 0 #count time in blocked state
self.waitingTime = 0 #count time in ready state
self.runningTime = 0 #count time in running state
def __lt__(self, p):
'''priority: arrival time, input order'''
return (self.A < p.A) if (self.A != p.A) else (self.i < p.i)
def __repr__(self):
return "({} {} {} {})".format(self.A, self.B, self.C, self.M)
def __str__(self):
stateStr = (' '*10 + self.state)[-10:]
burstStr = (' '*3 + str(self.burst if not glb.q else self.countDown))[-3:]
return stateStr + burstStr
def printSummary(self):
print(''' (A,B,C,M) = ({},{},{},{})\n\tFinishing time: {}\n\tTurnaround time: {}\n\tI/O time: {}\n\tWaiting time: {}\n''' \
.format(self.A, self.B, self.C, self.M,
self.finishTime, self.turnaroundTime,
self.ioTime, self.waitingTime)
)
def tick(self):
'''recalculate time variables'''
state = self.state
if state not in ['unstarted', 'terminated']:
self.turnaroundTime += 1
if state == 'running':
self.burst -= 1 if self.burst > 0 else 0
self.remC -= 1
self.countDown -= 1 if glb.q > 0 else 0
self.runningTime += 1
elif state == 'ready':
self.waitingTime += 1
elif state == 'blocked':
self.burst -= 1 if self.burst > 0 else 0
self.ioTime += 1
return
def updateState(self):
'''update state based on new time calculations'''
now = glb.tk.getNow()
if self.state == 'running':
if self.remC == 0:
self.state = 'terminated'
self.finishTime = now
elif self.burst == 0:
self.block()
elif self.countDown == 0:
self.preempt()
elif self.state == 'unstarted':
if now == self.A:
self.unblock()
elif self.state == 'blocked':
if self.burst == 0:
self.unblock()
elif self.state == 'ready':
# ready processes are handled by the scheduler algorithm
pass
elif self.state == 'terminated':
# terminated processes are left alone
pass
return self.state
def ratio(self):
T = self.turnaroundTime
t = max(1, self.runningTime)
return T/t
def setRandomBurst(self):
self.prevBurst = glb.r.randomOS(self.B)
self.burst = self.prevBurst
return
def setIOBurst(self):
self.burst = self.M * self.prevBurst #Assumes that prevBurst was CPUBurst
return
def run(self):
self.state = 'running'
if glb.q:
self.countDown = glb.q
if self.burst == 0:
self.setRandomBurst()
def block(self):
self.state = 'blocked'
self.setIOBurst()
def _ready(self):
self.state = 'ready'
self.timeEnteredReady = glb.tk.getNow()
def unblock(self):
return self._ready()
def preempt(self):
return self._ready()
class ProcessTable(list):
"""docstring for ProcessTable"""
def __init__(self):
super(ProcessTable, self).__init__()
self.finishTime = 0
self.IOutil = 0
def __str__(self):
# unstarted 0 unstarted 0
result = ''
for el in self:
result += ' {}'.format(el)
return result
def __repr__(self):
# 2 (0 1 5 1) (0 1 5 1)
result = str(len(self))
for el in self:
result += ' {}'.format(el.__repr__())
return result
def sortByArrival(self):
self.sort(key=lambda p: p.A)
return self
def sortByInput(self):
self.sort(key=lambda p: p.i)
return self
def sortByReady(self):
self.sort(key=lambda p: p.timeEnteredReady)
return self
def sortByRatio(self):
self.sort(key=lambda p: -p.ratio())
return self
def sortByJob(self):
self.sort(key=lambda p:p.C - p.runningTime)
return self
def finished(self):
for p in self:
if p.state != 'terminated':
return False
self.finishTime = glb.tk.getNow() - 1
return True
def getAll(self, f):
result = ProcessTable()
for p in self:
if f(p):
result.append(p)
return result
def getByState(self, state):
return self.getAll(lambda p: p.state == state)
def tickAll(self):
if len(self.getAll(lambda p: p.state == 'blocked')) > 0:
self.IOutil += 1
for p in self:
p.tick()
def updateStateAll(self):
for p in self:
p.updateState()
def printSummaryAll(self):
self.sortByArrival()
psl = len(self)
finishTime = self.finishTime
CPUutil = sum(list([p.runningTime for p in self])) / finishTime
IOutil = self.IOutil / finishTime
Throughput = 100*psl/finishTime
avgTurnaround = sum(list([p.turnaroundTime for p in self])) / psl
avgWaiting = sum(list([p.waitingTime for p in self])) / psl
for i, p in enumerate(self):
print('Process {}:'.format(i))
p.printSummary()
print('''Summary Data:
Finishing time: {}
CPU Utilization: {:.6f}
I/O Utilization: {:.6f}
Throughput: {:.6f} processes per hundred cycles
Average turnaround time: {:.6f}
Average waiting time: {:.6f}\n''' \
.format(finishTime, CPUutil, IOutil, Throughput, avgTurnaround, avgWaiting))