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);

}