/* Copyright (C) 2009 by Mattia Monga */ /* $Id$ */ #define _GNU_SOURCE #include #include #include #include #include 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 comodit\`a 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]); } leave_section(p, &shared[2]);// il test nel while \`e dopo enter\_section 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 con possibili corse critiche. 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: */