1 /* philosopher - classical dinning philosopher as a demo xbt syncro stuff */
3 /* Copyright (c) 2007, 2009, 2010. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
10 #include "xbt/synchro.h"
12 XBT_LOG_NEW_DEFAULT_CATEGORY(philo, "Logs of this example");
15 /** Philosopher logic **/
16 int lunch_amount = 10;
17 int philosopher_amount;
26 int *id; /* to pass a pointer to the threads without race condition */
28 static void pickup(int id, int lunch)
30 XBT_INFO("Thread %d gets hungry (lunch #%d)", id, lunch);
31 xbt_mutex_acquire(mutex);
32 while (state[(id + (philosopher_amount - 1)) % philosopher_amount] ==
33 EATING || state[(id + 1) % philosopher_amount] == EATING) {
34 xbt_cond_wait(forks[id], mutex);
38 xbt_assert1(state[(id + (philosopher_amount - 1)) % philosopher_amount]
40 && state[(id + 1) % philosopher_amount] == THINKING,
41 "Philosopher %d eats at the same time that one of its neighbors!!!",
44 xbt_mutex_release(mutex);
45 XBT_INFO("Thread %d eats", id);
48 static void putdown(int id)
50 XBT_INFO("Thread %d is full", id);
51 xbt_mutex_acquire(mutex);
54 [(id + (philosopher_amount - 1)) % philosopher_amount]);
55 xbt_cond_signal(forks[(id + 1) % philosopher_amount]);
57 xbt_mutex_release(mutex);
58 XBT_INFO("Thread %d thinks", id);
62 * Some additionnal code to let the father wait the childs
70 /* Code ran by each thread */
71 static void philo_thread(void *arg)
73 int id = *(int *) arg;
76 for (i = 0; i < lunch_amount; i++) {
78 gras_os_sleep(id / 100.0); /* each philosopher sleeps and eat a time related to its ID */
80 gras_os_sleep(id / 100.0);
83 xbt_mutex_acquire(mut_end);
85 xbt_cond_signal(cond_end);
86 xbt_mutex_release(mut_end);
88 /* Enter an endless loop to test the killing facilities */
90 ("Thread %d tries to enter the dead-end; hopefully, the master will cancel it",
92 xbt_mutex_acquire(dead_end);
93 XBT_INFO("Oops, thread %d reached the dead-end. Cancelation failed", id);
96 int philosopher(int argc, char *argv[]);
97 int philosopher(int argc, char *argv[])
100 xbt_thread_t *philosophers;
102 gras_init(&argc, argv);
103 xbt_assert0(argc >= 2,
104 "This program expects one argument (the amount of philosophers)");
106 /* initializations of the philosopher mecanisms */
107 philosopher_amount = atoi(argv[1]);
108 state = xbt_new0(int, philosopher_amount);
109 id = xbt_new0(int, philosopher_amount);
110 forks = xbt_new(xbt_cond_t, philosopher_amount);
111 philosophers = xbt_new(xbt_thread_t, philosopher_amount);
113 mutex = xbt_mutex_init();
114 for (i = 0; i < philosopher_amount; i++) {
117 forks[i] = xbt_cond_init();
120 /* setup the ending mecanism */
121 running_threads = philosopher_amount;
122 cond_end = xbt_cond_init();
123 mut_end = xbt_mutex_init();
124 dead_end = xbt_mutex_init();
125 xbt_mutex_acquire(dead_end);
127 XBT_INFO("Spawn the %d threads (%d lunches scheduled)", philosopher_amount,
130 for (i = 0; i < philosopher_amount; i++) {
131 char *name = bprintf("thread %d", i);
133 xbt_thread_create(name, philo_thread, &id[i],
134 0 /*not joinable */ );
139 xbt_mutex_acquire(mut_end);
140 while (running_threads)
141 xbt_cond_wait(cond_end, mut_end);
142 xbt_mutex_release(mut_end);
144 XBT_INFO("Cancel all childs");
145 /* nuke them threads */
146 for (i = 0; i < philosopher_amount; i++) {
147 xbt_thread_cancel(philosophers[i]);
150 xbt_mutex_release(dead_end);