Department of Computer & Math. Sciences

 

Programming Assignment # 3

CS4315

 

 

The attached program shows an implementation of the producer-consumer problem using threads. It uses POSIX mutex locks (or mutexes) to support synchronization between the producer and consumer threads. The mutex is the simplest thread synchronization mechanism supported by POSIX (others are semaphores and condition variables). A number of library functions are provided to support mutexes. Among them are: pthread_mutex_init, pthread_mutex_lock, and pthread_mutex_unlock. Look up the man pages to familiarize yourself with these functions as well as the other thread related functions used in the program. You may also want to check some UNIX references on these functions (e.g. "UNIX Network Programming" by Richard Stevens, Prentice Hall 1999).

 

    1. (a) The attached program attempts to solve the bounded-buffer problem for 1 producer and 1 consumer, but is not a correct solution. Read the program carefully, and provide a scenario in which it produces an incorrect answer. (b) Copy the attached program and compile it. Note that the program consists of two files: buf.h and proj3.c. When compiling, use the pthread option to be able to include the pthread library functions to your program (see the man pages on command cc for more info). Execute the program and verify the scenario you provided to answer question 1(a).

 

 

    2. Modify the attached program so that it solves the bounded-buffer problem using (a) mutex locks, (b) semaphores (see next question).  This means that you need to turn in two solutions, one using locks and the other semaphores. However, combine two solutions into one program and use a switch to choose either solution during execution as shown below:

 

Type “1” to use lock and “2” to use semaphore: 1

 

The expected result is XXXXXX

The result of the program is XXXXXX

 

 Make sure to explicitly mark the changes that you make (use highlight marker) and state whether your solution correctly solves the problem.

 

 

 

Note: When using semaphore functions (sem_wait, sem_post, etc.), to force the linker to include the real-time library functions (associated with semaphores) you must use the -l option with the library name ( i.e. -lrt ).  You also need to use the -L option to give the linker the path of the real-time library.  Here is the format of the cc command on Digital UNIX:

                cc  -o proj3  proj3.c  -L/usr/ccs/lib -lrt  -pthread

 

 

Project submission:

Answers to questions 1 should be typed on separate Word document. Submit the Word document together with the source code of the program on Blackboard Vista before the due date (See the course schedule).  Your programs will be graded based on correctness and clarity.

 

 

===============================================buf.h=======================

/* /* An incorrect implementation of the bounded-buffer problem: header file buf.h*/

#include <pthread.h>

#define BUFSIZE 8

static int buffer[BUFSIZE]; // declare shared buffer

static int bufin = 0; // index to where next item produced to go in the buffer

static int bufout = 0; // index to where next item consumed is to come from

pthread_mutex_t buffer_lock; // mutex to ensure mutually exclusive access to buffer

/* Get the next item from buffer and put it in *itemp. */

void get_item(int *itemp)

{

 

    pthread_mutex_lock(&buffer_lock); // check buffer_lock. If buffer_lock is locked thread is

                                                         // blocked until buffer_lock becomes unlocked.

                                                        // Otherwise, the thread locks lock_buffer and gets in

                                                        // critical  section.

 

    *itemp = buffer[bufout];

    bufout = (bufout + 1) % BUFSIZE;

    pthread_mutex_unlock(&buffer_lock); // unlocked 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;

}

==================================Proj3.c====================================

/* An incorrect implementation of the bounded-buffer problem */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include "buf.h"

#define NUMITEMS 100 // Total number of items to be produces & consumed

int sum = 0;

void put_item(int);

void get_item(int *);

void *producer(void * arg1) // The producer function

{

    int i;

    for (i = 1; i <= NUMITEMS; i++)

        put_item(i*i);

    return NULL;

}

void *consumer(void *arg2) // The consumer function

{

    int i, myitem;

    for (i = 1; i <= NUMITEMS; i++) {

        get_item(&myitem);

        sum += myitem;

    }

return NULL;

}

void main(void)

{

    pthread_t prodtid;

    pthread_t constid;

    int i, total;

    /* Initialize buffer_lock to the default initial attribute values */

    pthread_mutex_init(&buffer_lock, NULL);

    /* This is used for testing purposes only. */

    total = 0;

    for (i = 1; i <= NUMITEMS; i++)

        total += i*i;

    printf("The expected sum should be %d\n", total);

 

/* create producer and consumer 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);

/* terminate process */

    exit(0);

}