/* chopsticks1.c chopstick management routines for Dining Philosophers example using processes This version uses usleep and busy-waiting in all processes. See also other version, which uses signals to wake up neighbors. */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include #include #include #include #include #include "chopsticks.h" #define LOCKFILENAME_LENGTH 8 #define CHECK(CALL)\ if ((CALL)) {\ perror (#CALL);\ exit (-1);\ } char * lockfilename[NTHREADS]; int lockfd[NTHREADS]; void lock (int i) { int fildes; while ((fildes = open (lockfilename[i], O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) == -1) { if (errno != EEXIST) chopsticks_emergency_stop(); CHECK (usleep (100)); /* sleep for 100 microseconds */ } close (fildes); } void unlock (int i) { CHECK (unlink (lockfilename[i]) == -1); } void chopsticks_init() { int i; for (i = 0; i < NTHREADS; i++) { lockfilename[i] = (char *) malloc (LOCKFILENAME_LENGTH); memset ((void *) lockfilename[i], 0, LOCKFILENAME_LENGTH); sprintf (lockfilename[i], "LCK%d5", i); } } void chopsticks_take (int i) { if (i == (NTHREADS - 1)) { lock (0); lock (NTHREADS - 1); } else { lock (i); lock ((i + 1) % NTHREADS); } } void chopsticks_put (int i) { unlock (i); unlock ((i + 1) % NTHREADS); } void chopsticks_finalize () { int i; for (i = 0; i < NTHREADS; i++) { unlink (lockfilename[i]); /* ignore result intentionally */ } } void chopsticks_emergency_stop() { fprintf (stderr, "*** EMERGENCY STOP***\n"); chopsticks_finalize (); /* kill self and all other members of the current process group */ kill (SIGKILL, 0); fprintf (stderr, "should never get here\n"); exit (-1); }