/* Copyright (C) 2009 by Mattia Monga <mattia.monga@unimi.it> */
/* $Id$ */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>


void enter_section(int process, int* turn, int* interested)
{
        int other = 1 - process;
        interested[process] = 1;
        *turn = process;
        while  (*turn == process && interested[other]){ 
                printf("Busy waiting di %d\n", process);
        }
}

void leave_section(int process, int* interested)
{
        interested[process] = 0;
}

int run(const int p, void* s)
{
        int* shared = (int*)s; /* alias per comodita` */
        while (enter_section(p, &shared[1], &shared[2]), 
               shared[0] < 10) {
                sleep(1);
                printf("Processo figlio (%d). s = %d\n", 
                       getpid(), shared[0]);
                if (!(shared[0] < 10)){
                        printf("Corsa critica!!!!\n");
                        abort();
                }
                shared[0] += 1;
                leave_section(p, &shared[2]);
        }
        return 0;
}

int run0(void*s){ return run(0, s); }
int run1(void*s){ return run(1, s); }
        

int main(void){
 
        int shared[4] = {0 , 0, 0, 0};

        /* int clone(int (*fn)(void *), 
         *           void *child_stack, 
         *           int flags,
         *           void *arg); 
         * crea una copia del chiamante (con le caratteristiche 
         * specificate da flags) e lo esegue partendo da fn */
        if (clone(run0, /* il nuovo
                         * processo esegue run(shared), vedi quarto
                         * parametro */
                  malloc(4096)+4096,  /* lo stack del nuovo processo 
                                       *  (cresce verso il basso!) */
                  CLONE_VM | SIGCHLD, /* la (virtual) memory e` condivisa */
                  shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        if (clone(run1, malloc(4096)+4096,  CLONE_VM | SIGCHLD, shared) < 0){
                perror("Errore nella creazione");
                exit(1);
        } 

        /* Memoria condivisa: i due figli nell'insieme eseguono 10 o
         * 11 volte: e` possibile una corsa critica. Il padre
         * condivide shared[0] con i figli */

        while(shared[0] < 10) {
                sleep(1);
                printf("Processo padre. s = %d %d %d %d\n", 
                       shared[0],
                       shared[1],
                       shared[2],
                       shared[3]);
        }
        return 0;
}

    
        
  



/* Local Variables: */
/* compile-command: "make -k " */
/* End: */
