CMPS 352 Operating Systems
Spring 2000
Programming Assignment #4
Due Date: May 11, 1999
The last assignment is to add process synchronization using semaphores to the producer and consumer problem you have designed in assignment 3.
1. Identify all the segments of code that should be executed mutually exclusively and then determine how to use semaphores to guarantee mutual exclusion. A design description is required and must be included as a comment at the beginning of the consumer program. It should be written in pseudo-code with emphasis on the usage of shared memory segments and semaphores. It should not be longer than a single-spaced page.
2. Insert wait and signal operations into proper places in your programs. The segment of code between a pair of wait and signal operations should be as short as possible in terms of execution time. That is because, when one process has locked the semaphore, other process what needs the semaphore must wait until the semaphore is released. The longer of the protected segment, the longer the other process may wait. Thus, it reduces the degree of concurrency.
Name your source files as “asgn4_userID_con.cpp” and “asgn4_userID_prod.cpp” for the consumer and producer, respectively. Replace userID with your real userID of your CS account. Do not use capital letters in the file name.
To submit your assignment, email me () and ATTACH your source file to the email. The subject of your email should appear like “CMPS352 Assignment 4 – Your first name then last name”. For example, if I submitted my program, the subject would appear as “CMPS352 Assignment 4 – Yaodong Bi”.
NOTE: The due date of this assignment is Thursday, May 11, 2000. Any submission after Friday, May 12, 2000 will NOT be graded.
/*=========================== conSem.C ============================*
Program Name: conSem.cpp
Class: Operating Systems, Fall 1998
Author: Yaodong Bi
Date: 12/1/98
Enviornment: Gnat (Unix) C++
Compilation: gcc -o conSem conSem.cpp
Usage: conSem
Description: This sample program shows how to use semaphores in to
synchronize the Producer and Consumer problem.
To find the statements related to semaphores, search for
"SEMAPHORE".
*=======================================================================*/
//#define SHARED_DEBUG
#define SEMAPHORE_DEBUG
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include "shared.h"
#include "semaphore.h" // SEMAPHORE
// structure of request nodes which are shared.
struct NODE {
int reqId;
int num;
struct NODE *prev;
struct NODE *next;
};
typedef struct NODE Node;
typedef Node *NodePtr;
struct INFO {
NodePtr dataHead;
NodePtr dataTail;
NodePtr freeHead;
NodePtr freeTail;
};
typedef struct INFO Info;
typedef Info *InfoPtr;
const int size = 5;
main()
{
NodePtr tmpPtr = NULL;
// Declare two shared memory segments
// bufptr points to a shared segment with a sequence of
// of nodes with request node type (Node).
// head points to a structure for the request queue
// and the available empty nodes.
Shared<Node> bufPtr(size, 800);
Shared<Info> head(1, 801);
Semaphore mutex(800, 1); // SEMAPHORE
Semaphore emptySlots(801, 5); // SEMAPHORE
Semaphore fullSlots(802,0); // SEMAPHORE
// When a SIGALRM is received, wakeup will be called.
// when a ctrl+c is received, cleanup is called.
signal(SIGALRM, wakeup);
signal(SIGINT, cleanup);
// Initialize the request queue and free node list pointers.
head->dataHead = head->dataTail = NULL;
head->freeHead = head->freeTail = NULL;
// Initialize the free node list
tmpPtr = bufPtr;
for (int i=0; i<size; i++) {
append(&(head->freeHead), &(head->freeTail), tmpPtr);
tmpPtr++;
}
for (;;) { // infinite loop in C
// Wait until a request comes.
fullSlots.wait(); // SEMAPHORE
mutex.wait(); // SEMAPHORE
printNode(head->dataHead);
// remove the request and put it into free node list
tmpPtr = remove(&(head->dataHead), &(head->dataTail));
append(&(head->freeHead), &(head->freeTail), tmpPtr);
mutex.signal(); // SEMAPHORE
emptySlots.signal(); // SEMAPHORE
delay(2);
}
}
/*=========================== prodSem.C ============================*
Program Name: prodSem.cpp
Class: Operating Systems, Fall 1998
Author: Yaodong Bi
Date: 12/1/98
Enviornment: Gnat (Unix) C++
Compilation: gcc -o prodSem prodSem.cpp
Usage: prodSem
Description: This sample program shows how to use semaphores in to
synchronize the Producer and Consumer problem.
To find the statements related to semaphores, search for
"SEMAPHORE".
*=======================================================================*/
#include <stdio.h>
#include "Shared.h"
#include "Semaphore.h" //SEMAPHORE
#include <signal.h>
struct NODE {
int reqId;
int num;
struct NODE *prev;
struct NODE *next;
};
typedef struct NODE Node;
typedef Node *NodePtr;
struct INFO {
NodePtr dataHead;
NodePtr dataTail;
NodePtr freeHead;
NodePtr freeTail;
};
typedef struct INFO Info;
typedef Info *InfoPtr;
void printNode(NodePtr);
NodePtr remove(NodePtr*, NodePtr*);
void append(NodePtr*, NodePtr*, NodePtr);
const int size = 5;
main()
{
// Declare two shared memory segments
Shared<Node> bufPtr(5, 800);
Shared<Info> head(1,801);
Semaphore mutex(800, 1); //SEMAPHORE
Semaphore emptySlots(801, 5); //SEMAPHORE
Semaphore fullSlots(802, 0); //SEMAPHORE
NodePtr tmpPtr = NULL;
int reqId = 0;
int number = 0;
while (scanf("%d", &number) != EOF) {
emptySlots.wait(); //SEMAPHORE
mutex.wait(); //SEMAPHORE
tmpPtr = remove(&(head->freeHead), &(head->freeTail));
tmpPtr->reqId = reqId++;
tmpPtr->num = number;
append(&(head->dataHead), &(head->dataTail), tmpPtr);
mutex.signal(); //SEMAPHORE
fullSlots.signal(); //SEMAPHORE
printNode(tmpPtr);
}
}
// Signal handler for SIGINT (ctrl+c) signal.
void cleanup()
{
// Declare the two shared memory segments.
Shared<Node> bufPtr(5, 800);
Shared<Info> head(1,801);
Semaphore mutex(800, 1); // SEMAPHORE
Semaphore emptySlots(801, 5); // SEMAPHORE
Semaphore fullSlots(802, 0); // SEMAPHORE
// Call the remove function to remove the shared
// memory segment from the system.
bufPtr.remove();
head.remove();
mutex.remove(); // SEMAPHORE
emptySlots.remove(); // SEMAPHORE
fullSlots.remove(); // SEMAPHORE
// Call exit to terminate the calling process.
// if exit is not called here, the calling process
// would continue from where it was interrupted.
exit(1);
}
void printNode(NodePtr nodePtr)
{
printf("R-ID = %d Number = %d\n", nodePtr->reqId, nodePtr->num);
}