/******* ** ** To compile: mc resource1.m -o resource1 -lm ** *******/ /************************************************************************ ** ** Resource Manager Simulation ** ** This program simulates a physical system consisting of one CPU ** server, one Disk server, and several Jobs. Jobs requests service ** from the CPU and the Disk. Both CPU and Disk servers serves the ** Jobs in FIFO order. ** ** The program use the following entities: ** (1) dirver: initiates the simulation ** (2) source: initiates job entities ** (3) cpu: models the cpu server ** (4) diskmanager: models the disk manager to assure ** mutual exclusion among the jobs ** (5) job: simulates a job instance ** ************************************************************************/ #include "maisie.h" #include #include #define MAXTIME 5000 /* Maximum simulation time */ #define CPU_MEAN 10 /* Mean CPU service time */ #define DISK_MEAN 10 /* Mean Disk service time */ #define ARRIVAL 0.1 /* Job arrival rate */ int Job_wait_t = 0; /* For statistics collecting */ int Job_no =0; message end{} dummy_end; /* End of simulation from driver */ /******* ** ** DISKMANAGER: (1) Accepts request message from jobs only if the disk ** is not currently occupied by other jobs. ** (2) or accepts the release message only if the sender ** is the one using the Disk. ** *******/ entity diskmanager{} { message req { ename id;} oldreq; /* Request message from jobs */ message release { ename id;} dummy_relaease;/* Release message from jobs */ int busy; /* == 1, if Disk is occupied */ int start, end, i, total; /* Statistics clooecting */ busy = 0; for( start = end = total = i=0;;) { wait until { mtype(req) st(!busy) { oldreq = msg.req; busy = 1; i++; start = ctf(sclock()); invoke oldreq.id with ack{}; } /* Accepts the release only if */ or mtype(release) /* the sender is using the DISK */ st(ename_cmp(oldreq.id,msg.release.id)) { busy = 0; end = ctf(sclock()); total += end - start; } or mtype(end) st (!busy) break; /* End of simulation */ } } end = ctf(sclock()); printf("Disk:\tserves %d jobs\tutilization %f\n", i, (float)(total)/(float)(end)); } /*********** ** ** CPU: accepts requests from jobs. The service time is assumed to ** have exponential distribution with mean equals to the input ** variable: mean. ** ***********/ entity cpu { mean } int mean; { message req { ename id;} job; int i, t, start, end, t_wait; for(i= t_wait = 0;;i++) { start = ctf(sclock()); wait until { mtype(req) { end = ctf(sclock()); t_wait += end-start; job = msg.req; wait expon(mean) until { mtype(timeout); or mtype(end) break; } invoke job.id with finish{}; } or mtype(end) break; } } end = ctf(sclock()); printf("CPU:\tserves %d jobs\tutilization %f\n", i,(float)(end-t_wait)/(float)end); } /********** ** ** JOB: Requests service from the CPU, requests for the access ** privilege from the diskmanager, and the release the privilege. ** The disk accessing time is assumed to have exponential ** distribution with mean equals to the input variable: dmean. ** **********/ entity job{ cpu, disk, dmean } ename disk, cpu; int dmean; { message ack { } dummy_ack; message finish{} dummy_finish; int i, t,end,start, t_wait, tid; invoke cpu with req {self}; wait until mtype(finish); invoke disk with req {self}; start = ctf(sclock()); wait until mtype(ack); end = ctf(sclock()); Job_wait_t += (t_wait = end - start); Job_no++; end = start + (t = expon(dmean)); wait t until mtype(timeout); invoke disk with release { self}; } /********* ** ** SOURCE: Initiates jobs with arrival rate equals to the input ** variables: arrival. ** *********/ entity source { cpu, disk, arrival, dmean } ename cpu, disk; float arrival; int dmean; { for(;;) wait expon((int)(1/arrival)) until { mtype(timeout) new job { cpu, disk, dmean}; or mtype(end) break; } printf("Job:\taverage waiting time\t%f\n",(float)Job_wait_t/(float)Job_no); } /********** ** ** DRIVER: Start the simulation. ** **********/ entity driver{} { ename disk, cpu, source; disk = new diskmanager { }; cpu = new cpu { CPU_MEAN}; source = new source { cpu, disk, (float)ARRIVAL, DISK_MEAN }; wait MAXTIME until mtype(timeout); invoke cpu with end{}; invoke disk with end{}; invoke source with end{}; } /********** ** ** EXPON(): Returns a value with exponential distribution. ** **********/ int expon(mean) int mean; { double a; a =(double)((double)(rand()%MAXINT)/(double)MAXINT); return((int)(-1*log(a)*mean+1)); }