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) {
30 INFO2("Thread %d gets hungry (lunch #%d)",id,lunch);
31 xbt_mutex_lock(mutex);
32 while (state[(id + (philosopher_amount-1))%philosopher_amount] == EATING ||
33 state[(id + 1)%philosopher_amount] == EATING)
35 xbt_cond_wait(forks[id], mutex);
39 xbt_assert1(state[(id + (philosopher_amount-1))%philosopher_amount] == THINKING &&
40 state[(id + 1)%philosopher_amount] == THINKING ,
41 "Philosopher %d eats at the same time that one of its neighbors!!!",id);
43 xbt_mutex_unlock(mutex);
44 INFO1("Thread %d eats",id);
46 static void putdown(int id) {
47 INFO1("Thread %d is full",id);
48 xbt_mutex_lock(mutex);
50 xbt_cond_signal(forks[(id+(philosopher_amount-1))%philosopher_amount]);
51 xbt_cond_signal(forks[(id+1)%philosopher_amount]);
53 xbt_mutex_unlock(mutex);
54 INFO1("Thread %d thinks",id);
58 * Some additionnal code to let the father wait the childs
66 /* Code ran by each thread */
67 static void philo_thread(void *arg) {
71 for (i=0; i<lunch_amount; i++) {
73 gras_os_sleep(id / 100.0); /* each philosopher sleeps and eat a time related to its ID */
75 gras_os_sleep(id / 100.0);
78 xbt_mutex_lock(mut_end);
80 xbt_cond_signal(cond_end);
81 xbt_mutex_unlock(mut_end);
83 /* Enter an endless loop to test the killing facilities */
84 INFO1("Thread %d tries to enter the dead-end; hopefully, the master will cancel it",id);
85 xbt_mutex_lock(dead_end);
86 INFO1("Oops, thread %d reached the dead-end. Cancelation failed",id);
89 int philosopher (int argc,char *argv[]);
90 int philosopher (int argc,char *argv[]) {
92 xbt_thread_t *philosophers;
94 gras_init(&argc,argv);
95 xbt_assert0(argc>=2,"This program expects one argument (the amount of philosophers)");
97 /* initializations of the philosopher mecanisms */
98 philosopher_amount = atoi(argv[1]);
99 state = xbt_new0(int,philosopher_amount);
100 id = xbt_new0(int,philosopher_amount);
101 forks = xbt_new(xbt_cond_t,philosopher_amount);
102 philosophers = xbt_new(xbt_thread_t,philosopher_amount);
104 mutex = xbt_mutex_init();
105 for (i=0; i<philosopher_amount; i++) {
108 forks[i] = xbt_cond_init();
111 /* setup the ending mecanism */
112 running_threads = philosopher_amount;
113 cond_end = xbt_cond_init();
114 mut_end = xbt_mutex_init();
115 dead_end = xbt_mutex_init();
116 xbt_mutex_lock(dead_end);
118 INFO2("Spawn the %d threads (%d lunches scheduled)", philosopher_amount, lunch_amount);
120 for (i=0; i<philosopher_amount; i++) {
121 char *name = bprintf("thread %d",i);
122 philosophers[i] = xbt_thread_create(name,philo_thread,&id[i]);
127 xbt_mutex_lock(mut_end);
128 while (running_threads)
129 xbt_cond_wait(cond_end,mut_end);
130 xbt_mutex_unlock(mut_end);
132 INFO0("Cancel all childs");
133 /* nuke them threads */
134 for (i=0; i<philosopher_amount; i++) {
135 xbt_thread_cancel(philosophers[i]);
138 xbt_mutex_unlock(dead_end);