def __init__(self, coreno): threading.Thread.__init__(self) self.terminated = False self.metalock = threading.RLock() self.messages = {} # UUID => (TID waiting for reply, callback) self.uuids_by_tid = defaultdict( lambda: []) # TID waiting for reply => UUIDs waited for self.rev_uuids_by_tid = defaultdict( lambda: []) # TIDs that are supposed to reply => UUIDs waited for self.pending_terminations = queue.Queue() # queue of tcbs self.uuidgen = NewIDIssuer() self.uuidgen.adjustID(coreno << 32)
def __init__(self, coreno): threading.Thread.__init__(self) self.terminated = False self.metalock = threading.RLock() self.events = [] # a heap queue of (run_at, Handler) self.pending_terminations = queue.Queue() # queue of tcbs self.teidgen = NewIDIssuer() # timer event ID, unique per TEP
def __init__(self, coreno): threading.Thread.__init__(self) self.terminated = False self.metalock = threading.RLock() self.messages = {} # UUID => (TID waiting for reply, callback) self.uuids_by_tid = defaultdict(lambda: []) # TID waiting for reply => UUIDs waited for self.rev_uuids_by_tid = defaultdict(lambda: []) # TIDs that are supposed to reply => UUIDs waited for self.pending_terminations = queue.Queue() # queue of tcbs self.uuidgen = NewIDIssuer() self.uuidgen.adjustID(coreno << 32)
class SMP(threading.Thread, Processor): def __init__(self, coreno): threading.Thread.__init__(self) self.terminated = False self.metalock = threading.RLock() self.messages = {} # UUID => (TID waiting for reply, callback) self.uuids_by_tid = defaultdict( lambda: []) # TID waiting for reply => UUIDs waited for self.rev_uuids_by_tid = defaultdict( lambda: []) # TIDs that are supposed to reply => UUIDs waited for self.pending_terminations = queue.Queue() # queue of tcbs self.uuidgen = NewIDIssuer() self.uuidgen.adjustID(coreno << 32) def terminate(self): self.terminated = True def onTaskletTerminated(self, tcb: TaskletControlBlock): self.pending_terminations.put(tcb) def deliver_reply_to(self, remote_tid: int, target_tid: int, obj: object, msg: SynchronousMessage): with self.metalock: try: tid_waiting_for_reply, callback = self.messages[msg.uuid] if tid_waiting_for_reply != target_tid: raise KeyError except KeyError: return # invalid! with S.syslock: try: tcb = S.tcbs[target_tid] except KeyError: return del self.messages[msg.uuid] self.uuids_by_tid[target_tid].remove(msg.uuid) if len(self.uuids_by_tid[target_tid]) == 0: del self.uuids_by_tid[target_tid] self.rev_uuids_by_tid[remote_tid].remove(msg.uuid) if len(self.rev_uuids_by_tid[remote_tid]) == 0: del self.rev_uuids_by_tid[remote_tid] tcb.handlers -= 1 S.schedule(tcb, callback, obj) def send_sync_to(self, from_tcb: TaskletControlBlock, target_tid: int, obj: object, handler: callable): """ Called from tasklet. Send a sync message from local tasklet to target tasklet """ if not S.isLocal(target_tid): raise NotImplementedError("No IPC for now, sorry!") smsg = SynchronousMessage(obj, from_tcb.tid, target_tid, self.uuidgen.next()) with S.syslock: if target_tid not in S.tcbs: S.schedule(from_tcb, handler, Tasklet.DoesNotExist) else: S.schedule(S.tcbs[target_tid], S.tcb_inst[target_tid].on_message, from_tcb.tid, smsg) with self.metalock: self.messages[smsg.uuid] = (from_tcb.tid, handler) self.rev_uuids_by_tid[target_tid].append(smsg.uuid) self.uuids_by_tid[from_tcb.tid].append(smsg.uuid) from_tcb.handlers += 1 def run(self): while not self.terminated: try: tcb_to_terminate = self.pending_terminations.get(True, 5) except queue.Empty: continue with self.metalock: a = self.rev_uuids_by_tid.pop(tcb_to_terminate.tid, ()) b = self.uuids_by_tid.pop(tcb_to_terminate.tid, ()) for uuid in itertools.chain(a, b): del self.messages[uuid]
class SMP(threading.Thread, Processor): def __init__(self, coreno): threading.Thread.__init__(self) self.terminated = False self.metalock = threading.RLock() self.messages = {} # UUID => (TID waiting for reply, callback) self.uuids_by_tid = defaultdict(lambda: []) # TID waiting for reply => UUIDs waited for self.rev_uuids_by_tid = defaultdict(lambda: []) # TIDs that are supposed to reply => UUIDs waited for self.pending_terminations = queue.Queue() # queue of tcbs self.uuidgen = NewIDIssuer() self.uuidgen.adjustID(coreno << 32) def terminate(self): self.terminated = True def onTaskletTerminated(self, tcb: TaskletControlBlock): self.pending_terminations.put(tcb) def deliver_reply_to(self, remote_tid: int, target_tid: int, obj: object, msg: SynchronousMessage): with self.metalock: try: tid_waiting_for_reply, callback = self.messages[msg.uuid] if tid_waiting_for_reply != target_tid: raise KeyError except KeyError: return # invalid! with S.syslock: try: tcb = S.tcbs[target_tid] except KeyError: return del self.messages[msg.uuid] self.uuids_by_tid[target_tid].remove(msg.uuid) if len(self.uuids_by_tid[target_tid]) == 0: del self.uuids_by_tid[target_tid] self.rev_uuids_by_tid[remote_tid].remove(msg.uuid) if len(self.rev_uuids_by_tid[remote_tid]) == 0: del self.rev_uuids_by_tid[remote_tid] tcb.handlers -= 1 S.schedule(tcb, callback, obj) def send_sync_to(self, from_tcb: TaskletControlBlock, target_tid: int, obj: object, handler: callable): """ Called from tasklet. Send a sync message from local tasklet to target tasklet """ if not S.isLocal(target_tid): raise NotImplementedError("No IPC for now, sorry!") smsg = SynchronousMessage(obj, from_tcb.tid, target_tid, self.uuidgen.next()) with S.syslock: if target_tid not in S.tcbs: S.schedule(from_tcb, handler, Tasklet.DoesNotExist) else: S.schedule(S.tcbs[target_tid], S.tcb_inst[target_tid].on_message, from_tcb.tid, smsg) with self.metalock: self.messages[smsg.uuid] = (from_tcb.tid, handler) self.rev_uuids_by_tid[target_tid].append(smsg.uuid) self.uuids_by_tid[from_tcb.tid].append(smsg.uuid) from_tcb.handlers += 1 def run(self): while not self.terminated: try: tcb_to_terminate = self.pending_terminations.get(True, 5) except queue.Empty: continue with self.metalock: a = self.rev_uuids_by_tid.pop(tcb_to_terminate.tid, ()) b = self.uuids_by_tid.pop(tcb_to_terminate.tid, ()) for uuid in itertools.chain(a, b): del self.messages[uuid]
class S(object): """ The grand central dispatch """ frameNo = 0 pageNo = 0 syslock = Lock() tcbs = {} # tid: int -> TaskletControlBlock tcb_inst = {} # tid: int -> TaskletInstance terminations = Queue() # list of tids' tidIssuer = NewIDIssuer() loc = local() eeps = [] # event processors neps = [] # network processors smps = [] # synchronous message processors teps = [] # time event processors @staticmethod def registerNewTasklet(tcb, inst): S.tcbs[tcb.tid] = tcb S.tcb_inst[tcb.tid] = inst @staticmethod def onTaskletTerminated(tcb): """an EEP has decided that a tasklet is dead""" del S.tcbs[tcb.tid] del S.tcb_inst[tcb.tid] for proc in itertools.chain(S.eeps, S.neps, S.smps, S.teps): proc.onTaskletTerminated(tcb) @staticmethod def startup(eeps=3, neps=3, smps=2, teps=2): """Starts up the SIC""" from ypage.processors.EEP import EEP for i in range(0, eeps): eep = EEP() eep.start() S.eeps.append(eep) from ypage.processors.NEP import NEP for i in range(0, neps): nep = NEP() nep.start() S.neps.append(nep) from ypage.processors.SMP import SMP for i in range(0, smps): smp = SMP(i) smp.start() S.smps.append(smp) from ypage.processors.TEP import TEP for i in range(0, teps): tep = TEP(i) tep.start() S.teps.append(tep) print("Started", eeps+neps+smps+teps, "processors total:") print(" ", neps, "Network Event Processors") print(" ", eeps, "Event Execution Processors") print(" ", smps, "Synchronous Message Processors") print(" ", teps, "Time Event Processors") @staticmethod def getNEP(tcb): """Returns a NEP that handles given tasklet""" return S.neps[tcb.tid % len(S.neps)] @staticmethod def getSMP(tid): """Returns a SMP that handles given tasklet on behalf of tid""" return S.smps[tid % len(S.smps)] @staticmethod def getTEP(tid): """Returns a TEP that handles given tasklet on behalf of tid""" return S.teps[tid % len(S.teps)] @staticmethod def schedule(tcb, callable_: callable, *args, **kwargs): """Schedule an event on one of available EEPs""" S.eeps[tcb.tid % len(S.eeps)].put(tcb, callable_, *args, **kwargs) @staticmethod def isLocal(tid: int) -> bool: """Checks if a particular TID belongs to a local tasklet""" return (tid >> 40) == ((S.frameNo << 8) + S.pageNo) @staticmethod def getNextTID() -> int: """Returns a new, free TID""" return S.tidIssuer.next()