1
votes

I have a question about this piece of code I have. It is the classic readers-writers problem. I followed the pseudo-code found on this wikipedia page for the first problem that has writers starving. I would like to know how I would actually notice the starvation of the writers going on.

I tried putting print statements of the shared_variable in various places, but this didn't give me much insight. But maybe I just didn't understand what was going on. Would someone be able to explain to me how I could visually see the starvation happening? Thank you! The number of attempts that the reader or writer would attempt to read or write is given as a command line argument.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>


// Compile it like so: gcc assignment2.c -lpthread


// Shared variables (semaphore and integer)
static sem_t rw_mutex;
static sem_t mutex;
static int read_count = 0;

// Shared variable
int shared_variable = 0;

static void *writerAction(void *arg){
    int number_attempt = *((int *) arg);
    int attempt = 0;
    do{
        sem_wait(&rw_mutex);
        shared_variable = shared_variable + 10;
        sem_post(&rw_mutex);
        attempt++;
    }while(attempt < number_attempt);
}

static void *readerAction(void *arg){
    int number_attempt = *((int *) arg);
    int attempt = 0;
   do{
        sem_wait(&mutex);
        read_count++;
        // waiting to be able to read for the possible writer
        if (read_count == 1 ){
            sem_wait(&rw_mutex); // get the lock so that writter can't write!
        }

        // Release the read_count variable
        sem_post(&mutex);
        sem_wait(&mutex);
        read_count--;

        if (read_count == 0){
            sem_post(&rw_mutex); // release the lock so that writter can write
        }
        sem_post(&mutex);
        attempt++;
    } while(attempt < number_attempt);
}




int main(int argc, char *argv[]) {

    int number_writers = 10;
    int number_readers = 500;
    int reader_repeat_count = atoi(argv[2]);
    int writer_repeat_count = atoi(argv[1]);

    // Instantiating the threads for the writters and readers
    pthread_t writer_threads[number_writers];
    pthread_t reader_threads[number_readers];

    // Initation of semaphores
    sem_init(&rw_mutex, 0, 1);
    sem_init(&mutex, 0, 1);

    printf("Start creation of Readers\n");
    for(int i = 0; i <number_readers; i++){
        pthread_create(&reader_threads[i], NULL, readerAction, &reader_repeat_count);
    }
    printf("Start creation of Writers\n");
    for(int i = 0; i < number_writers; i++){
        pthread_create(&writer_threads[i], NULL, writerAction, &writer_repeat_count);
    }

    // All the actions is hapenning here
    printf("Wait for Readers\n");
    for(int i = 0; i < number_readers; i++){
        printf("Waiting for : %d\n",i);
        pthread_join(reader_threads[i], NULL);
    }

    printf("Wait for Writers\n");
    // Collect all the writers
    for(int i = 0; i < number_writers; i++){
        printf("Waiting for : %d\n",i);
        pthread_join(writer_threads[i], NULL);
    }

    // Results
    printf("The shared variable is : %d\n",shared_variable);
   }
1

1 Answers

0
votes

First of all there is a syntax error, the return type of writerAction and readerAction should be void not void*

In order to see writer starvation you can print "writer trying to write" just before writer is trying to acquire the rw_mutex, the call to sem_wait(&rw_mutex). Add another print when the writer has updated the shared variable, inside the critical section. Add one more printf just after the the entry section of the reader. Which is this code.

// Release the read_count variable
sem_post(&mutex);
printf("reader reading shared value %d\n", shared_variable);

Now when you run the code with large repeat count, You will see "writer trying to write" then you will see a large number of reader printouts instead of the one from writer updating the shared variables, which will prove that the readers are starving the writer by not allowing it to update the variable.