process shared binary semaphore

Viewed 54

I've created a binary semaphore that can be shared between two processes using pthread_mutex_t, pthread_cond_t and bool flag. But I've a little doubt of my implementation regarding the initialization of the mutex and condvar attributes(race condition if Pro1 is created first and then Pro2 or Pro2 created first and then Pro1). This is my code:

Pro1.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>

struct bs_attr {
    pthread_mutex_t mutex;
    pthread_cond_t cvar;
    bool flag;
};

struct bs_attr *bs_attr_obj;

void post() {
    pthread_mutex_lock(&bs_attr_obj->mutex);
    bs_attr_obj->flag = true;
    pthread_mutex_unlock(&bs_attr_obj->mutex);
    pthread_cond_signal(&bs_attr_obj->cvar);
}

void wait() {
    pthread_mutex_lock(&bs_attr_obj->mutex);
    while (!bs_attr_obj->flag)
        pthread_cond_wait(&bs_attr_obj->cvar, &bs_attr_obj->mutex);
    bs_attr_obj->flag = false;
    pthread_mutex_unlock(&bs_attr_obj->mutex);
}

void create_shm(const char *bin_sem_ID, const bool create, const int flags, const int mode) {
    int bs_attr_obj_ID;
    if ((bs_attr_obj_ID = shm_open(bin_sem_ID, flags, mode)) == -1) {
        printf("shm_open failed with %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }

    if (create) {
        if (ftruncate(bs_attr_obj_ID, sizeof(bs_attr)) == -1) {
            printf("ftruncate failed with %s\n", bin_sem_ID);

            exit(EXIT_FAILURE);
        }
    }

    if ((bs_attr_obj = (bs_attr *)(mmap(NULL, sizeof(bs_attr), PROT_READ | PROT_WRITE, MAP_SHARED, bs_attr_obj_ID, 0))) == MAP_FAILED) {
        printf("mmap failed with %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }

    if (create) {
        pthread_mutex_lock(&bs_attr_obj->mutex);
        bs_attr_obj->flag = false;
        pthread_mutex_unlock(&bs_attr_obj->mutex);
    }
}

int main() {
    const char *bin_sem_ID = "/BIN_SEM1";
    create_shm(bin_sem_ID, true, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG);
    
    // IS THE BELOW PART A RACE CONDITION?
    /* set mutex shared between processes */
    pthread_mutexattr_t mutex_attr;
    pthread_mutexattr_init(&mutex_attr);
    if (pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED) != 0) {
        printf("mutex attribute process shared error %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }
    pthread_mutex_init(&bs_attr_obj->mutex, &mutex_attr);
    pthread_mutexattr_destroy(&mutex_attr);

    /* set cvar shared between processes */
    pthread_condattr_t cvar_attr;
    pthread_condattr_init(&cvar_attr);
    if (pthread_condattr_setpshared(&cvar_attr, PTHREAD_PROCESS_SHARED) != 0) {
        printf("condition variable attribute process shared error %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }
    pthread_cond_init(&bs_attr_obj->cvar, &cvar_attr);
    pthread_condattr_destroy(&cvar_attr);

    while (true) {
        post();
        printf("signal posted\n");

        sleep(1);
    }
}

Pro2.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>

struct bs_attr {
    pthread_mutex_t mutex;
    pthread_cond_t cvar;
    bool flag;
};

struct bs_attr *bs_attr_obj;

void post() {
    pthread_mutex_lock(&bs_attr_obj->mutex);
    bs_attr_obj->flag = true;
    pthread_mutex_unlock(&bs_attr_obj->mutex);
    pthread_cond_signal(&bs_attr_obj->cvar);
}

void wait() {
    pthread_mutex_lock(&bs_attr_obj->mutex);
    while (!bs_attr_obj->flag)
        pthread_cond_wait(&bs_attr_obj->cvar, &bs_attr_obj->mutex);
    bs_attr_obj->flag = false;
    pthread_mutex_unlock(&bs_attr_obj->mutex);
}

void create_shm(const char *bin_sem_ID, const bool create, const int flags, const int mode) {
    int bs_attr_obj_ID;
    if ((bs_attr_obj_ID = shm_open(bin_sem_ID, flags, mode)) == -1) {
        printf("shm_open failed with %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }

    if (create) {
        if (ftruncate(bs_attr_obj_ID, sizeof(bs_attr)) == -1) {
            printf("ftruncate failed with %s\n", bin_sem_ID);

            exit(EXIT_FAILURE);
        }
    }

    if ((bs_attr_obj = (bs_attr *)(mmap(NULL, sizeof(bs_attr), PROT_READ | PROT_WRITE, MAP_SHARED, bs_attr_obj_ID, 0))) == MAP_FAILED) {
        printf("mmap failed with %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }

    if (create) {
        pthread_mutex_lock(&bs_attr_obj->mutex);
        bs_attr_obj->flag = false;
        pthread_mutex_unlock(&bs_attr_obj->mutex);
    }
}

int main() {
    const char *bin_sem_ID = "/BIN_SEM1";
    create_shm(bin_sem_ID, false, O_RDWR, S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP);
    
    // IS THE BELOW PART A RACE CONDITION?
    /* set mutex shared between processes */
    pthread_mutexattr_t mutex_attr;
    pthread_mutexattr_init(&mutex_attr);
    if (pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED) != 0) {
        printf("mutex attribute process shared error %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }
    pthread_mutex_init(&bs_attr_obj->mutex, &mutex_attr);
    pthread_mutexattr_destroy(&mutex_attr);

    /* set cvar shared between processes */
    pthread_condattr_t cvar_attr;
    pthread_condattr_init(&cvar_attr);
    if (pthread_condattr_setpshared(&cvar_attr, PTHREAD_PROCESS_SHARED) != 0) {
        printf("condition variable attribute process shared error %s\n", bin_sem_ID);

        exit(EXIT_FAILURE);
    }
    pthread_cond_init(&bs_attr_obj->cvar, &cvar_attr);
    pthread_condattr_destroy(&cvar_attr);

    while (true) {
        wait();
        printf("signal received\n");

        sleep(1);
    }
}
0 Answers
Related