1 /* philosopher - classical dinning philosopher as a demo xbt syncro stuff */
3 /* Copyright (c) 2007 Martin Quinson. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "xbt/synchro.h"
11 XBT_LOG_NEW_DEFAULT_CATEGORY(philo, "Logs of this example");
14 /** Philosopher logic **/
15 int lunch_amount = 10;
16 int philosopher_amount;
25 int *id; /* to pass a pointer to the threads without race condition */
27 static void pickup(int id, int lunch)
29 INFO2("Thread %d gets hungry (lunch #%d)", id, lunch);
30 xbt_mutex_acquire(mutex);
31 while (state[(id + (philosopher_amount - 1)) % philosopher_amount] == EATING
32 || state[(id + 1) % philosopher_amount] == EATING) {
33 xbt_cond_wait(forks[id], mutex);
37 xbt_assert1(state[(id + (philosopher_amount - 1)) % philosopher_amount] ==
39 && state[(id + 1) % philosopher_amount] == THINKING,
40 "Philosopher %d eats at the same time that one of its neighbors!!!",
43 xbt_mutex_release(mutex);
44 INFO1("Thread %d eats", id);
47 static void putdown(int id)
49 INFO1("Thread %d is full", id);
50 xbt_mutex_acquire(mutex);
53 [(id + (philosopher_amount - 1)) % philosopher_amount]);
54 xbt_cond_signal(forks[(id + 1) % philosopher_amount]);
56 xbt_mutex_release(mutex);
57 INFO1("Thread %d thinks", id);
61 * Some additionnal code to let the father wait the childs
69 /* Code ran by each thread */
70 static void philo_thread(void *arg)
72 int id = *(int *) arg;
75 for (i = 0; i < lunch_amount; i++) {
77 gras_os_sleep(id / 100.0); /* each philosopher sleeps and eat a time related to its ID */
79 gras_os_sleep(id / 100.0);
82 xbt_mutex_acquire(mut_end);
84 xbt_cond_signal(cond_end);
85 xbt_mutex_release(mut_end);
87 /* Enter an endless loop to test the killing facilities */
89 ("Thread %d tries to enter the dead-end; hopefully, the master will cancel it",
91 xbt_mutex_acquire(dead_end);
92 INFO1("Oops, thread %d reached the dead-end. Cancelation failed", id);
95 int philosopher(int argc, char *argv[]);
96 int philosopher(int argc, char *argv[])
99 xbt_thread_t *philosophers;
101 gras_init(&argc, argv);
102 xbt_assert0(argc >= 2,
103 "This program expects one argument (the amount of philosophers)");
105 /* initializations of the philosopher mecanisms */
106 philosopher_amount = atoi(argv[1]);
107 state = xbt_new0(int, philosopher_amount);
108 id = xbt_new0(int, philosopher_amount);
109 forks = xbt_new(xbt_cond_t, philosopher_amount);
110 philosophers = xbt_new(xbt_thread_t, philosopher_amount);
112 mutex = xbt_mutex_init();
113 for (i = 0; i < philosopher_amount; i++) {
116 forks[i] = xbt_cond_init();
119 /* setup the ending mecanism */
120 running_threads = philosopher_amount;
121 cond_end = xbt_cond_init();
122 mut_end = xbt_mutex_init();
123 dead_end = xbt_mutex_init();
124 xbt_mutex_acquire(dead_end);
126 INFO2("Spawn the %d threads (%d lunches scheduled)", philosopher_amount,
129 for (i = 0; i < philosopher_amount; i++) {
130 char *name = bprintf("thread %d", i);
131 philosophers[i] = xbt_thread_create(name, philo_thread, &id[i],0/*not joinable*/);
136 xbt_mutex_acquire(mut_end);
137 while (running_threads)
138 xbt_cond_wait(cond_end, mut_end);
139 xbt_mutex_release(mut_end);
141 INFO0("Cancel all childs");
142 /* nuke them threads */
143 for (i = 0; i < philosopher_amount; i++) {
144 xbt_thread_cancel(philosophers[i]);
147 xbt_mutex_release(dead_end);