/******* ** ** To compile: mc resource2.m -o resource2 ** ** Note: when compiling with -DTRACE flag, a more detailed ** execution trace will output to the terminal ** *******/ /************************************************************************ ** ** Resource Manager Simulation ** ** This program simulates the behavior of a resource manager that ** controls two types of resources: printers and channels. ** Initially, MAXPRINTER units of printers and MAXCHANNELS channels ** are assigned to the manager. The manager accepts a request for printers ** only when there are available printers. For channels requests, ** the manager grants a channel only when there are matching requests ** for 'send' and 'recv' channels and the channel is not in use. ** Similarly, matching channel releases are required to free a channel. ** ** Entities: ** (1) manger: controls the resources according the above rule ** (2) print_job: jobs requesting for printers ** (3) channel_job: jobs requesting for channels ** (4) driver: create MAXJOB of print_job and MAXJOB of channel_job ** ** Note: This program demonstrates the use of compound_resume ** stamtements. ** *************************************************************************/ #include #include "maisie.h" #define MAXJOB 10 #define MAXCHANNELS 4 #define MAXPRINTER 10 entity manager{} { message chnls { ename hisid; int cno; int myno; } mvars; message chnlr { ename hisid; int cno; int myno; } mvarr; message relcs { int cno; int myno; } relcs; message relcr { int cno; int myno; } relcr; message printer { ename hisid; int count; } printer; message prelc { int count; } prelc; void print_relc(), print_prelc(), print_alloc(), print_printer(); int cfree[MAXCHANNELS], cno; int units = MAXPRINTER; for (cno=0; cno < MAXCHANNELS; cno++) cfree[cno] = 1; for(;;) { wait until { printer=mtype(printer) min count st ((msg.printer.count) < units) { units -= printer.count; invoke printer.hisid with printer { printer.count }; #ifdef TRACE print_printer(); #endif } or mvars=mtype(chnls) st(cfree[msg.chnls.cno]) and mvarr=mtype(chnlr) st(msg.chnlr.cno == mvars.cno) { cfree[mvars.cno] = 0; invoke mvars.hisid with alloc{mvarr.hisid, mvars.cno}; invoke mvarr.hisid with alloc{mvars.hisid, mvars.cno}; print_alloc(&mvars); } or relcs=mtype(relcs) and relcr=mtype(relcr) st (relcs.cno==msg.relcr.cno) { cfree[msg.relcr.cno] = 1; print_relc(&relcr); } or prelc=mtype(prelc) { units += prelc.count; #ifdef TRACE print_prelc(&prelc); #endif } } } } /********************************* *** *** Job requesting for printers *** *********************************/ entity print_job {myno,manager} int myno; ename manager; { message printer { int pno; } printer; void print_request(),print_alloc(), print_release(); int units; hold(rand()%100); /* Simulation!! */ units = rand()%MAXPRINTER/3+1; /* How many units do I need? */ #ifdef TRACE print_request(); #endif invoke manager with printer { self, units}; wait until printer=mtype(printer); #ifdef TRACE print_alloc(); #endif hold(rand()%100); #ifdef TRACE print_release(); #endif invoke manager with prelc { units }; } /********************************* *** *** Job requesting for channels *** *********************************/ entity channel_job{myno,manager} int myno; ename manager; { message alloc { ename partner; int cno; } alloc; message done dummy_done; int cno; void print_alloc(), print_request(), print_release(); hold(rand()%100); /* Simulation !! */ /*** *** Do I request for send or recv channel? ***/ cno = (myno/2)%MAXCHANNELS; if(myno%2) { #ifdef TRACE print_request("send"); #endif invoke manager with chnls { self, cno, myno }; } else { #ifdef TRACE print_request("recv"); #endif invoke manager with chnlr { self, cno, myno }; } /*** *** Waiting for manager to grant the channel ***/ wait until alloc=mtype(alloc); #ifdef TRACE print_alloc(&alloc); #endif /*** *** Simulate using the channel ***/ hold(rand()%101); /*** *** Release channel ***/ if(myno%2) invoke manager with relcs{alloc.cno,myno}; else invoke manager with relcr{alloc.cno,myno}; } entity driver {argc,argv} int argc; char **argv; { ename manager; int i,n=MAXJOB; if(argc >= 2) { n=atoi(argv[1]); if(n>MAXJOB) n = MAXJOB; } manager=new manager {}; for(i=0; i< n; i++) { new print_job {i,manager}; } for(; i< 3*n; i++) { new channel_job {i,manager}; } } /***************************** ** ** Function associations ** *****************************/ /*** *** Functions associated with the entity Manager ***/ void manager::print_relc() { printf("Manger got release for channel %d from (%d %d) at simulation time %d\n", relcr.cno,relcs.myno,relcr.myno,sclock()); } void manager::print_prelc(tmsg) message prelc *tmsg; { printf("Manger got release for %d printers at simulation time %d\n", tmsg->count,sclock()); } void manager::print_printer() { printf("Manger got request for %d units of printers at simulation time %d\n", printer.count,sclock()); } void manager::print_alloc(tmsg) message chnls *tmsg; { printf("Manger allocates channel %d to (%d %d) at simulation time %d\n", tmsg->cno,mvars.myno,mvarr.myno,sclock()); } /*** *** Functions associated with the entity print_job ***/ void print_job::print_request() { printf("Job %d requests %d printers at simulation time %d\n", myno, units ,sclock()); } void print_job::print_alloc() { printf("Job %d got %d units of printers at simulation time %d\n", myno, units ,sclock()); } void print_job::print_release() { printf("Job %d releases %d units of printers at %d\n",myno, units ,sclock()); } /*** *** Functions associated with the entity channel_job ***/ void channel_job::print_request(ch) char *ch; { printf("Job %d request %s channel %d at simulation time %d\n", myno,ch,cno,sclock()); } void channel_job::print_alloc(tmsg) message alloc *tmsg; { printf("Job %d got channel %d at simulation time %d\n", myno, tmsg->cno,sclock()); } void channel_job::print_release() { printf("Job %d release allocated channel %d at simulation time %d\n", myno,cno,sclock()); }