I am attempting to create a code that simulates child care center. In this center one adult can care for up to three children. This condition has to be fulfilled all the time. Adults and children are processes generated randomly and amount of children and adults is set in program arguments. Child can enter only if there is enough adults inside and adult can leave only if there is enough other adults to care for the children. If not, passive waiting should be implemented, until the condition allows child/adult to leave/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 generating of processes. There is one shared semaphore entry
that allows only one process at the time to request entering. Shared memory variables adults_inside
and children_inside
keep track of the inner state.
My problem is basically located in handler function. After condition disallowing child to enter is triggered, I can not figure out how to implement passive wait. I was thinking about using pause()
system call and store the waiting processes in queue, but is seem quite inefficient. What approach should I choose?