#include #include #include #include #include #include #include #include #include #define MAX_SEND_SIZE 2 union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short int *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; struct mymsgbuf { long mtype; char mtext[MAX_SEND_SIZE]; }; void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text) { /* Send a message to the queue */ // printf("Sending a message ...\n"); qbuf->mtype = type; strcpy(qbuf->mtext, text); if((msgsnd(qid, (struct msgbuf *)qbuf, strlen(qbuf->mtext)+1, 0)) ==-1) { perror("msgsnd"); exit(1); } } void read_message(int qid, struct mymsgbuf *qbuf, long type) { /* Read a message from the queue */ // printf("Reading a message ...\n"); qbuf->mtype = type; msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0); // printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext); } void locksem(int sid, int member) { struct sembuf sem_lock={ 0, -1, 0}; if( member<0 || member>0) //(get_member_count(sid)-1)) { fprintf(stderr, "semaphore member %d out of range\n", member); return; } sem_lock.sem_num = member; if((semop(sid, &sem_lock, 1)) == -1) { fprintf(stderr, "Wait failed\n"); exit(1); } // else // printf("Semaphore resources decremented by one (locked)\n"); } void unlocksem(int sid, int member) { struct sembuf sem_unlock={ member, 1, 0}; int semval; if( member<0 || member>0) // (get_member_count(sid)-1)) { fprintf(stderr, "semaphore member %d out of range\n", member); return; } sem_unlock.sem_num = member; /* Attempt to unlock the semaphore set */ if((semop(sid, &sem_unlock, 1)) == -1) { fprintf(stderr, "Signal failed\n"); exit(1); } // else // printf("Semaphore resources incremented by one (unlocked)\n"); } writeshm(int* segptr, int index, int value) { //strcpy(segptr, text); segptr[index] = value; printf("(Controler) Wrote %d\n", value); fflush(stdout); } int readshm(int* segptr, int id, int index) { if(segptr[index] > 0) printf("(Philosopher %d) Read %d\n", (id+1), segptr[index]); return segptr[index]; } remove_sem(int semid) { semctl(semid, 0, IPC_RMID, 0); printf("Semaphore set marked for deletion\n"); } remove_shm(int shmid) { shmctl(shmid, IPC_RMID, 0); printf("Shared memory segment marked for deletion\n"); } void remove_queue(int qid) { /* Remove the queue */ msgctl(qid, IPC_RMID, 0); printf("Message queue marked for deletion\n"); } philosopher(int msgqueue_id, int phil_id, int* segptr, int semid) { struct mymsgbuf qbuf; while(readshm(segptr,phil_id,0) == 0) //While not stopped { read_message(msgqueue_id, &qbuf, (phil_id+1)); printf("(Philosopher %d) Taking left fork\n",(phil_id+1)); fflush(stdout); read_message(msgqueue_id, &qbuf, (phil_id+2)); printf("(Philosopher %d) Taking right fork\n",(phil_id+1)); printf("(Philosopher %d) Eating\n",(phil_id+1)); fflush(stdout); send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, (phil_id+1), "1"); printf("(Philosopher %d) Dropping left fork\n",(phil_id+1)); fflush(stdout); send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, (phil_id+2), "1"); printf("(Philosopher %d) Dropping right fork\n",(phil_id+1)); printf("(Philosopher %d) Thinking\n",(phil_id+1)); fflush(stdout); } unlocksem(semid,0); } last_philosopher(int msgqueue_id, int*segptr, int semid) { struct mymsgbuf qbuf; while(readshm(segptr,2,0) == 0) //While not stopped { read_message(msgqueue_id, &qbuf, 1); printf("(Philosopher %d) Taking right fork\n",3); fflush(stdout); read_message(msgqueue_id, &qbuf, 3); printf("(Philosopher %d) Taking left fork\n",3); printf("(Philosopher %d) Eating\n",3); fflush(stdout); send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, 3, "3"); printf("(Philosopher %d) Dropping left fork\n",3); fflush(stdout); send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, 1, "1"); printf("(Philosopher %d) Dropping right fork\n",3); printf("(Philosopher %d) Thinking\n",3); fflush(stdout); } unlocksem(semid,0); } controler(int msgqueue_id, int*segptr, int semid, int shmid) { getchar(); writeshm(segptr,0,1); locksem(semid,0); locksem(semid,0); locksem(semid,0); remove_queue(msgqueue_id); remove_shm(shmid); remove_sem(semid); } int main(int argc, char *argv[]) { key_t key_q, key_mem, key_sem; int msgqueue_id; struct mymsgbuf qbuf; int id, cntr; pid_t pid; int shmid, semid; int *segptr; union semun semopts; /* Create unique key via call to ftok() */ key_q = ftok(".", 'q'); key_mem = ftok(".", 'm'); key_sem = ftok(".", 's'); /* Open the queue - create if necessary */ if((msgqueue_id = msgget(key_q, IPC_CREAT|0660)) == -1) { perror("msgget"); exit(1); } //Filling the message queue send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, 1, "1"); send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, 2, "2"); send_message(msgqueue_id, (struct mymsgbuf *)&qbuf, 3, "3"); /* Open the shared memory segment - create if necessary */ if((shmid = shmget(key_mem, sizeof(int), IPC_CREAT|IPC_EXCL|0666)) == -1) { printf("Shared memory segment exists - opening as client\n"); /* Segment probably already exists - try as a client */ if((shmid = shmget(key_mem, sizeof(int), 0)) == -1) { perror("shmget"); exit(1); } } else { printf("Creating new shared memory segment\n"); } /* Attach (map) the shared memory segment into the current process */ if((segptr = (int *)shmat(shmid, 0, 0)) == (int *)-1) { perror("shmat"); exit(1); } writeshm(segptr,0,0); //Creating the semaphore array printf("Attempting to create new semaphore set with 1 members\n"); if((semid = semget(key_sem, 1, IPC_CREAT|IPC_EXCL|0666)) == -1) { fprintf(stderr, "Semaphore set already exists!\n"); exit(1); } semopts.val = 0; semctl(semid, 0, SETVAL, semopts); //Creating the philosopher processes id = 0; for(cntr = 0; cntr < 3; cntr++) { pid = fork(); if(pid < 0) { perror("Process creation failed"); exit(1); } if(pid == 0) { //This is a son if(cntr < 2) philosopher(msgqueue_id,id, segptr, semid); else last_philosopher(msgqueue_id, segptr, semid); cntr = 3; } else { //This is the father id++; } } if(pid != 0) controler(msgqueue_id, segptr, semid, shmid); return(0); }