I am trying to create a code that mimics a child care center. In this center, one adult can take care of three children. This condition must be met all the time. Adults and children are randomly generated processes, and the number of children and adults is set in the arguments of the program. A child can only enter if there are enough adults in it, and an adult can leave only if there are enough other adults to take care of the children. If not, passive waiting should be realized until the condition allows the child / adults to exit / enter.
#include <time.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> #include <string.h> #include <semaphore.h> #include <sys/mman.h> #include <sys/ipc.h> #include <sys/shm.h> void load_init_values(); void handler(int, int, char*); pid_t adults, children; int adult_max_t, child_max_t, adc, chc, amt, cmt, shm_a_id, shm_c_id; int *adults_inside, *children_inside; sem_t *adults_sem, *children_sem, *entry; int main(int argc, char *argv[]) { srand(time(NULL)); setbuf(stdout,NULL); adc=atoi(argv[1]); chc=atoi(argv[2]); adult_max_t=atoi(argv[3]); child_max_t=atoi(argv[4]); amt=atoi(argv[5]); cmt=atoi(argv[6]); int pid=0; load_init_values(); adults = fork(); if (adults == 0) { for(int i=0; i<=adc-1; i++) { int adult_t = (random() % (adult_max_t + 1)); usleep(adult_t*1000); adults = fork(); // Adult process is created here if(adults == 0) { handler(getpid(), amt, "adult"); } else { } } } else { children = fork(); if (children == 0) { for(int i=0; i<=chc-1; i++) { int child_t = (random() % (child_max_t + 1)); usleep(child_t*1000); children = fork(); // Child process is created here if(children == 0) { handler(getpid(), cmt, "child"); break; } else { } } } else { } } return 0; } void handler(int pid,int maxtime, char* type) { sem_wait(entry); printf("%s %i%s\n",type,pid," attempting to enter..."); if(type == "child") { int child_leave_t = (random() % (maxtime + 1)); if((*adults_inside) != 0) { if(((*children_inside)+1)/(*adults_inside) <= 3) { (*children_inside)++; printf("%s %i%s\n",type,pid," entered!"); usleep(child_leave_t*1000); printf("%s %i%s\n",type,pid," left!"); (*children_inside)--; } else { printf("%s %i%s\n",type,pid," can not enter. Waiting..."); } } else { printf("%s %i%s\n",type,pid," can not enter. Waiting..."); } } else if(type == "adult") { (*adults_inside)++; printf("%s %i%s\n",type,pid," entered."); } sem_post(entry); } void load_init_values() { adults_sem = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); children_sem = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); entry = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0); shm_a_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | IPC_EXCL | 0666); shm_c_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | IPC_EXCL | 0666); adults_inside = (int *) shmat(shm_a_id, NULL, 0); children_inside = (int *) shmat(shm_c_id, NULL, 0); sem_init(adults_sem,1,1); sem_init(children_sem,1,1); sem_init(entry,1,1); }
This code only simulates the process of generating processes. There is one common entry semaphore that allows only one process to request input. The adults_inside memory variables adults_inside and children_inside monitor the internal state.
My problem is mainly in the handler function. After the condition that prohibits the introduction of a child element is launched, I cannot understand how to implement passive waiting. I was thinking about using the pause() system call and storing pending processes in a queue, but it seems pretty inefficient. Which approach to choose?