/* Avem un tablou bidimensional de intregi care este retinut intr-o zona de * memorie partajata. Tabloul bidimensional are proprietatea ca orice element * de pe ultima linie este suma tuturor elementelor de pe coloana sa si * respectiv un element de pe ultima coloana este suma tuturor elementelor de * pe linia sa. Elementul din coltul dreapta jos nu este folosit. La aceasta * zona de memorie au acces doua procese: unul care ia alege aleator un element * al tabloului bidimensional si il modifica la o valoare aleatoare si un alt * proces care verifica daca sumele totale sunt corecte si tipareste * elementele tabloului bidmensional. */ #include #include #include #include #include /* Blocheaza semaforul n din setul sem */ void lock (int sem, int n) { struct sembuf sop; sop.sem_num = n; sop.sem_op = -1; sop.sem_flg = 0; semop (sem, &sop, 1); } /* Deblocheaza semaforul n din setul sem */ void unlock (int sem, int n) { struct sembuf sop; sop.sem_num = n; sop.sem_op = 1; sop.sem_flg = 0; semop (sem, &sop, 1); } /* Creaza un set de n semafoare cu cheia k */ int face_sema (key_t k, int n) { int semid, i; /* Verifica daca deja exista un semafor cu cheia k */ if ((semid = semget (k, n, 0)) != -1) /* Distruge semaforul existent */ semctl (semid, 0, IPC_RMID, 0); if ((semid = semget (k, n, IPC_CREAT | 0600)) != -1) /* Semaforul este blocat trebuie sa-l deblocam */ for (i = 0; i < n; i++) unlock (semid, i); return semid; } /* Linia si coloana unde se retin sumele totale de pe linii si coloane */ int linie_suma, coloana_suma; /* Macrou pentru accesarea elementului de la linia l, coloana c a tabloului t */ #define ELEM(l,c,t) (*((l)+((c)*NRCOL)+t)) int linie_sema, coloana_sema; /* numarul de linii si de coloane */ #define NRLIN 8 #define NRCOL 8 /* cheia zonei de memorie partajata si a semaforului pentru linii * CHEIE+1 este cheia semaforului pentru coloane */ #define CHEIE 4321 /*---------------- modifica_aleator() -------------------------*/ /* Selecteaza aleator un element al tabloului bidimensional t, insereaza in * locul sau o valoare aleatoare si actualizeaza linia si coloana cu sumele * totale */ void modifica_aleator (int *t) { int linie, coloana, valoare_veche, valoare_noua; /* Ia un element aleator si il modifica */ linie = rand () % (NRLIN - 1); coloana = rand () % (NRCOL - 1); valoare_noua = rand () % 1000; /* Inceputul unei sectiuni critice */ lock (linie_sema, linie); lock (coloana_sema, coloana); /* Se modifica elementul din tabloul bidimensional */ valoare_veche = ELEM (t, linie, coloana); ELEM (t, linie, coloana) = valoare_noua; /* Se modifica sumele */ ELEM (t, linie, coloana_suma) += (valoare_noua - valoare_veche); ELEM (t, linie_suma, coloana) += (valoare_noua - valoare_veche); /* Sfirsitul sectiunii critice */ unlock (linie_sema, linie); unlock (coloana_sema, coloana); usleep (5000); } /* ------------------- verifica_tipareste () ---------------------- */ void verifica_tipareste (int *t) { int linie, coloana, suma, nr_gresit; static int nr_tablou = 0; /* numara tablourile bidimensionale */ nr_gresit = 0; nr_tablou++; for (linie = 0; linie < NRLIN; linie++) { suma = 0; /* Inceputul sectiunii critice */ lock (linie_sema, linie); for (coloana = 0; coloana < NRCOL; coloana++) { if (coloana != coloana_suma) suma += ELEM (t, linie, coloana); printf ("%5d", ELEM (t, linie, coloana)); } if (linie != linie_suma) nr_gresit += (suma != ELEM (t, linie, coloana_suma)); /* Sfirsitul sectiunii critice */ unlock (linie_sema, linie); printf ("\n"); } for (coloana = 0; coloana < coloana_suma; coloana++) { suma = 0; /* Inceputul sectiunii critice */ lock (coloana_sema, coloana); for (linie = 0; linie < linie_suma; linie++) suma += ELEM (t, linie, coloana); nr_gresit += (suma != ELEM (t, linie_suma, coloana)); /* Sfirsitul sectiunii critice */ unlock (coloana_sema, coloana); } if (nr_gresit) printf ("\nTabloul nr %d gresit\n", nr_tablou); if ((nr_tablou % 100) == 0) printf ("\nTabloul nr %d prelucrat\n", nr_tablou); printf ("\n-----------------------------\n"); sleep (1); } /* --------------- main ---------------------------------------------- */ void main () { int id, linie, coloana, *tablou; setbuf (stdout, NULL); linie_suma = NRLIN - 1; coloana_suma = NRCOL - 1; /* Creaza un segment de memorie partajata */ id = shmget (CHEIE, NRLIN * NRCOL * sizeof (int), IPC_CREAT | 0600); if (id < 0) { perror ("Eroare la crearea segmentului de memorie partajata"); exit (1); } tablou = (int *) shmat (id, 0, 0); if (tablou < (int *) (0)) { perror ("Eroare la atasarea la segmentul de memorie partajata"); exit (2); } /* Initializeaza tabloul cu 0 */ for (linie = 0; linie < NRLIN; linie++) for (coloana = 0; coloana < NRCOL; coloana++) ELEM (tablou, linie, coloana) = 0; /* Creaza doua seturi de semafoare pentru a proteja liniile si coloanele */ linie_sema = face_sema (CHEIE, NRLIN); coloana_sema = face_sema (CHEIE + 1, NRCOL); if ((linie_sema < 0) || (coloana_sema < 0)) { perror ("Eroare la crearea semafoarelor"); exit (2); } /* Pornesc doua procese: unul care modifica matricea si unul care o verifica * si o tipareste */ if (fork ()) { while (1) verifica_tipareste (tablou); } else { while (1) modifica_aleator (tablou); } }