I’m trying to implement a functional version of the classic reader-writer problem in IPC which doesn’t cause starvation. You can find the full article here
To me my implementation seems correct, but I prefer asking people who knows more stuff than me. What do you think, is it correct? (list
is a shared memory i didnt post the full code because here is the sauce)
Here’s the code
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <time.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/msg.h> #include <semaphore.h> #include <fcntl.h> #define TEST_ERROR if (errno) {fprintf(stderr, \ "%s:%d: PID=%5d: Error %d (%s)\n", \ __FILE__, \ __LINE__, \ getpid(), \ errno, \ strerror(errno));} //third read-writer problem int readers, writers; int main() { struct sembuf sops_mutex, sops_resource; int sem_mutex, sem_resource, shm_id, *list, i, j, status; pid_t child_pid; shm_id = shmget(IPC_PRIVATE, sizeof(list), 0666 | IPC_CREAT | IPC_EXCL); TEST_ERROR; list = shmat(shm_id, NULL, 0); TEST_ERROR; sem_mutex = semget((key_t)getpid(), 1, 0600 | IPC_CREAT | IPC_EXCL); TEST_ERROR; sem_resource = semget((key_t)getpid()+1, 1, 0600 | IPC_CREAT | IPC_EXCL); TEST_ERROR; semctl(sem_mutex, 0, SETVAL, 1); //signal(mutex) semctl(sem_resource, 0, SETVAL, 1); //signal(mutex) //i%2==0 reader else writer for(i=0; i<20; i++) { switch(fork()) { case 0: switch(i%2) { case 0://reader while(semctl(sem_mutex, 0, GETVAL) != 1); //wait(mutex) if(writers > 0 || readers == 0) { semctl(sem_mutex, 0, SETVAL, 1); //signal(mutex) while(semctl(sem_resource, 0, GETVAL) != 1); //wait(mutex) while(semctl(sem_mutex, 0, GETVAL) != 1); //wait(mutex) } readers++; semctl(sem_mutex, 0, SETVAL, 1); //signal(mutex) for(j = 0; j<20; j++) { //reading if(j%2!=0) printf("%d %d ", getpid(), list[j]); }printf("\n"); while(semctl(sem_mutex, 0, GETVAL) != 1); //wait(mutex) readers--; if(readers==0) semctl(sem_resource, 0, SETVAL, 1); //signal(resource) semctl(sem_mutex, 0, SETVAL, 1); //signal(mutex) break; default://writer while(semctl(sem_mutex, 0, GETVAL) != 1); //wait(mutex) writers++; //writers <- +1 semctl(sem_mutex, 0, SETVAL, 1); //signal(mutex) while(semctl(sem_resource, 0, GETVAL) != 1); //wait(resource) list[i] = i; //writing while(semctl(sem_mutex, 0, GETVAL) != 1); //wait(mutex) writers--; semctl(sem_mutex, 0, SETVAL, 1); //signal(mutex) semctl(sem_resource, 0, SETVAL, 1); //signal(resource) break; } shmdt(list); TEST_ERROR; exit(0); break; default: break; } } while (shmctl(shm_id, IPC_RMID, NULL)) { TEST_ERROR; } while((child_pid = wait(&status)) != -1) { printf("PARENT: %d, CHILD_TERMINATED: %d STATUS: %d \n", getpid(), child_pid, WEXITSTATUS(status)); } semctl(sem_resource, 0, IPC_RMID); semctl(sem_mutex, 0, IPC_RMID); }
This is the wait-signal portion
And this is the code of interest