Warning:  Undefined array key "view" in /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php on line 2
Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php on line 47
Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php on line 48
Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php on line 49
Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php on line 50
Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php:2) in /var/www/html/wp-content/uploads/classes/so/1920/lab-examples/index.php on line 51
/**
 *  Variante con tre figli: un produttore ed due consumatori di numeri
 *  generati a random. I tre processi usano una area di memoria
 *  condivisa che contiene piu' elementi e 3 semafori per coordinarsi.
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define DIM_BUFFER      10
#define HOW_MANY        200
#define S_MUTEX 0
#define S_EMPTY 1
#define S_FULL  2
int WAIT(int sem_des, int num_semaforo) {
    struct sembuf operazioni[1] = { { num_semaforo, -1, 0 } };
    return semop(sem_des, operazioni, 1);
}
int SIGNAL(int sem_des, int num_semaforo) {
    struct sembuf operazioni[1] = { { num_semaforo, +1, 0 } };
    return semop(sem_des, operazioni, 1);
}
// produce numeri random e li scrive nella memoria condivisa
void produttore(int shm, int sems, int num, int howmany) {
    int *p, *in, *out;
    int i, number, len;
    long tot = 0;
    srand(time(NULL));                                      // randomizza il generatore di numeri pseudo-causali
    if ((p = (int *)shmat(shm, NULL, 0)) == (int *)-1) {    // attacca la memoria condivisia
        perror("shmat");
        exit(1);
    }
    in = p + DIM_BUFFER;        // la penultima posizione conterra' l'indice dell'inizio coda
    out = p + DIM_BUFFER + 1;   // l'ultima posizione conterra' l'indice della fine della coda
    *in = 0;
    *out = 0;
    for (i = 0; i < howmany; i++) {
        number = rand() % 500;
        WAIT(sems, S_EMPTY);                                                // diminuisce le posizioni vuote
        WAIT(sems, S_MUTEX);                                                // entra nella sezione critica
        p[*in] = number;                                                    // scrive il numero nella coda
        *in = (*in + 1) % DIM_BUFFER;                                       // sposta l'indice in avanti (ciclicamente)
        len = (*in > *out ? (*in - *out) : (DIM_BUFFER - (*out - *in)));    // calcola in # di elementi in coda
        printf("Produttore %d: %d  \t(in=%d out=%d len=%d)\n", num, number, *in, *out, len);
        tot += number;
        SIGNAL(sems, S_MUTEX);  // esce dalla sezione critica
        SIGNAL(sems, S_FULL);   // incrementa le posizioni piene
        usleep(rand() % 40000);
    }
    printf("Produttore %d: totale finale=%ld\n", num, tot);
    exit(0);
}
// legge i numeri dalla coda e li stampa a video
void consumatore(int shm, int sems, int num, int howmany) {
    int *p, *in, *out;
    int i, number, len;
    long tot = 0;
    if ((p = (int *)shmat(shm, NULL, 0)) == (int *)-1) {   // attacca la memoria condivisia
        perror("shmat");
        exit(1);
    }
    in = p + DIM_BUFFER;        // la penultima posizione conterra' l'indice dell'inizio coda
    out = p + DIM_BUFFER + 1;   // l'ultima posizione conterra' l'indice della fine della coda
    for (i = 0; i < howmany; i++) {
        WAIT(sems, S_FULL);                                                 // diminuisce le posizioni piene
        WAIT(sems, S_MUTEX);                                                // entra nella sezione critica
        number = p[*out];                                                   // legge il numero dalla coda
        *out = (*out + 1) % DIM_BUFFER;                                     // sposta l'indice in avanti (ciclicamente)
        len = (*in >= *out ? (*in - *out) : (DIM_BUFFER - (*out - *in)));   // calcola in # di elementi in coda
        printf("Consumatore %d: %d  \t(in=%d out=%d len=%d)\n", num, number, *in, *out, len);
        tot += number;
        SIGNAL(sems, S_MUTEX);  // esce dalla sezione critica
        SIGNAL(sems, S_EMPTY);  // incrementa le posizioni vuote
        usleep(rand() % 50000);
    }
    printf("Consumatore %d: totale finale=%ld\n", num, tot);
    exit(0);
}
int main() {
    int id_shm, id_sems;
    // crea l'area di memoria condivisa per i DIM_BUFFER numeri e due variabili aggiuntive
    if ((id_shm = shmget(IPC_PRIVATE, (DIM_BUFFER + 2) * sizeof(int), IPC_CREAT | 0600)) == -1) {
        perror("shmget");
        exit(1);
    }
    // crea i 3 semafori (S_MUTEX, S_EMPTY, S_FULL)
    if ((id_sems = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600)) == -1) {
        perror("semget");
        exit(1);
    }
    // imposta i valori iniziali dei semafori
    semctl(id_sems, S_MUTEX, SETVAL, 1);
    semctl(id_sems, S_EMPTY, SETVAL, DIM_BUFFER);
    semctl(id_sems, S_FULL, SETVAL, 0);
    // crea i due processi figli: produttore e consumatore
    if (fork() != 0) {
        if (fork() != 0) {
            if (fork() != 0) {
                // corpo del padre
                wait(NULL);
                wait(NULL);
                wait(NULL);
            } else {
                produttore(id_shm, id_sems, 1, HOW_MANY * 2);
            }
        } else {
            consumatore(id_shm, id_sems, 2, HOW_MANY);
        }
    } else {
        consumatore(id_shm, id_sems, 1, HOW_MANY);
    }
    // distrugge memoria condivisa e semaforo
    shmctl(id_shm, IPC_RMID, NULL);
    semctl(id_sems, 0, IPC_RMID, 0);
    exit(0);
}