/* Esame del 01/09/14
*
* In una applicazione concorrente k threads condividono r risorse equivalenti dovendo eseguire ognuna una diversa
* elaborazione che necessita di una istanza delle risorse.
*
* Scrivere un programma C che generi ad intervalli casuali i thread di calcolo che non dovranno mai essere piu` di k
* Ogni thread richiede tramite la funzione Richiesta() l’accesso ad una istanza libera delle r risorse, se ce ne sono.
* La funzione assegna la risorsa e torna un indice della stessa sotto forma di intero compreso tra 0 e r − 1;
* La funzione ritorna sempre un valore, aspettando che una risorsa si liberi se non ci sono istanze disponibili.
*
* Il generico thread esegue la computazione invocando una funzione il cui prototipo `e void Elabora( int x ),
* essendo x la risorsa assegnata al thread.
* Dopo aver fatto uso della istanza della risorsa il thread la rilascia invocando una funzione il cui prototipo
* e' void Rilascia( int x ), dove x indica l’indice della risorsa da rendere disponibile.
* Specificare la stuttura del generico thread e le funzioni Richiesta() e Rilascia() in modo tale che
* ogni istanza di risorsa venga usata da non piu’ di un thread alla volta anche se piu` thread eseguono in modo
* concorrente.
*
* Svolgimento a cura di Emanuele Munafò.
* Pertanto la soluzione data potrebbe essere inesatta e/o errata.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define K 10
#define R 4
sem_t s_nrisorselibere; // Contatore del numero delle risorse libere
pthread_mutex_t m_BMrisorsacondivisa; // Mutex per proteggere la bitmap della risorsa condivisa
short int BMrisorsacondivisa[R]; // Bitmap risorsa condivisa 0: risorsa libera, 1: risorsa occupata
sem_t s_maxthreads;
// Prototipi funzioni
unsigned int richiesta();
void rilascia(int x);
void* runner(void* runner);
void* elabora(int x);
int main(int argc, char const *argv[]){
int r;
pthread_t pid;
// Inizializzo mutex e semafori
sem_init(&s_nrisorselibere, 0, R); // Inizialmente tutte le risorse sono libere
sem_init(&s_maxthreads, 0, K);
pthread_mutex_init(&m_BMrisorsacondivisa, NULL);
// Inizializzo la bitmap a 0
for(int i=0;i<R;++i){
BMrisorsacondivisa[i] = 0;
}
// Inizializzo seme random
srand(time(NULL));
// Genero sempre thread ma max K
while(1){
sem_wait(&s_maxthreads);
r = rand()%300;
usleep(r);
pthread_create(&pid, NULL, runner, NULL);
}
return 0;
}
void* runner(void* params){
unsigned int nr = richiesta(); // Richiedi numero di risorsa libera
// Lavora sui dati
elabora(nr); // Elabora i dati, la mutua escusione è implicitamente utilizzata con richiesta() e rilascia()
// Rilascia le risorse
rilascia(nr);
}
unsigned int richiesta(){
sem_wait(&s_nrisorselibere); // Attendo che ci sia almeno una risorsa libera
unsigned int retvalue = 0;
pthread_mutex_lock(&m_BMrisorsacondivisa);
for(int i=0;i<R && (retvalue == 0);++i){ // Break al primo valore 0 che trova
if(BMrisorsacondivisa[i] == 0) // Ciò significa che l'iesima risorsa è libera
retvalue = i;
}
pthread_mutex_unlock(&m_BMrisorsacondivisa);
return retvalue;
}
void rilascia(int x){
pthread_mutex_lock(&m_BMrisorsacondivisa);
BMrisorsacondivisa[x] = 0;
pthread_mutex_unlock(&m_BMrisorsacondivisa);
sem_post(&s_nrisorselibere);
}
Comments
0 B
|👍
/👎
0 B
|👍
/👎