#include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include #include /* * ***D08*** due contatori condivisi tra processi: cont1 e cont2 processo padre crea 2 processi figli. ogni processo figlio fa questo per N (= 100000): - incrementa cont1; - se cont1 % 10 == 0 (cioè se cont1 è divisibile per 10), allora incrementa cont2 OPPURE: processo figlio A fa questo per N (= 100000): - incrementa cont1; - se cont1 % 10 == 0 (cioè se cont1 è divisibile per 10), allora incrementa cont2 processo figlio B fa questo per N (= 100000): - incrementa cont2; - se cont2 % 10 == 0 (cioè se cont2 è divisibile per 10), allora incrementa cont1 l'accesso ai due contatori deve essere regolato da un mutex (implementato con semaforo). [un mutex per ogni contatore? o un singolo mutex per entrambi?] */ #define N 100000 int * cont1; int * cont2; sem_t * mutex1; sem_t * mutex2; // QUESTA SOLUZIONE PROVOCA UN "DEADLOCK" tra i due processi figli //void process1() { // for (int i = 0; i < N; i++) { // if (sem_wait(mutex1) != 0) { // perror("sem_wait"); // exit(1); // } // // (*cont1)++; // // if (*cont1 % 10 == 0) { // if (sem_wait(mutex2) != 0) { // perror("sem_wait"); // exit(1); // } // // (*cont2)++; // // if (sem_post(mutex2) != 0) { // perror("sem_post"); // exit(1); // } // } // // if (sem_post(mutex1) != 0) { // perror("sem_post"); // exit(1); // } // // } // // printf("[child1] bye\n"); // // exit(0); //} // //void process2() { // for (int i = 0; i < N; i++) { // if (sem_wait(mutex2) != 0) { // perror("sem_wait"); // exit(1); // } // // (*cont2)++; // // if (*cont2 % 10 == 0) { // if (sem_wait(mutex1) != 0) { // perror("sem_wait"); // exit(1); // } // // (*cont1)++; // // if (sem_post(mutex1) != 0) { // perror("sem_post"); // exit(1); // } // } // // if (sem_post(mutex2) != 0) { // perror("sem_post"); // exit(1); // } // // } // // printf("[child1] bye\n"); // // // exit(0); //} void process1() { int inc_other_counter; for (int i = 0; i < N; i++) { if (sem_wait(mutex1) != 0) { perror("sem_wait"); exit(1); } (*cont1)++; inc_other_counter = (*cont1 % 10) == 0; if (sem_post(mutex1) != 0) { perror("sem_post"); exit(1); } if (inc_other_counter) { if (sem_wait(mutex2) != 0) { perror("sem_wait"); exit(1); } (*cont2)++; if (sem_post(mutex2) != 0) { perror("sem_post"); exit(1); } } } printf("[child1] bye\n"); exit(0); } void process2() { int inc_other_counter; for (int i = 0; i < N; i++) { if (sem_wait(mutex2) != 0) { perror("sem_wait"); exit(1); } (*cont2)++; inc_other_counter = (*cont2 % 10) == 0; if (sem_post(mutex2) != 0) { perror("sem_post"); exit(1); } if (inc_other_counter) { if (sem_wait(mutex1) != 0) { perror("sem_wait"); exit(1); } (*cont1)++; if (sem_post(mutex1) != 0) { perror("sem_post"); exit(1); } } } printf("[child2] bye\n"); exit(0); } int main() { pid_t pid1, pid2; char * result; // chiedo una memoria condivisa per: due contatori, due semafori result = mmap(NULL, sizeof(int)*2 + sizeof(sem_t)*3, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1,0 ); if (result == MAP_FAILED) { perror("mmap"); exit(1); } cont1 = result; cont2 = &result[sizeof(int)]; // sem_unlink("/sem1"); // sem_unlink("/sem2"); // // mutex1 = sem_open("/sem1", O_CREAT, 0600, 1); // mutex2 = sem_open("/sem2", O_CREAT, 0600, 1); mutex1 = &result[sizeof(int)*2]; mutex2 = &result[sizeof(int)*2 + sizeof(sem_t)]; // mutex2 = mutex1 + 1; if (sem_init(mutex1, 1, 1) != 0) { perror("sem_init"); exit(1); } if (sem_init(mutex2, 1, 1) != 0) { perror("sem_init"); exit(1); } pid1 = fork(); if (pid1 == -1) { perror("fork"); exit(1); } else if (pid1 == 0) process1(); pid2 = fork(); if (pid2 == -1) { perror("fork"); exit(1); } else if (pid2 == 0) process2(); // aspettiamo la conclusione dei due processi while (wait(NULL) != -1) ; sem_destroy(mutex1); sem_destroy(mutex2); printf("cont1=%d\ncont2=%d\n", *cont1, *cont2); return 0; }