ProvaTeoria 2011.01.17

From Sistemi Operativi
Jump to navigation Jump to search

TESTO COMPITO

Esercizio 1

/*Scrivere un monitor reqq che gestisca una coda di richieste.
I richiedenti chiamano la funzione che ha la seguente signature:
answer_t reqq.query(request_t request);
Query deve fermare il processo richiedente fino a completamento della richiesta da parte di un gestore. Il valore di ritorno
e' la risposta del gestore.
Ci sono N gestori che si comportano come segue:
multiq_handler: process[i, i=0,..,N-1] {
	request_t req;
	int type;
	while (1) {
		req=reqq.getquery(i);
		reqq.reply(i,handle(req));
	}
}
Le richieste vengono assegnate ai gestori disponibili o accodate se sono tutti impegnati. Quando un gestore termina la
gestione (funzione handle, che non implementare!) invia il risultato tramite la reply. Il valore passato alla reply deve
essere restituito al richiedente come valore di ritorno della funzione query. Se non vi sono richieste disponibili i gestori si
fermano attendendo nuove richieste.*/

monitor reqq{
	condition oktogetquery;
	condition oktoask;
	condition oktogo;
	queue waiting;
	int gestori=0;
	
	procedure entry answer_t query(request_t request){
		waiting.enqueue(request);
		if(gestori>=N)
			oktoask.wait();
		oktogetquery.signal();
		send(request);
		oktogo.wait();
		if(!waiting.isEmpty())
			oktoask.signal();
	}
	
	procedure entry request_t getquery(int i){
		if(waiting.isEmpty())
			oktogetquery.wait();
		gestori++;
		waiting.dequeue();
	}
	
	procedure entry answer_t reply(int i, rips){
		gestori--;
		oktogo.signal();
	}
}

Giulia e Lisa

rd(June 12): la variabile "gestori" la chiamerei "gestoryoccupati" o "busy" per capire meglio il significato. cosa e' quella "SEND" nella query? mica e' un message passing. La richiesta e' stata inserita nella coda waiting, quindi da li' deve essere presa. Tra l'altro la getquery che deve restituire una request_t non ha alcun return. La gestione della oktogo e' errata. Non e' assolutamente detto che il server che ha preso la prima richiesta sia il primo a terminare. Occorre quindi studiare qualche metodo di sincronizzazione per fare in modo che la reply riattivi proprio il processo corrispondente alla query che e' stata elaborata. La signature della funzione reply e' errata: non restituisce una answer_t ma void. answer_t e' il tipo del parametro rips, che peraltro e' inutilizzato nella reply: come fa ad essere "passato" come valore di ritorno all query? La query, che deve restituire un answer_t non ha alcun return.




/*
Esercizio 1: Scrivere un monitor reqq che gestisca una coda di richieste.
I richiedenti chiamano la funzione che ha la seguente signature:
answer_t reqq.query(request_t request);
Query deve fermare il processo richiedente fino a completamento della richiesta da parte di un gestore. Il valore di ritorno 
e' la risposta del gestore.
Ci sono N gestori che si comportano come segue:
multiq_handler: process[i, i=0,..,N-1] {
	request_t req;
	int type;
	while (1) {
		 req=reqq.getquery(i);
		 reqq.reply(i,handle(req));
 	}
}
Le richieste vengono assegnate ai gestori disponibili o accodate se sono tutti impegnati. Quando un gestore termina la 
gestione (funzione handle, che non implementare!) invia il risultato tramite la reply. Il valore passato alla reply deve 
essere restituito al richiedente come valore di ritorno della funzione query. Se non vi sono richieste disponibili i gestori si 
fermano attendendo nuove richieste.
*/


/*La mia soluzione si basa su una struttura reqEntry contenente un campo per la domanda, uno per la risposta, una condizione oktoexit e un intero per il gestore.
Quando arriva un richiedente inserisce una struttura con una domanda e con i campi risposta e gestore vuoti.
Quando un gestore si occupa di una domanda setta l'opportuno campo gestore al suo indice e, al termine della routine handle(), inserisce la sua risposta nell'opportuno
campo della struct risvegliando il richiedente*/

struct reqEntry
{
	request_t req;
	condition oktoexit;
	answer_t reply=NULL;
	int handler=VOID; //VOID è un valore speciale avente valore diverso dagli indici dei gestori
}
monitor reqq
{
	reqEntry* rq=Queue(); /*coda di reqEntry*/
	condition oktohandle; /*per i gestori*/
	answer_t procedure entry query(request_t request)
	{
		rq.insert(request); 
		rp=rq.searchByReq(request);
		oktohandle.signal(); /*cerco se esiste un gestore in attesa per la mia richiesta*/
		rp->oktoexit.wait();
		risp=rp->reply; 
		remove(rp); /*recupero la risposta e rimuovo la struct dalla coda*/
		return risp;	
	}
	request_t procedure entry  getquery(int index)
	{
		if isEmptyFree(rq) /*isEmptyFree ritorna 1 se non ci sono struct libere (cioè con handler VOID) nella coda di reqEntry*/
		{
			oktohandle.wait();
		}
		rp=rq.searchFree(); /*restituisce un elemento della coda di reqEntry avente handler VOID*/
		rp->handler=index; 
		return rp;
	}
	procedure entry reply(int index, answer_t rep)
	{
		rp=rq.searchByHandler(index); /*cerca nella lista la struct avente handler uguale al mio indice*/
		rp->reply=rep;
		rp->oktoexit.signal();
	}
}

Esercizio 3

struct sendINFO
{
	pid_t receiver;
	int nmsg;
}

sendINFO* listINFO=List(); //ogni processo ha un database di strutture sendINFO per sapere quanti messaggi di ogni destinatario
						   //risultano ancora non recapitati

T* database=List(); //ogni processo ha un database di messaggi 

int iasend(pid_t destination, T message)
{
	T tmpMSG;
	sendINFO tmpINFO;
	asend(destination,message);	
	if ((tmpINFO=listINFO.search(destination))==NULL) //se questo destinatario non ha ancora un'entry nella lista, lo inserisco
		{
			list.insert(destination,0);
			tmpINFO=listINFO.search(destination);
		}
	tmpINFO.nmsg++; 
	
	/*SCORRIMENTO BUFFER DI MESSAGGI E AGGIORNAMENTO LISTA*/
	asend(getpid(),"BOT"); 
	while((tmpMSG=arecv(*))!="BOT")
	{
		if (tmpMSG=="OK")
		{
			tmpINFO=listINFO.search(tmpMSG.sender);
			tmpINFO.nmsg--;
			if (nmsg==0)
				listINFO.remove(tmpINFO);
		}
		else
			db.add(tmpMSG);
	}
	tmpINFO=search(destination);
	if(tmpINFO!=NULL)
		return tmpINFO.nmsg;
	else
		return 0;
}

T iareceive(pid_t sender)
{
	T ris;
	ris=db.search(sender);
	if (ris==NULL)
		ris=arecv(sender);
	asend(sender,"OK");
	return ris;
}

-stefano92