Exercise 5, Problem 1: Doctor and patients in monitor
monitor Reception { cond in; cond out; cond check; cond gone; # to inform that the patient is really gone boolean reserved = true; procedure Cometoreception( ) { # code for a patient if (reserved) wait(in); # wait to get in else reserved = true; # mark reception room reserved go to the reception room signal(check); # tell the doctor examination by the doctor wait(out); # wait until allowed to leave leave the reception room; signal(gone); } procedure Examinepatient ( ) { # code for the doctor if !empty(in) signal(in); # call a patient in if there is somebody waiting else reserved = false; #if not then mark yourself free wait(check); # wait for a patient to arrive o examine a patient signal(out); # allow a patient to leave wait(gone); # waitfor the customer to really leave } } process Patient( )[i = 1 to n] { while (true) do what ever you do feel sick call Reception.Cometoreception( ); } } process Doctor( ) { while (true) call Reception.Examinepatient( ); }
Exercise 5, problem 2: Barbers in the monitor
b) Simple solution for one barber
process CUSTOMER[1 to N] { while (true) { let_your_hair_grow(); call Barber_Shop.get_haircut(); } } process BARBER { while (true) { call Barber_Shop.get_next_customer(); haircut(); call Barber_Shop.finished_cut(); } } The monitor from fig 5.10 ripped off to bare necessities: ======================================================= monitor Barber_Shop { int barber = 0; # chair and open variables are not needed cond barber_available; cond chair_occupied; cond door_open; cond customer_left; procedure get_haircut() { while (barber==0) wait(barber_available); barber = barber – 1; # chair = chair +1; signal(chair_occupied); # while(open ==0) wait(door_open); # open=open -1; signal(customer_left); } procedure get_next_customer() { barber = barber + 1; signal(barber_available); # while (chair ==0) wait(chair_occupied); # chair = chair -1; } procedure finished_cut() { # open = open +1; signal(door_open); # while (open > 0) wait(customer_left); } } # monitor Barber_Shop
c) Many barbers in the barbershop
process CUSTOMER[1 to M] { while (true) { let_your_hair_grow(); call Barber_Shop.get_haircut(); } } process BARBER[barber=1 to N] # This was changed { while (true) { call Barber_Shop.get_next_customer(barber); haircut(); call Barber_Shop.finished_cut(barber); } } monitor Barber_Shop { int n_free_barber = 0; # number of free barbers boolean free_chair[N]; # is the chair i free? int barber = 1; # identity of some free barber cond chair_occupied[N]; # wait until somebody sitting in the chair cond door_open[N]; # wait until haircut finished cond barber_available; # wait for free barber procedure get_haircut() { while (n_free_barber==0) wait(barber_available); while (! free_chair[barber]) barber = (barber + 1) % N; # find a free barber free_chair[barber] = false; # and reserve him n_free_barber--; signal(chair_occupied[barber]); # wakeup the sleeping barber wait(door_open[barber]); # wait until barbering finished } procedure get_next_customer(int barber) { n_free_barber++; # free barber free_chair[barber] = true; # free chair signal(barber_available); # inform the possibly waiting customers wait(chair_occupied[barber]); # wait for a customer to arrive } procedure finished_cut(int barber) { signal(door_open[barber]); # customer finished } } # monitor Barber_Shop
Exercise 5, problem 3: Checkpointing
chan ready_to_write(), writing_done(), proceed(); process P[0] # coordinator { while (true) { do_what_ever_you_do(); for [i = 1 to N] receive ready_to_write(); # checkpoint: wait for the others for [i = 1 to N] send proceed(); # let others proceed save_your_own_state_to_disk(); for [i = 1 to N] receive writing_done(); # wait until others have written for [i = 1 to N] send proceed(); # let others proceed } } process P[i = 1 to N] # the other processes { while (true) do { do_what_ever_you_do(); send ready_to_write(); # inform that you are ready to write receive proceed(); # wait for permission to proceed save_your_own_state_to_disk(); send writing_done(); # inform thar you are ready receive proceed(); # wait for permission to proceed } } Exercise 5, problem 4: Message passing at Korvatunturi: chan arrived (), # reindeers inform Rednose ready (), # Rednose informs Santa Santatoreindeers (char); # Santa communicates with reindeers process Reindeer[i=1 to N-1] { while (true) { wander around; arrive at Korvatunturi; send arrived (); receive Santatoreindeers [i](); # start fly around delivering presents; receive Santatoreindeers[i] (); # thanks } } process Rednose { # acts as coordinator while (true) { wander around with other reindeers; arrive at Korvatunturi; for [i=1 to N-1] receive(arrived); # wait until all N-1 have arrived send ready(); # inform Santa receive Santatoreindeers[0]; # wait for Santa to start fly around and deliver presents; receive Santatoreindeers[0]; # wait for Santa to give thanks } } process Santa { while (true) { do all kind of things; receive ready(); for [i=0 to N-1] send Santatoreindeers[i]; deliver presents; for [i=0 to N-1] send Santatoreindeers[i]; enjoy holiday season; } } Exercise 5, problem 5: Shared bank account server with message passing chan request (int custid, int amount, int type); chan reply[n] (types of results); process BankAccountServer { int custid; # customer number int amount; # amount of money for deposit or withdrawal int type; # type of request: withdrawal = 1, deposit = 0 int saldo = 0; # saldo of the account int n, front =0, rear = n-1, # size of the queue buffer, first in the queue, last in the buffer nbr = 0; # number of those waiting for withdrawal type queue [n, 2]; # queue for those waiting for withdrawal; qamount, qcustid while (true) { receive request (int custid, int amount, int type); if (type = = 0) { # deposit saldo = saldo + amount; # increase saldo send reply[custid] ('OK'); # send OK reply to the customer # check, if the next waiting request can be allocated while (saldo > queue [front].qamount) {# the first request in the queue saldo = saldo - queue [front].qamount; send reply[queue [front].qcustid] ('OK'); # send OK reply to the customer front = (front + 1)%n; # update the queue nbr --; } else { # withdrawal if (saldo > amount AND nbr = = 0) { # enough saldo and nobody waiting saldo = saldo -amount; # decrease saldo send reply[custid] ('OK'); # send OK reply to the customer } else { # put the request into the queue if (nbr < n) rear = (rear + 1) / n; { queue[rear].qcustid = custid; queue[rear].qamount = amount; nbr ++; } # the request is in the queue; it is assumed that it can be filled pretty soon # the customer is informed first when the there is enough money for the # withdrawal # it would be possible to send some warning here else # there is no more room in the queue send reply[custid] ('PROBLEMS'); # the customer should send the request enew } # end of withdrawal } end of while }end of BankAccountServer Exercise 5, problem 6: type req_kind = enum(READ, WRITE); chan IO_request (int clientID, req_kind oper, types of arguments); chan reply_to_read[M](types of arguments); chan reply_to_write[M](types of arguments); process DB_server]i=1 to N] # N server processes using same channel { # the first one takes the request int clientID; req_kind oper; variables for args; varibles for results; other local declarations; while (true) { receive IO_request(clientID, oper, args); # wait for request switch(oper) { case READ { RW_controller.request_read(); results=perform_read_operation_to_DB(args); RW_controller.release_read(); send reply_to_read[clientID](results); } case WRITE { RW_controller.request_write(); results=perform_write_operation_to_DB(args); RW_controller.release_write(); send reply_to_write[clientID](results); } } #end switch } } # end DB_server # Monitor that takes care of the mutual exclusion monitor RW_Controller # Andrews fig 5.5 (tai harj 5.1) { int nr=0, nw=0; cond oktoread, oktowrite; procedure request_read() { while (nw > 0) wait(oktoread); nr++; } procedure release_read() { nr--; if (nr==0) signal(oktowrite); } procedure request_write() { while (nr > 0 || nw > 0) wait(oktowrite); nw++; } procedure release_write() { nw--; signal(oktowrite); signal_all(oktoread); } }