1 /* linux-dp.c --- dining philosophers, on LinuxThreads
2 Jim Blandy <jimb@cygnus.com> --- March 1999 */
4 /* It's okay to edit this file and shift line numbers around. The
5 tests use gdb_get_line_number to find source locations, so they
6 don't depend on having certain line numbers in certain places. */
13 #include <sys/types.h>
15 /* The number of philosophers at the table. */
19 If you want to lock a mutex M, all the mutexes you have locked
20 already must appear before M on this list.
25 fork_mutex[num_philosophers - 1]
30 /* You must hold this mutex while writing to stdout. */
31 pthread_mutex_t stdout_mutex;
33 /* You must hold this mutex while calling any of the random number
34 generation routines. */
35 pthread_mutex_t random_mutex;
37 /* array of mutexes, one for each fork; fork_mutex[i] is to the left
38 of philosopher i. A philosopher is holding fork i iff his/her
39 thread has locked fork_mutex[i]. */
40 pthread_mutex_t *fork_mutex;
42 /* array of threads, one representing each philosopher. */
43 pthread_t *philosophers;
52 fprintf (stderr, "out of memory\n");
60 shared_printf (char *format, ...)
64 va_start (ap, format);
65 pthread_mutex_lock (&stdout_mutex);
67 pthread_mutex_unlock (&stdout_mutex);
74 static unsigned int seed;
77 pthread_mutex_lock (&random_mutex);
78 result = rand_r (&seed);
79 pthread_mutex_unlock (&random_mutex);
84 my_usleep (long usecs)
86 struct timeval timeout;
88 timeout.tv_sec = usecs / 1000000;
89 timeout.tv_usec = usecs % 1000000;
91 select (0, 0, 0, 0, &timeout);
97 my_usleep ((shared_random () % 2000) * 100);
101 print_philosopher (int n, char left, char right)
105 shared_printf ("%*s%c %d %c\n", (n * 4) + 2, "", left, n, right);
109 philosopher (void *data)
111 int n = * (int *) data;
113 print_philosopher (n, '_', '_');
116 if (n == num_philosophers - 1)
119 /* The last philosopher is different. He goes for his right
120 fork first, so there is no cycle in the mutex graph. */
122 /* Grab the right fork. */
123 pthread_mutex_lock (&fork_mutex[(n + 1) % num_philosophers]);
124 print_philosopher (n, '_', '!');
127 /* Then grab the left fork. */
128 pthread_mutex_lock (&fork_mutex[n]);
129 print_philosopher (n, '!', '!');
132 print_philosopher (n, '_', '_');
133 pthread_mutex_unlock (&fork_mutex[n]);
134 pthread_mutex_unlock (&fork_mutex[(n + 1) % num_philosophers]);
141 /* Grab the left fork. */
142 pthread_mutex_lock (&fork_mutex[n]);
143 print_philosopher (n, '!', '_');
146 /* Then grab the right fork. */
147 pthread_mutex_lock (&fork_mutex[(n + 1) % num_philosophers]);
148 print_philosopher (n, '!', '!');
151 print_philosopher (n, '_', '_');
152 pthread_mutex_unlock (&fork_mutex[n]);
153 pthread_mutex_unlock (&fork_mutex[(n + 1) % num_philosophers]);
161 main (int argc, char **argv)
163 num_philosophers = 5;
165 /* Set up the mutexes. */
167 pthread_mutexattr_t ma;
170 pthread_mutexattr_init (&ma);
171 pthread_mutex_init (&stdout_mutex, &ma);
172 pthread_mutex_init (&random_mutex, &ma);
173 fork_mutex = xmalloc (num_philosophers * sizeof (fork_mutex[0]));
174 for (i = 0; i < num_philosophers; i++)
175 pthread_mutex_init (&fork_mutex[i], &ma);
176 pthread_mutexattr_destroy (&ma);
179 /* Set off the threads. */
182 int *numbers = xmalloc (num_philosophers * sizeof (*numbers));
185 philosophers = xmalloc (num_philosophers * sizeof (*philosophers));
187 pthread_attr_init (&ta);
189 for (i = 0; i < num_philosophers; i++)
192 /* linuxthreads.exp: create philosopher */
193 pthread_create (&philosophers[i], &ta, philosopher, &numbers[i]);
196 pthread_attr_destroy (&ta);
199 /* linuxthreads.exp: info threads 2 */
202 /* Drink yourself into oblivion. */