CS-384 Operating
Systems
Lab 2
Semaphores, Locks,
and Condition Variables
Date: December
4, 2001
Due: December
18, 2001
A special case of the Producers/Consumers problem, called the “Bounded Buffer” problem is described both in the textbook and the online notes from class (Chapter 7 in Silberschatz, with background material in Chapters 4 & 5). The goal of this second assignment is to implement your own solution to the Bounded Buffer problem using the process synchronization primitives available in the Unix/Linux system (notably: Semaphores, Locks, and Condition Variables). This solution consists of one producer and one consumer thread. Generate adequate output from your multi-threaded program, so that it is apparent that the producer thread blocks on a full buffer and the consumer thread blocks on an empty one so that no “collisions” occur between the producer or consumer threads on the same item in the buffer.
The following code is provided as an example of POSIX threads and locks (mutex’s). It does not properly solve the bounded buffer problem, because the producer and consumer require further coordination. Add semaphores to this program so that proper synchronization is demonstrated between the threads.
For more information on semaphores, run: man –k semaphores on a Unix/Linux system.
/* File 1: The buffer definitions */
#include <pthread.h>
#define BUFSIZE 8
static int buffer[BUFSIZE];
static int bufin = 0;
static int bufout = 0;
static pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER;
/* Get the next item from
buffer and put it in *itemp. */
void get_item(int *itemp)
{
pthread_mutex_lock(&buffer_lock);
*itemp = buffer[bufout];
bufout = (bufout + 1) % BUFSIZE;
pthread_mutex_unlock(&buffer_lock);
return;
}
/* Put item into buffer at position bufin and update bufin.
*/
void put_item(int item)
{
pthread_mutex_lock(&buffer_lock);
buffer[bufin] = item;
bufin = (bufin + 1) % BUFSIZE;
pthread_mutex_unlock(&buffer_lock);
return;
}
/* File 2: The producer and consumer threads */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define SUMSIZE 100
int sum = 0;
void put_item(int);
void get_item(int *);
void * producer(void * arg) //
producers execute this
{
int i;
for (i = 1; i <= SUMSIZE; i++)
put_item(i*i);
return NULL;
}
void * consumer(void * arg) //
consumers execute this
{
int i, myitem;
for (i = 1; i <= SUMSIZE; i++) {
get_item(&myitem);
sum += myitem;
}
return NULL;
}
int main(void) // the driver program
{
pthread_t prodtid;
pthread_t constid;
int i, total;
/* check value */
total = 0;
for (i = 1; i <= SUMSIZE; i++)
total += i*i;
printf("The actual sum should be %d\n", total);
/* create threads */
if (pthread_create(&constid, NULL, consumer, NULL))
fprintf(stderr,"Could not create consumer");
else if (pthread_create(&prodtid, NULL, producer, NULL))
fprintf(stderr,"Could not create producer");
/* wait for the threads to finish */
pthread_join(prodtid, NULL);
pthread_join(constid, NULL);
printf("The threads produced the sum %d\n", sum);
exit(0);
}