import psyco
psyco.full()
import sys, array
from time import clock
from array import array
# task id constants
IDLE = 0
WORKER = 1
HANDLERA = 2
HANDLERB = 3
DEVICEA = 4
DEVICEB = 5
layout = 50
def main(count=10000):
startTicks = clock()
s = Scheduler();
s.addIdleTask(IDLE, 0, [], count)
s.addWorkerTask(WORKER, 1000, [
Packet(WORKER, Packet.WORK),
Packet(WORKER, Packet.WORK)
])
s.addHandlerTask(HANDLERA, 2000, [
Packet(DEVICEA, Packet.DEVICE),
Packet(DEVICEA, Packet.DEVICE),
Packet(DEVICEA, Packet.DEVICE)
])
s.addHandlerTask(HANDLERB, 3000, [
Packet(DEVICEB, Packet.DEVICE),
Packet(DEVICEB, Packet.DEVICE),
Packet(DEVICEB, Packet.DEVICE)
])
s.addDeviceTask(DEVICEA, 4000, [])
s.addDeviceTask(DEVICEB, 5000, [])
s.schedule()
stopTicks = clock()
frequency = 1000000
f=open('testrun-times.xml', 'a')
f.write('<ExternalStat>');
f.write('<size>')
f.write(str(count));
f.write('</size>')
f.write('<ticks>')
f.write(str(int((stopTicks - startTicks)*frequency)));
f.write('</ticks>')
f.write('<ticksPerSecond>')
f.write(str(frequency));
f.write('</ticksPerSecond>')
f.write('</ExternalStat>\n');
f.close()
print 'QueueCount = %d\nHoldCount = %d' % (s.queueCount, s.holdCount)
def trace(c):
global layout
if layout <= 0:
sys.stdout.write('\n')
layout = 50
layout -= 1
sys.stdout.write(c)
class Scheduler:
def __init__(self):
self.table = [None, None, None, None, None, None]
self.list = None
self.queueCount = 0
self.holdCount = 0
def addDeviceTask(self, id, pri, wkq):
self.addTask(id, pri, wkq, DeviceTask(self))
def addHandlerTask(self, id, pri, wkq):
self.addTask(id, pri, wkq, HandlerTask(self))
def addIdleTask(self, id, pri, wkq, count):
self.addRunningTask(id, pri, wkq, IdleTask(self, 1, count))
def addWorkerTask(self, id, pri, wkq):
self.addTask(id, pri, wkq, WorkerTask(self, HANDLERA, 0))
def addTask(self, id, pri, wkq, task):
self.currentTcb = Tcb(self.list, id, pri, wkq, task)
self.list = self.currentTcb
self.table[id] = self.currentTcb
def addRunningTask(self, id, pri, wkq, task):
self.addTask(id, pri, wkq, task)
self.currentTcb.setRunning()
def schedule(self):
self.currentTcb = self.list
while self.currentTcb is not None:
if self.currentTcb.isHeldOrSuspended():
self.currentTcb = self.currentTcb.getLink()
else:
self.currentId = self.currentTcb.getId()
# if __debug__:
# trace(str(self.currentId + 1))
self.currentTcb = self.currentTcb.run()
def queue(self, packet):
tcb = self.table[packet.getId()]
self.queueCount += 1
packet.setId(self.currentId)
return tcb.checkPriorityAdd(self.currentTcb,packet)
def release(self,id):
tcb = self.table[id]
tcb.notHeld()
if tcb.getPriority() > self.currentTcb.getPriority():
return tcb
else:
return self.currentTcb
def holdCurrent(self):
self.holdCount += 1
self.currentTcb.held()
return self.currentTcb.getLink()
def suspendCurrent(self):
self.currentTcb.suspended()
return self.currentTcb
class DeviceTask:
def __init__(self, scheduler):
self.scheduler = scheduler
self.v1 = None
self.v2 = None
def run(self, packet):
if packet is None:
if self.v1 is None:
return self.scheduler.suspendCurrent()
else:
pkt = self.v1
self.v1 = None
return self.scheduler.queue(pkt)
else:
self.v1 = packet
# if __debug__:
# trace(str(packet.a1))
return self.scheduler.holdCurrent()
class HandlerTask:
def __init__(self, scheduler):
self.scheduler = scheduler
self.v1 = []
self.v2 = []
def run(self, packet):
if packet is not None:
if packet.kind == Packet.WORK:
self.v1.append(packet)
else:
self.v2.append(packet)
if self.v1: # not empty
workPacket = self.v1[0]
count = workPacket.getA1()
if count > 3:
del self.v1[0]
return self.scheduler.queue(workPacket)
else:
if self.v2: # not empty
devicePacket = self.v2.pop(0)
devicePacket.setA1(workPacket.a2[count])
workPacket.setA1(count + 1)
return self.scheduler.queue(devicePacket)
return self.scheduler.suspendCurrent()
class IdleTask:
def __init__(self, scheduler, v1, v2):
self.scheduler = scheduler
self.v1 = v1
self.v2 = v2
def run(self, packet):
self.v2 -= 1
if self.v2 == 0:
return self.scheduler.holdCurrent()
else:
if (self.v1 & 1) == 0:
self.v1 = self.v1 >> 1
return self.scheduler.release(DEVICEA)
else:
self.v1 = (self.v1 >> 1) ^ 0xD008
return self.scheduler.release(DEVICEB)
class WorkerTask:
ALPHA = '0ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def __init__(self, scheduler, v1, v2):
self.scheduler = scheduler
self.v1 = v1
self.v2 = v2
def run(self, packet):
if packet is None:
return self.scheduler.suspendCurrent()
else:
if self.v1 == HANDLERA:
self.v1 = HANDLERB
else:
self.v1 = HANDLERA
packet.setId(self.v1)
packet.setA1(0)
for i in range(4):
self.v2 += 1
if self.v2 > 26:
self.v2 = 1
packet.getA2()[i] = WorkerTask.ALPHA[self.v2]
return self.scheduler.queue(packet)
class Tcb:
RUNNING = 0
RUNNABLE = 1
SUSPENDED = 2
HELD = 4
SUSPENDED_RUNNABLE = SUSPENDED | RUNNABLE
NOT_HELD = ~HELD
def __init__(self, link, id, pri, wkq, task):
self.link = link
self.id = id
self.pri = pri
self.wkq = wkq
self.task = task
if len(wkq) == 0:
self.state = 2 # Tcb.SUSPENDED
else:
self.state = 3 # Tcb.SUSPENDED_RUNNABLE
def getLink(self):
return self.link
def getId(self):
return self.id
def getPriority(self):
return self.pri
def checkPriorityAdd(self, task, packet):
if self.wkq: # not empty
self.wkq.append(packet)
else:
self.wkq.append(packet)
self.state |= 1 # Tcb.RUNNABLE
if self.pri > task.getPriority():
return self
return task
def run(self):
if self.state == 3: # Tcb.SUSPENDED_RUNNABLE
packet = self.wkq.pop(0)
if self.wkq: # not empty
self.state = 1 # Tcb.RUNNABLE
else:
self.state = 0 # Tcb.RUNNING
else:
packet = None
return self.task.run(packet)
def setRunning(self):
self.state = 0 # Tcb.RUNNING
def suspended(self):
self.state |= 2 # Tcb.SUSPENDED
def held(self):
self.state |= 4 # Tcb.HELD
def notHeld(self):
self.state &= ~4 # Tcb.NOT_HELD
def isHeldOrSuspended(self):
# return (self.state & Tcb.HELD) != 0
# or self.state == Tcb.SUSPENDED
return (self.state & 4) != 0 or self.state == 2
class Packet:
DEVICE = 0
WORK = 1
def __init__(self, id, kind):
self.id = id
self.kind = kind
self.a1 = 0
self.a2 = array('c','0000')
def getId(self):
return self.id
def setId(self,id):
self.id = id
def getKind(self):
return self.kind
def getA1(self):
return self.a1
def setA1(self,a1):
self.a1 = a1
def getA2(self):
return self.a2
if __name__ == '__main__':
import getopt
opts, args = getopt.getopt(sys.argv[1:],'')
count = 10000
if len(args) > 0:
count = int(args[0])
main(count=count)
|