3 /* philosopher - classical dinning philosopher as a demo xbt syncro stuff */
5 /* Copyright (c) 2007 Martin Quinson. All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include "xbt/synchro.h"
13 XBT_LOG_NEW_DEFAULT_CATEGORY(philo, "Logs of this example");
16 /** Philosopher logic **/
17 int lunch_amount = 10;
18 int philosopher_amount;
27 int *id; /* to pass a pointer to the threads without race condition */
29 static void pickup(int id, int lunch)
31 INFO2("Thread %d gets hungry (lunch #%d)", id, lunch);
32 xbt_mutex_acquire(mutex);
33 while (state[(id + (philosopher_amount - 1)) % philosopher_amount] == EATING
34 || state[(id + 1) % philosopher_amount] == EATING) {
35 xbt_cond_wait(forks[id], mutex);
39 xbt_assert1(state[(id + (philosopher_amount - 1)) % philosopher_amount] ==
41 && state[(id + 1) % philosopher_amount] == THINKING,
42 "Philosopher %d eats at the same time that one of its neighbors!!!",
45 xbt_mutex_release(mutex);
46 INFO1("Thread %d eats", id);
49 static void putdown(int id)
51 INFO1("Thread %d is full", id);
52 xbt_mutex_acquire(mutex);
55 [(id + (philosopher_amount - 1)) % philosopher_amount]);
56 xbt_cond_signal(forks[(id + 1) % philosopher_amount]);
58 xbt_mutex_release(mutex);
59 INFO1("Thread %d thinks", id);
63 * Some additionnal code to let the father wait the childs
71 /* Code ran by each thread */
72 static void philo_thread(void *arg)
74 int id = *(int *) arg;
77 for (i = 0; i < lunch_amount; i++) {
79 gras_os_sleep(id / 100.0); /* each philosopher sleeps and eat a time related to its ID */
81 gras_os_sleep(id / 100.0);
84 xbt_mutex_acquire(mut_end);
86 xbt_cond_signal(cond_end);
87 xbt_mutex_release(mut_end);
89 /* Enter an endless loop to test the killing facilities */
91 ("Thread %d tries to enter the dead-end; hopefully, the master will cancel it",
93 xbt_mutex_acquire(dead_end);
94 INFO1("Oops, thread %d reached the dead-end. Cancelation failed", id);
97 int philosopher(int argc, char *argv[]);
98 int philosopher(int argc, char *argv[])
101 xbt_thread_t *philosophers;
103 gras_init(&argc, argv);
104 xbt_assert0(argc >= 2,
105 "This program expects one argument (the amount of philosophers)");
107 /* initializations of the philosopher mecanisms */
108 philosopher_amount = atoi(argv[1]);
109 state = xbt_new0(int, philosopher_amount);
110 id = xbt_new0(int, philosopher_amount);
111 forks = xbt_new(xbt_cond_t, philosopher_amount);
112 philosophers = xbt_new(xbt_thread_t, philosopher_amount);
114 mutex = xbt_mutex_init();
115 for (i = 0; i < philosopher_amount; i++) {
118 forks[i] = xbt_cond_init();
121 /* setup the ending mecanism */
122 running_threads = philosopher_amount;
123 cond_end = xbt_cond_init();
124 mut_end = xbt_mutex_init();
125 dead_end = xbt_mutex_init();
126 xbt_mutex_acquire(dead_end);
128 INFO2("Spawn the %d threads (%d lunches scheduled)", philosopher_amount,
131 for (i = 0; i < philosopher_amount; i++) {
132 char *name = bprintf("thread %d", i);
133 philosophers[i] = xbt_thread_create(name, philo_thread, &id[i],0/*not joinable*/);
138 xbt_mutex_acquire(mut_end);
139 while (running_threads)
140 xbt_cond_wait(cond_end, mut_end);
141 xbt_mutex_release(mut_end);
143 INFO0("Cancel all childs");
144 /* nuke them threads */
145 for (i = 0; i < philosopher_amount; i++) {
146 xbt_thread_cancel(philosophers[i]);
149 xbt_mutex_release(dead_end);