A shared memory segment holds a STORE with at least 10 [STORE_SIZE] pairs (STORE_ID, STORE_ELEM); you choose an initial list of pairs. STORE_ID and STORE_ELEM are strings of, respectively, 9 [STORE_ID_SIZE] and 8 [STORE_ELEM_SIZE] characters. STORE_ID represents a social security number [for example "155243352"] and STORE_ELEM represents the corresponding balance [for example " 4563750"].
The RAND_PROC processes execute the functions STORE_UPDATE and STORE_READ on the STORE. These are slow operations [assume that they involve IO], taking one second.
function STORE_UPDATE (WHO : STORE_ID;
WHAT : STORE_ELEM) return INTEGER;
{It updates the value of WHO to be WHAT. It returns 0 iff successful}
{Note that WHO denotes the pair with first element equal to WHO.}
function STORE_READ (WHO : STORE_ID;
var WHAT : STORE_ELEM) return INTEGER;
{It retrieves the value of WHO and stores it in WHAT.
It returns 0 iff successful}
HMW_MAIN executes the STORE_BALANCE function on the STORE. It is a slow operation.
function STORE_BALANCE return INTEGER;
{It returns the sum of the STORE_ELEMs (seen as integers) in the STORE}
RAND_PROC1 and RAND_PROC2 have the same form [but use different seeds for the random number generator]. RAND_PROC1 and RAND_PROC2 should respond within callbacks to the signals from HMW_MAIN.
RAND_PROCi:
initialization;
Establish the signal handlers. For example:
signal(SIGUSR1, dostats);
signal(SIGUSR2, doexit);
[of course you have to write the functions dostats, doexit]
segmentid = ObtainSegment(size of STORE);
Attach to segmentid and set STOREPTR to value returned by Attach;
[All access to STORE is done through STOREPTR]
loop
Select at random STORE_READ or STORE_UPDATE
[in both operations the STORE_ID should be selected
at random from a list maintained at RAND_PROCi; in the
STORE_UPDATE operation STORE_ELEM should be created using
a random number generator] and execute the corresponding
function and log the call and result;
wait some random time;
end loop
conclusion;
function dostats(int s): print out statistics of RAND_PROCi;
function doexit(int s): detach from shared memory segment and exit;
function ObtainSegment(int StoreSize)
begin
Open (creating if necessary) the (initially empty) file SHMIDFILE
for reading and writing;
Obtain an exclusive lock on SHMIDFILE;
if ISEMPTY(SHMIDFILE) then { shared memory segment not created yet }
begin
Invoke shmget as
shmid := shmget(IPC_PRIVATE,StoreSize,SHM_R|SHM_W);
Invoke shmat to attach segment to address space as
StartAddressOfSTORE := shmat(shmid,0,0);
Initialize STORE;
Write shmid into SHMIDFILE;
end
else { shared memory segment already created }
begin
Read shmid from SHMIDFILE;
Invoke shmat to attach segment to addres space as
StartAddressOfSTORE := shmat(shmid,0,0);
end
Release lock on SHMIDFILE;
end { ObtainSegment }
function STORE_READ (storeid id, storeelem *elem) return integer:
use filerwreadlock to lock the id entry in the store;
sleep(1);
set elem to the value of the elem field in the id entry of the store;
use filerwunlock to unlock the id entry of the store
write appropriate information to log;
update statistics;
return appropriate result code;
function STORE_UPDATE(storeid id, storeelem elem) return integer:
use filerwwritelock to lock the id entry in the store;
sleep(1);
set the elem field in the id entry of the store to elem;
use filerwunlock to unlock the id entry of the store
write appropriate information to log;
update statistics;
return appropriate result code;
HMW_MAIN
HMW_MAIN, after starting the other processes, in a loop prompts the users
to ask if they want to see statistical information from RAND_PROC1 and
RAND_PROC2.
HMW_MAIN:
pid_t pids[3];
initialization;
Create filelocks fl;
if ((pids[0]=fork())<0) {perror("fork"); exit(1);}
else if (pids[1]==0) RAND_PROC1();
if ((pids[2]=fork())<0) {perror("fork"); exit(1);}
else if (pids[2]==0) RAND_PROC2();
segmentid = ObtainLateSegment();
Attach to segmentid and set STOREPTR to value returned by Attach;
[All access to STORE is done through STOREPTR]
loop
Prompt the User;
If the answer is "1" then
send a signal to RAND_PROC1 [RAND_PROC1
will write to the screen the number of Read and
Update messages that it has executed [different
numbers represents the Reads started and completed,
and the Updates started and completed]].
else if the answer is "2", then
the same is done with RAND_PROC2
else if the answer is "3", then
Call STORE_BALANCE and print out result
else
send signals to RAND_PROC1, RAND_PROC2
requesting that they terminate;
wait that they all exit and exit the loop;
end loop
Delete the shared memory segment;
Delete the filelocks;
Conclusion;
function ObtainLateSegment(void) return segmentid:
repeat
open the agreed "shmidfile.dat" file;
if it exists, read from it the segmentid
else sleep(1) and repeatloop
function STORE_BALANCE():
let sum be an integer initialized to 0;
filelongrwlock(fl);
sleep(1);
for each index i of a storepair in the store
add to sum the integer value of storeptr[i]->elem;
filelongrwunlock(fl);
return sum;
STOREPTR
This code shows how we may use the STORE through a pointer. Note that
I have used malloc instead of shmat so as to simplify the example.
Also STOREIDSIZE is 10 and STORELEMSIZE is 9 so as to allow space for null
terminator of the string.
#define STORESIZE 10
#define STOREIDSIZE 10
#define STORELEMSIZE 9
typedef char storeid[STOREIDSIZE];
typedef char storeelem[STORELEMSIZE];
typedef struct {
storeid id;
storeelem elem;} storepair;
typedef storepair storetype[STORESIZE];
storetype * storeptr;
void storeinit();
int main () {
storeptr = (storetype *) malloc(sizeof(storetype));
storeinit();
printf ("id of second entry: %s\n", storeptr[1]->id);
exit(0);
}
void storeinit(){
strcpy(storeptr[0]->id, "123456789");
strcpy(storeptr[1]->id, "234567891");
strcpy(storeptr[2]->id, "345678912");
strcpy(storeptr[3]->id, "456789123");
strcpy(storeptr[4]->id, "567891234");
strcpy(storeptr[5]->id, "678912345");
strcpy(storeptr[6]->id, "789123456");
strcpy(storeptr[7]->id, "891234567");
strcpy(storeptr[8]->id, "912345678");
strcpy(storeptr[9]->id, "012345678");
strcpy(storeptr[0]->elem, " 123451");
strcpy(storeptr[1]->elem, " 123452");
strcpy(storeptr[2]->elem, " 123453");
strcpy(storeptr[3]->elem, " 123454");
strcpy(storeptr[4]->elem, " 123455");
strcpy(storeptr[5]->elem, " 123456");
strcpy(storeptr[6]->elem, " 123457");
strcpy(storeptr[7]->elem, " 123458");
strcpy(storeptr[8]->elem, " 123459");
strcpy(storeptr[9]->elem, " 123450");
}
ingargiola@cis.temple.edu