Skip to content
Advertisement

C system v Semaphore not locking critical region

I have a code that reads an integer from shared memory and then incerements the number in child processes. I’m using semaphore to lock this critical region so that the integer gets only increased if no other process is not increasing it. So I get a stable integer value.

I have used SYSTEM V Semaphore for that, however I’m not able to make it work as it looks like that my usage of that functions don’t do anything.

The program simplyspawns 100 processeces where each process increments the integer inside the shared memory by 1. ( The shared memory segment in initially created by another program, let me know if you need that too!)

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/wait.h>

#define FIFO_PATH "/tmp/RESULT_FIFO"
#define PROC_NUM 10
#define MAX_ITERATIONS 1
#define SHM_SIZE 1024
#define SHM_KEY 23423

int shmid, *shmdata, semid;
struct sembuf semaphore;

int main() {
    FILE *fp_fifo;
    /* Initialize Semaphore */
    semid = semget (2134L, 0, IPC_PRIVATE);
    if(semid <0) {
        semid = semget (2134, 1, IPC_CREAT | IPC_EXCL | 0666);
        if (semid < 0) {
            perror("semget()");
            exit(EXIT_FAILURE);
        }
    }
    semctl(semid, 0, SETVAL, (int)1);
    shmid = shmget(234234, sizeof(int),  0777);
    if(shmid == -1) {
        perror("shmget()");
        exit(EXIT_FAILURE);
    }
    shmdata = shmat(shmid, 0, 0);
    if(shmdata == -1) {
        perror("shmat()");
        exit(EXIT_FAILURE);
    }
    printf("key is53 %i n", *shmdata);
    for (int i = 0; i < 100; ++i) {
        int t = fork();
        if(t > 0) {
            /*parent*/
        } else if(t == -1) {
            perror("fork()");
        } else if(t == 0)  {
            /* Child*/
            semaphore.sem_op  = -1;
            semaphore.sem_num = 0;
            semaphore.sem_flg = SEM_UNDO;
            if(semop(semid, &semaphore, 1) == -1) {
                perror("semop()");
                exit(EXIT_FAILURE);
            }

            *shmdata=*shmdata+1;
            semaphore.sem_op  = 1;
            if(semop(semid, &semaphore, 1) == -1) {
                perror("semop()");
                exit(EXIT_FAILURE);
            }
            return EXIT_SUCCESS;
        }
    }
    wait(0);
    printf("key is53 %i n", *shmdata);

    if((fp_fifo = fopen(FIFO_PATH, "w")) == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    fprintf(fp_fifo, "%d", *shmdata);
    shmdata = 0;
    shmdt(shmdata);
    return EXIT_SUCCESS;
}

Advertisement

Answer

I foudn the error it was because of the wait() was not working correctly. The semaphore worked correctly, but wait(NULL) was not correctly used. Here is my corrected version of a simple example how to use system V semaphore:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <unistd.h>
#include <sys/wait.h>

#define FIFO_PATH "/tmp/RESULT_FIFO"
#define PROC_NUM 10
#define MAX_ITERATIONS 1
#define SHM_SIZE 1024
#define SHM_KEY 23423

int shmid, *shmdata, semid;
struct sembuf semaphore;

int main() {
    FILE *fp_fifo;
    /* Initialize Semaphore */
    semid = semget (2134L, 0, IPC_PRIVATE);
    if(semid <0) {
        semid = semget (2134, 1, IPC_CREAT | IPC_EXCL | 0666);
        if (semid < 0) {
            perror("semget()");
            exit(EXIT_FAILURE);
        }
    }
    semctl(semid, 0, SETVAL, (int)1);
    shmid = shmget(234234, sizeof(int),  0777);
    if(shmid == -1) {
        perror("shmget()");
        exit(EXIT_FAILURE);
    }
    shmdata = shmat(shmid, 0, 0);
    if(shmdata == -1) {
        perror("shmat()");
        exit(EXIT_FAILURE);
    }
    printf("key is46 %i n", *shmdata);
    for (int i = 0; i < 100; ++i) {
        int t = fork();
        if(t > 0) {
            /*parent*/
            wait(NULL);
        } else if(t == -1) {
            perror("fork()");
        } else if(t == 0)  {
            /* Child*/
            semaphore.sem_op  = -1;
            semaphore.sem_num = 0;
            semaphore.sem_flg = SEM_UNDO;
            if(semop(semid, &semaphore, 1) == -1) {
                perror("semop()");
                exit(EXIT_FAILURE);
            }


            *shmdata= *shmdata+1;
           // printf("key is65 %i n", *shmdata);
            semaphore.sem_op  = 1;
            if(semop(semid, &semaphore, 1) == -1) {
                perror("semop()");
                exit(EXIT_FAILURE);
            }
            return EXIT_SUCCESS;
        }
    }
    printf("key is73 %d n", *shmdata);

    if((fp_fifo = fopen(FIFO_PATH, "w")) == NULL) {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    fprintf(fp_fifo, "%d", *shmdata);
    shmdata = 0;
    shmdt(shmdata);
    return EXIT_SUCCESS;
}
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement