Consider the C program (twoupdate) to demonstrate race condition. In this assignment, we will implement Peterson's algorithm to ensure mutual exclusion in the respective critical sections of the two processes, and thereby eliminate the race condition.
In order to implement Peterson's Algorithm, the two processes should share a boolean array calledflagwith two components and an integer variable called turn, all initialized suitably. We will create and access these shared variables using UNIX system calls relating to shared memory – shmget, shmat, shmdtandshmctl. The necessary include files and function prototypes for these system calls are as follows:
#include
#include
#include
int shmget(key_t key, size_t size, int shmflag);
void *shmat(int shmid, const void *shmaddr, int shmflag);
int *shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
Spool out the man files for these system calls and study them carefully.
First create an include file called sharevar.h as shown. The file sharevar.h contains necessary constant and type definitions to create the shared memory segment for this assignment. In order to create a shared memory segment, the processes must first agree on a unique key.
Study the attached listing of the files named sharevar.h and twoupdate.c, which show the use of these system calls. There is no need to modify twoupdate.c. But you have to suitably modify process0.c and process1.c. Both processes should make shmget, shmat and shmdt system calls in their respective main functions. Further, the lockfile and unlockfile functions in these two processes should implement the Peterson's algorithm. But, note that the shmctl to remove the shared memory segment should be called only by twoupdate.c. Be sure to create the file data with an integer 0 in it before you run the program every time. If the program works correctly, the final value left in the file should be the same every time the program is run, as long as the count for update is not changed.
Create a script output with a listing of all source files – sharevar.h, twoupdate.c, process0.c, and process1.c. Show the output of four or five runs of twoupdate for small values of count, say below 30. If you use a C Shell script file for repeated testing, provide a listing of the same. Exit from script.
Warning: Do not edit the source file inside the script. The control characters will create a messy script output. Edit out the print statements in both processes and recompile them.
Warning: The program runs for this part may take several minutes. Create a new script file with three runs of twoupdate for count = 1000, 5000, and 10000, as further proof of proper file access coordination between the two processes. Cleary we do not want lengthy printouts. Hence, we have edited out the print statements inside process0.c and process1.c.
BELOW IS THE CODE for twoupdate.c, sharevar.h, process0.c (process1.c is just a copy).
//twoupdate.c
#include
#include
#include
#include
#include
#include "sharevar.h"
/*Variables needed for shared memory segment*/
/*Set up as external variables for programming ease*/
int shmid;
syncvars *shmptr;
int main (int argc, char *argv[])
{
FILE *fp; int initial, final; int status;
/*Check for command line arguments*/
if (argc != 3)
{
printf("usage: %s filename count\n", argv[0]);
return -1;
}
/*Determine initial value in file before update*/
fp = fopen(argv[1], "r");
fscanf(fp, "%d", &initial);
fclose(fp);
/*Create a shared memory segment for the given key*/
/*provided one does not exist already*/
shmid = shmget(SHMKEY, sizeof(syncvars), PERMS | IPC_CREAT);
/*Attach the shared memory segment to this process*/
shmptr = (syncvars *) shmat(shmid, (void *) NULL, 0);
/*Initialize the shared memory for Peterson's Algorithm*/
shmptr->flag[0] = FALSE;
shmptr->flag[1] = FALSE;
shmptr->turn = 0;
/*Launch the two processes*/
if (fork() == 0) {
execlp("process0", "process0", argv[1], argv[2], (char *) NULL);
}
if (fork() == 0) {
execlp("process1", "process1", argv[1], argv[2], (char *) NULL);
}
/*Wait for the two processes to terminate*/
wait(&status); wait(&status);
/*Detach the shared memory segment*/
shmdt((void *) shmptr);
/*Remove the shared memory segment*/
shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL);
/*Determine final value in file after update*/
fp = fopen(argv[1], "r");
fscanf(fp, "%d", &final);
fclose(fp);
/*Print value in file before and after two-process update*/
printf("\n\n****Initial value in file %d\n\n", initial);
printf("****Final value in file %d\n\n", final);
return 0;
}
//sharevar.h
/*Constant and type definitions needed for creating the*/
/*shared memory segment to implement Peterson's Algorithm*/
#define PERMS 0666 /*Access rights*/
#define SHMKEY ((key_t) 800123456) /*Use your Banner ID#*/
#define FALSE 0
#define TRUE 1
typedef struct {
int flag[2];
int turn;
} syncvars;
//process0.c
#include
#include
#include
#include
#include
#include
#include
void waste_time(void);
#define MAXSIZE 80
int main(int argc, char *argv[])
{
/*Uses UNIX input/output system calls for file access */
/*for no reason other than educational value*/
/*function prototype for file access*/
void fileaccess (int fd, int count);
int fd, count;
/*Check for command line arguments*/
if (argc != 3) {
printf("usage: process0 filename count\n");
return -1;
}
count = atoi(argv[2]);
/*Open file and update*/
fd = open(argv[1], O_RDWR, 0);
fileaccess(fd, count);
return 0;
}
/*Access the file with the given fd and increment*/
/*the only integer value in that file count times*/
void fileaccess(int fd, int count)
{
/*function prototypes for locking and unlocking file*/
void lockfile (void);
void unlockfile (void);
int i, k, value; pid_t pid;
char buff[MAXSIZE];
/*Initialize the seed for random number generator*/
srand(time(NULL));
pid = getpid();
for (i = 0; i < count; i++)
{
lockfile(); /*lock the file*/
/*Read value from file*/
lseek(fd, 0L, 0);
k = read(fd, buff, MAXSIZE); buff[k] = '\0';
sscanf(buff, "%d\n", &value);
/*Increment value*/
value++;
/*Slow down*/
waste_time();
/*Write back into file*/
sprintf(buff, "%10d\n", value);
lseek(fd, 0L, 0);
k = strlen(buff); write(fd, buff, k);
printf("pid = %d, new value = %d\n", pid, value);
unlockfile(); /*unlock the file*/
}
}
void waste_time (void)
{
/*Slow down; waste time in loop*/
int randNum = rand() % 100000; int x;
for (x = 0; x < randNum; x++) {
}
}
void lockfile(void)
{
}
void unlockfile(void)
{
}
Thanks so much for your help!!
process1.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "sharevar.h"
#define MAXSIZE 80
void fileaccess(int fd, int count);
int shmid;
syncvars *shmptr;
int main(int argc, char *argv[])
{
int fd, count;
if(argc != 3){
printf("usage: process1 filename
count\n");
return -1;
}
count = atoi(argv[2]);
fd = open(argv[1], O_RDWR, 0);
fileaccess(fd, count);
return 0;
}
void fileaccess(int fd, int count){
void lockfile (void);
void unlockfile (void);
int i, k, value; pid_t pid;
char buff[MAXSIZE];
shmid = shmget(SHMKEY, sizeof(syncvars), PERMS |
IPC_CREAT);
shmptr = (syncvars *) shmat(shmid, (void *) NULL,
0);
pid = getpid();
for(i = 0; i < count; i++){
lockfile();
while(shmptr->turn == 0
&& shmptr->flag[0] == TRUE );
//critical stuff
lseek(fd, 0L, 0);
k = read(fd, buff, MAXSIZE); buff[k]
= '\0';
sscanf(buff, "%d\n",
&value);
value++;
sprintf(buff, "%10d\n",
value);
lseek(fd, 0l, 0);
k = strlen(buff); write(fd, buff,
k);
printf("pid = %d, new value = %d\n",
pid, value);
unlockfile();
}
}
void lockfile (void){
shmptr->flag[1] = TRUE;
shmptr->turn = 0;
}
void unlockfile (void){
shmptr->flag[1] = FALSE;
}
twoupdate.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "sharevar.h"
/*Variables needed for shared memory segment*/
/*Set up as external variables for programming ease*/
int shmid;
syncvars *shmptr;
int main(int argc, char *argv[]){
FILE *fp; int initial, final; int status;
/*Check for command line arguments*/
if(argc != 3){
printf("usage: %s filename
count\n", argv[0]);
return -1;
}
/*Deterime initial value in the file before
update*/
fp = fopen(argv[1], "r");
fscanf(fp, "%d", &initial);
fclose(fp);
/*Create a shared memory segmenmt for the given
key*/
/*provided one does not exist already*/
shmid = shmget(SHMKEY, sizeof(syncvars), PERMS |
IPC_CREAT);
/*Attach the shared memory segment to this
process.*/
shmptr = (syncvars *) shmat(shmid, (void *) NULL,
0);
/*Initialize the shared memory for Peterson's
Algorithm*/
shmptr->flag[0] = FALSE;
shmptr->flag[1] = FALSE;
shmptr->turn = 0;
/*Launch the two processes*/
if(fork() == 0){
execlp("process0", "process0",
argv[1], argv[2], (char *) NULL);
}
if(fork() == 0){
execlp("process1", "process1",
argv[1], argv[2], (char *) NULL);
}
/*Wait for the two processes to terminate*/
wait(&status); wait(&status);
/*Detatch the shared memory segment*/
shmdt((void *) shmptr);
/*Remove the shared memory segment*/
shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL);
/*Determine the file value in file after
update*/
fp = fopen(argv[1], "r");
fscanf(fp, "%d", &final);
fclose(fp);
/*Print value in file before and after two-process
update*/
printf("\n\n****Initial value in file %d\n\n",
initial);
printf("****Final value in file %d\n\n", final);
return 0;
}
sharevar.h
/*Constant and type definitions needed for creating the*/
/*shared memory segment to implement Peterson's Algorithm*/
#define PERMS 0666 /*Acess rights*/
#define SHMKEY ((key_t) 800650198)
#define FALSE 0
#define TRUE 1
typedef struct {
int flag[2];
int turn;
} syncvars;
Get Answers For Free
Most questions answered within 1 hours.