/* 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>

int run(void* s)
{
        int* shared = (int*)s; /* alias per comodita` */
        while (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;
        }
        return 0;
}


int main(void){
 
        int shared[2] = {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(run, /* 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(run, 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(1) {
                sleep(1);
                printf("Processo padre. s = %d\n", shared[0]);
        }
        return 0;
}

    
        
  



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