How to create a proper barrier with barrier function in C using semaphore

179 Views Asked by At

I have tried to create three different function init_barrier, reach_barrier and destroy_barrier. These three functions have these properties: init_barrier: Takes one argument – The number of processes that will call the barrier. This function should create any shared memory required, as well as the semaphores you need. Note that in the algorithm above count is a shared variable that is updated by multiple processes and can thus create race conditions. You will need one more semaphore to act as a mutex to protect this variable. reach_barrier: Does not take any arguments. Follows the algorithm above. destroy_barrier: If the caller is a parent process, destroy all semaphores and detach and release all shared memory.

The given pseudo code for the two function init and reach barrier:

int nproc = 0, count = 0;
sem_t barrier;
// Initializes the barrier
void init_barrier(int num_proc) {
    nproc = num_proc;
    count = 0;
    Initialize barrier to 0.
}
// Every process calls this to “reach” the barrier
void reach_barrier() {
    count++;
    if(count == nproc) {
    // Release one process
        signal(barrier);
    }
    else {
        // We are not the last process. So we wait at the
        // semaphore until we are freed.
        wait(barrier);
        // Now that we are freed, we free the next process
        signal(barrier);
    }
}
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "barrier.h"

int nproc = 0, count = 0;
sem_t barrier;  // Semaphore for the barrier
sem_t mutex;    // Semaphore to protect the 'count' variable;

void init_barrier(int num_proc) {
    nproc = num_proc;
    count = 0;

    // Initialize the barrier semaphore to 0
    if (sem_init(&barrier, 0, 0) != 0) {
        perror("Failed to initialize barrier semaphore");
        exit(EXIT_FAILURE);
    }

    // Initialize the mutex semaphore to 1
    if (sem_init(&mutex, 0, 1) != 0) {
        perror("Failed to initialize mutex semaphore");
        exit(EXIT_FAILURE);
    }
}

void reach_barrier() {
    sem_wait(&mutex);  // Lock the mutex to protect 'count'
    count++;
    
    if (count == nproc) {
        // Release all waiting processes
        int i;
        for (i = 0; i < nproc - 1; i++) {
            sem_post(&barrier);
        }
    } else {
        // Release the mutex before waiting
        sem_post(&mutex);
        // Wait at the barrier until released
        sem_wait(&barrier);
    }
    
    sem_wait(&mutex);  // Lock the mutex to protect 'count'
    count--;
    if (count == 0) {
        // The last process releases the waiting processes
        int i;
        for (i = 0; i < nproc - 1; i++) {
            sem_post(&barrier);
        }
    }
    sem_post(&mutex);  // Unlock the mutex
}

void destroy_barrier(int my_pid) {
    if (my_pid == 0) {
        // This is the parent process
        // Destroy semaphores
        if (sem_destroy(&barrier)
            perror("Failed to destroy barrier semaphore");
            exit(EXIT_FAILURE);
        }
        if (sem_destroy(&mutex) != 0) {
            perror("Failed to destroy mutex semaphore");
            exit(EXIT_FAILURE);
        }
        
        // Detach and free any shared memory if needed
        // You can add code here to handle shared memory cleanup
    }
}

I try with my code but apparently my code didnt success to let the children return and cause the output stuck at a point when I try to run on the testcases.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
#include "barrier.h"

#define NUM_PROCESSES   6
#define MAX_SLEEP       1000000  // Maximum sleep period in microseconds

int main() {
    int i, pid;
    int sleep_time[NUM_PROCESSES];

    init_barrier(NUM_PROCESSES+1);

    srand(time(NULL));
    for(i=0; i<NUM_PROCESSES; i++) {

        // The children will all slip at different amounts of time
        sleep_time[i] = (int) (((float) rand() / RAND_MAX) * MAX_SLEEP);
        if((pid = fork()) == 0) {
            srand(time(NULL));
            break;
        }
    }

    if(pid == 0) {
        usleep(sleep_time[i]);

        // Reach the barrier.
        printf("\tChild %d slept for %3.2f seconds and has now reached the barrier\n", i, sleep_time[i]/1000000.0);
        reach_barrier();
    }
    else {
        // Parent will just wait at barrier for all children to return
        printf("**Parent waiting for children**\n\n");
        reach_barrier();
        printf("\n**All the children have returned**\n");
        
        // Clean up the process table
        for(i=0; i<NUM_PROCESSES; i++)
            wait(NULL);

        destroy_barrier(pid);
    }
}

After compiling and run the file, it stuck at the point and wont print all the children have returned and I cant figured out why?

0

There are 0 best solutions below