INFOPedia : LSOMutexPizzeriaPthread

HomePage :: Categorie :: Indice :: Ultime modifiche :: Ultimi commenti :: Login/Registrazione
Come ultima fatica prima degli esami ho risolto il problema dei pizzaioli in UNIX. Ho aggiunto qualcosa per rendere visibile l'utilizzo dei mutex.

Il testo del problema:



In una pizzeria molto frequentata vi lavorono due pizzaioli. L’unico forno disponibile può contenere un massimo di 8 pizze quindi i pizzaioli devono condividere l’unico forno disponibile. La vita lavorativa dei pizzaioli quindi consiste

Fino a quando ci sono ordinazioni

1) Prende una ordinazione con un numero n random di pizze da 1 a 10 da preparare

2) Prepara le pizze in un tempo t=n*tp

3) Inforna un numero di pizze m che può infornare

4) Aspetta un tempo t=tc in cui le pizze vengono cotte

5) Se ha cotto tutte le pizze va al punto 1 se no va al punto 3

a) Sviluppare in linguaggio C un programma che simuli la situazione descritta commentando le scelte fatte.

Ho aggiunto un tempo di infornatura e sfonatura delle pizze...

// Includo le librerie.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

// Costanti e funzioni utili
#define N 8 // Numero posti del forno
#define TP 1 // Tempo di preparazione di una pizza
#define TC 3 // Tempo di cottura
#define GetRandom( min, max ) ((rand( ) % (int)(((max) + 1) - (min))) + (min))

// Variabile che conterrà il nome del programma (inutile)
char *progname;

/* Il mutex associato al forno e l'attributo da passare all'inizializzatore del mutex! */
pthread_mutex_t hForno; // Ogni elemento è un posto nel forno
pthread_mutexattr_t attr; // UTILISSIMO!!!

// Variabile condivisa per il controllo dei posti disponibili. Protetta dal mutex.
int nPostiDisponibili = N;

// Variabile di controllo del ciclo principale
int finito;

/* print error message and die */
void error(char *f){
    extern char *progname;
    if (progname)
        fprintf(stderr, "%s: ", progname);
    perror(f);
    exit(1);
}

/* suspend execution of the calling thread */
void waiting(int min, int max){
    sleep(rand()%(max-min+1) + min);
}

// Routine comune ad ogni thread!
void *Pizzaiolo(void *param){
    int id=*(int *)param; // id del thread
    int nPizzeOrdinate, nPizzeRimanenti, nPizzeInfornate = 0;
    int evaso = 1; // Flag di controlla l'evasione dell'ordine
    int finito = 1; // Flag che controlla il ciclo principale
    while(finito){ // Ciclo principale
        if(evaso) { // Se ho finito prendo una nuova ordinazione
            nPizzeOrdinate = GetRandom(1,10);
            nPizzeRimanenti = nPizzeOrdinate;
            printf("T%d: E' arrivata un'ordinazione! Preparo %d pizze\n", id, nPizzeOrdinate);
            sleep(nPizzeOrdinate*TP);
            printf("T%d: Ho preparato %d pizze\n", id, nPizzeOrdinate);
            evaso = 0; // Comincio...
        }
        while( nPizzeRimanenti > 0 ) { // Ciclo sino a quando soddisfo l'ordine
            // Controllo sui posti disponibili. Controllo che non inforno più pizze di quanto me ne rimangono.
            if(  nPostiDisponibili > 0 && nPizzeInfornate < nPizzeRimanenti ) {
                // Controllo se il forno è occupato dall'altro pizzaiolo, se è occupato goto else, altrimenti continuo...
                if(pthread_mutex_trylock(&hForno) == 0 ) { // Controllo se posso accedere al forno
                    pthread_mutex_lock(&hForno); // Blocco l'accesso al forno
                    printf("T%d: Forno libero. Ci sono %d posti, inforno una pizza! Me ne mancano %d..\n",id, nPostiDisponibili, nPizzeRimanenti-nPizzeInfornate -1);
                    nPostiDisponibili--; // Occupo un posto
                    sleep(1); // tempo di infornatura...serve a fare vedere che i mutex funzionano!
                    pthread_mutex_unlock(&hForno); // Rilascio il forno...l'altro può infornare o sfornare   
                    nPizzeInfornate++; // Inforno una pizza
                } else { // Se il forno è occupato faccio un resoconto ( non capita... )
                    printf("T%d: Voglio infornare ma il forno e' occupato. Aspetto! Ho gia' in forno %d pizze\n", id, nPizzeInfornate);
                    sleep(2); // Aspetto...
                    continue; // Ricomincio il ciclo sino a quando non soddisfo l'ordine
                }
            } else { // Se non ci sono posti disponibili oppure ho già finito di infornare le pizze ordinate...
                printf("T%d: Ho %d pizze in forno...Ne rimangono %d\n",id, nPizzeInfornate, nPizzeRimanenti - nPizzeInfornate);
                nPizzeRimanenti -= nPizzeInfornate; // A seconda di quante pizze ho infornato diminuisco in numero di pizze rimanenti
                sleep(TC); // Aspetto che si cuociano le pizze infornate
                if(pthread_mutex_trylock(&hForno) == 0 ) { // Controllo se posso accedere al forno
                    pthread_mutex_lock(&hForno); // Blocco l'accesso al forno
                    nPostiDisponibili += nPizzeInfornate; // Sforno le pizze infornate, libero i posti.
                    printf("T%d: Ho sfornato %d pizze delle %d ordinate! Me ne rimangono %d\n", id, nPizzeInfornate, nPizzeOrdinate, nPizzeRimanenti);
                    sleep(1); // Tempo di sfornatura...così faccio vedere che i mutex funzionano!!!
                    pthread_mutex_unlock(&hForno); // Sblocco l'accesso al forno
                } else { // Se il forno è occupato faccio un resoconto ( non capita... )
                    printf("T%d: Voglio sfornare %d pizze delle %d ordinate ma il forno e' occupato. Aspetto!\n", id, nPizzeInfornate, nPizzeOrdinate);
                    sleep(1); // Aspetto...
                    continue; // Ricomincio il ciclo sino a quando non soddisfo l'ordine
                }               
                nPizzeInfornate = 0; // Ho tolto tutte le pizze infornate
            }
        } // Ho soddisfatto l'ordine!
        printf("T%d: Ho cotto tutte le %d pizze ordinate!\n",id, nPizzeOrdinate);
        evaso = 1; // L'ordine è stato evaso.
        // MODIFICARE QUESTO FLAG A ZERO SE SI DESIDERA CHE I PIZZAIOLI RICEVANO UN SOLO ORDINE!!!
        finito = 1;
    }
    return NULL;
}

   
// Inizia il programmino...
int main(int argc, char *argv[])
{
    // Inizializzo l'attributo del mutex
    pthread_mutexattr_init(&attr);
    // Mutex di tipo ERRORCHECK
    pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK);
   
    // Struttura di un thread pizzaiolo
    struct  {
        int id;
        pthread_t thread_id;
    } pizzaiolo[2];
   
   
    // Questo &#8730;® il nome del programmino
    progname=argv[0];
    // Via al semeeeeeeee
    srand(time(NULL));
   
    /* create mutex di tipo ERRORCHECK */
    if (pthread_mutex_init(&hForno, &attr))
            error("pthread_mutex_init");

    /* create and run the threads */
    pizzaiolo[0].id = 1;
    if (pthread_create(&pizzaiolo[0].thread_id, NULL, Pizzaiolo, &pizzaiolo[0].id))
        error("pthread_create");
   
    pizzaiolo[1].id=2; // id del secondo thread
    if (pthread_create(&pizzaiolo[1].thread_id, NULL, Pizzaiolo, &pizzaiolo[1].id))
        error("pthread_create");
   
    // Per modificare finito vedere le ultime righe di codice della routine Pizzaiolo
    // Se finito == 1 allora il ciclo principale è infinito, se finito == 0 allora i pizzaioli ricevono e completano un solo ordine.

    /* se il ciclo principale della routine Pizzaiolo non è infinito uccido i thread quando finiscono  altrimenti SIGINT per terminare! */
   
    if( pthread_join(pizzaiolo[0].thread_id,NULL) )
        error("pthread_join");
    else printf("\n\nUcciso il primo pizzaiolo! =) \n\n");
   
    if( pthread_join(pizzaiolo[1].thread_id,NULL) )
        error("pthread_join");
    else printf("\n\nUcciso il secondo pizzaiolo! =) \n\n");
   
    return 0;
}





Torna a Lab Sistemi Operativi

Non ci sono commenti in questa pagina. [Scrivi commento]

Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by Wikka Wakka Wiki 1.1.6.1
La pagina è stata generata in 0.2295 secondi