From 87d6923d69bc0a33e0ac25f3f3eef27f9a24c9f9 Mon Sep 17 00:00:00 2001 From: yuchen Date: Wed, 8 Apr 2015 11:25:14 +0800 Subject: [PATCH] add process-cpuio-homework for lab5 --- related_info/lab5/process-cpuio-homework.py | 274 ++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100755 related_info/lab5/process-cpuio-homework.py diff --git a/related_info/lab5/process-cpuio-homework.py b/related_info/lab5/process-cpuio-homework.py new file mode 100755 index 0000000..e17067d --- /dev/null +++ b/related_info/lab5/process-cpuio-homework.py @@ -0,0 +1,274 @@ +#! /usr/bin/env python + +import sys +from optparse import OptionParser +import random + +# process switch behavior +SCHED_SWITCH_ON_IO = 'SWITCH_ON_IO' + +# io finished behavior +IO_RUN_LATER = 'IO_RUN_LATER' + +# process states +STATE_RUNNING = 'RUNNING' +STATE_READY = 'READY' +STATE_DONE = 'DONE' +STATE_WAIT = 'WAITING' + +# members of process structure +PROC_CODE = 'code_' +PROC_PC = 'pc_' +PROC_ID = 'pid_' +PROC_STATE = 'proc_state_' + +# things a process can do +DO_COMPUTE = 'cpu' +DO_YIELD = 'yld' +DO_IO = 'io' + +class scheduler: + def __init__(self, process_switch_behavior, io_done_behavior, io_length): + # keep set of instructions for each of the processes + self.proc_info = {} + self.process_switch_behavior = process_switch_behavior + self.io_done_behavior = io_done_behavior + self.io_length = io_length + return + + def new_process(self): + proc_id = len(self.proc_info) + self.proc_info[proc_id] = {} + self.proc_info[proc_id][PROC_PC] = 0 + self.proc_info[proc_id][PROC_ID] = proc_id + self.proc_info[proc_id][PROC_CODE] = [] + self.proc_info[proc_id][PROC_STATE] = STATE_READY + return proc_id + + def load(self, program_description): + proc_id = self.new_process() + tmp = program_description.split(':') + if len(tmp) != 3: + print 'Bad description (%s): Must be number ' + print ' where X is the number of instructions' + print ' and Y is the percent change that an instruction is YIELD' + print ' and Z is the percent change that an instruction is IO' + exit(1) + + num_instructions, chance_yield, chance_io = int(tmp[0]), float(tmp[1])/100.0, float(tmp[2])/100.0 + assert(chance_yield+chance_io<1) + + #print "proc %d, num_instr %d, change_cpu %f" % (proc_id,num_instructions, chance_cpu) + for i in range(num_instructions): + randnum=random.random(); + if randnum < (1.0-chance_yield-chance_io): + self.proc_info[proc_id][PROC_CODE].append(DO_COMPUTE) + elif randnum >= (1.0-chance_yield-chance_io) and randnum < (1.0-chance_io): + self.proc_info[proc_id][PROC_CODE].append(DO_YIELD) + else: + self.proc_info[proc_id][PROC_CODE].append(DO_IO) + #print "proc %d, instr idx %d, instr cxt %s" % (proc_id, i, self.proc_info[proc_id][PROC_CODE][i]) + return + + #change to READY STATE, the current proc's state should be expected + #if pid==-1, then pid=self.curr_proc + def move_to_ready(self, expected, pid=-1): + #YOUR CODE + return + + #change to RUNNING STATE, the current proc's state should be expected + def move_to_running(self, expected): + #YOUR CODE + return + + #change to DONE STATE, the current proc's state should be expected + def move_to_done(self, expected): + #YOUR CODE + return + + #choose next proc using FIFO/FCFS scheduling, If pid==-1, then pid=self.curr_proc + def next_proc(self, pid=-1): + #YOUR CODE + return + + def get_num_processes(self): + return len(self.proc_info) + + def get_num_instructions(self, pid): + return len(self.proc_info[pid][PROC_CODE]) + + def get_instruction(self, pid, index): + return self.proc_info[pid][PROC_CODE][index] + + def get_num_active(self): + num_active = 0 + for pid in range(len(self.proc_info)): + if self.proc_info[pid][PROC_STATE] != STATE_DONE: + num_active += 1 + return num_active + + def get_num_runnable(self): + num_active = 0 + for pid in range(len(self.proc_info)): + if self.proc_info[pid][PROC_STATE] == STATE_READY or \ + self.proc_info[pid][PROC_STATE] == STATE_RUNNING: + num_active += 1 + return num_active + + def get_ios_in_flight(self, current_time): + num_in_flight = 0 + for pid in range(len(self.proc_info)): + for t in self.io_finish_times[pid]: + if t > current_time: + num_in_flight += 1 + return num_in_flight + + + def space(self, num_columns): + for i in range(num_columns): + print '%10s' % ' ', + + def check_if_done(self): + if len(self.proc_info[self.curr_proc][PROC_CODE]) == 0: + if self.proc_info[self.curr_proc][PROC_STATE] == STATE_RUNNING: + self.move_to_done(STATE_RUNNING) + self.next_proc() + return + + def run(self): + clock_tick = 0 + + if len(self.proc_info) == 0: + return + + # track outstanding IOs, per process + self.io_finish_times = {} + for pid in range(len(self.proc_info)): + self.io_finish_times[pid] = [] + + # make first one active + self.curr_proc = 0 + self.move_to_running(STATE_READY) + + # OUTPUT: heade`[rs for each column + print '%s' % 'Time', + for pid in range(len(self.proc_info)): + print '%10s' % ('PID:%2d' % (pid)), + print '%10s' % 'CPU', + print '%10s' % 'IOs', + print '' + + # init statistics + io_busy = 0 + cpu_busy = 0 + + while self.get_num_active() > 0: + clock_tick += 1 + + # check for io finish + io_done = False + for pid in range(len(self.proc_info)): + if clock_tick in self.io_finish_times[pid]: + # if IO finished, the should do something for related process + #YOUR CODE + pass #YOU should delete this + + # if current proc is RUNNING and has an instruction, execute it + instruction_to_execute = '' + if self.proc_info[self.curr_proc][PROC_STATE] == STATE_RUNNING and \ + len(self.proc_info[self.curr_proc][PROC_CODE]) > 0: + #pop a instruction from proc_info[self.curr_proc][PROC_CODE]to instruction_to_execute + #YOUR CODE + pass #YOU should delete this + + # OUTPUT: print what everyone is up to + if io_done: + print '%3d*' % clock_tick, + else: + print '%3d ' % clock_tick, + for pid in range(len(self.proc_info)): + if pid == self.curr_proc and instruction_to_execute != '': + print '%10s' % ('RUN:'+instruction_to_execute), + else: + print '%10s' % (self.proc_info[pid][PROC_STATE]), + if instruction_to_execute == '': + print '%10s' % ' ', + else: + print '%10s' % 1, + num_outstanding = self.get_ios_in_flight(clock_tick) + if num_outstanding > 0: + print '%10s' % str(num_outstanding), + io_busy += 1 + else: + print '%10s' % ' ', + print '' + + # if this is an YIELD instruction, switch to ready state + # and add an io completion in the future + if instruction_to_execute == DO_YIELD: + #YOUR CODE + pass #YOU should delete this + # if this is an IO instruction, switch to waiting state + # and add an io completion in the future + elif instruction_to_execute == DO_IO: + #YOUR CODE + pass #YOU should delete this + + # ENDCASE: check if currently running thing is out of instructions + self.check_if_done() + return (cpu_busy, io_busy, clock_tick) + +# +# PARSE ARGUMENTS +# + +parser = OptionParser() +parser.add_option('-s', '--seed', default=0, help='the random seed', action='store', type='int', dest='seed') +parser.add_option('-l', '--processlist', default='', + help='a comma-separated list of processes to run, in the form X1:Y1:Z1,X2:Y2:Z2,... where X is the number of instructions that process should run, and Y/Z the chances (from 0 to 100) issue an YIELD/IO', + action='store', type='string', dest='process_list') +parser.add_option('-L', '--iolength', default=3, help='how long an IO takes', action='store', type='int', dest='io_length') +parser.add_option('-p', '--printstats', help='print statistics at end; only useful with -c flag (otherwise stats are not printed)', action='store_true', default=False, dest='print_stats') +(options, args) = parser.parse_args() + +random.seed(options.seed) + +process_switch_behavior = SCHED_SWITCH_ON_IO +io_done_behavior = IO_RUN_LATER +io_length=options.io_length + + +s = scheduler(process_switch_behavior, io_done_behavior, io_length) + +# example process description (10:100,10:100) +for p in options.process_list.split(','): + s.load(p) + +print 'Produce a trace of what would happen when you run these processes:' +for pid in range(s.get_num_processes()): + print 'Process %d' % pid + for inst in range(s.get_num_instructions(pid)): + print ' %s' % s.get_instruction(pid, inst) + print '' +print 'Important behaviors:' +print ' System will switch when', +if process_switch_behavior == SCHED_SWITCH_ON_IO: + print 'the current process is FINISHED or ISSUES AN YIELD or IO' +else: + print 'error in sched switch on iobehavior' + exit (-1) +print ' After IOs, the process issuing the IO will', +if io_done_behavior == IO_RUN_LATER: + print 'run LATER (when it is its turn)' +else: + print 'error in IO done behavior' + exit (-1) +print '' + +(cpu_busy, io_busy, clock_tick) = s.run() + +print '' +print 'Stats: Total Time %d' % clock_tick +print 'Stats: CPU Busy %d (%.2f%%)' % (cpu_busy, 100.0 * float(cpu_busy)/clock_tick) +print 'Stats: IO Busy %d (%.2f%%)' % (io_busy, 100.0 * float(io_busy)/clock_tick) +print '' \ No newline at end of file