Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
5095a5eb8cc13f534f1216431e087c238156c20f
[simgrid.git] / examples / gras / synchro / philosopher.c
1 /* $Id$ */
2
3 /* philosopher - classical dinning philosopher as a demo xbt syncro stuff   */
4
5 /* Copyright (c) 2007 Martin Quinson. All rights reserved.                  */
6
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. */
9
10 #include "gras.h"
11 #include "xbt/synchro.h"
12
13 XBT_LOG_NEW_DEFAULT_CATEGORY(philo,"Logs of this example");
14
15
16 /** Philosopher logic **/
17 int lunch_amount = 10;
18 int philosopher_amount;
19
20 xbt_mutex_t mutex;
21 xbt_cond_t *forks;
22
23 #define THINKING 0
24 #define EATING 1
25 int *state;
26
27 int *id; /* to pass a pointer to the threads without race condition */
28
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) 
34      {
35         xbt_cond_wait(forks[id], mutex);
36      }
37    
38    state[id] = EATING;
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);
42         
43    xbt_mutex_unlock(mutex);
44    INFO1("Thread %d eats",id);
45 }
46 static void putdown(int id)  {
47    INFO1("Thread %d is full",id);
48    xbt_mutex_lock(mutex);
49    state[id] = THINKING;
50    xbt_cond_signal(forks[(id+(philosopher_amount-1))%philosopher_amount]);
51    xbt_cond_signal(forks[(id+1)%philosopher_amount]);
52    
53    xbt_mutex_unlock(mutex);
54    INFO1("Thread %d thinks",id);
55 }
56
57 /*
58  * Some additionnal code to let the father wait the childs
59  */
60 xbt_mutex_t mut_end;
61 xbt_cond_t cond_end;
62 int running_threads;
63
64 xbt_mutex_t dead_end;
65
66 /* Code ran by each thread */
67 static void philo_thread(void *arg) {
68    int id = *(int*)arg;
69    int i;
70    
71    for (i=0; i<lunch_amount; i++) {
72       pickup(id,i);
73       gras_os_sleep(id / 100.0); /* each philosopher sleeps and eat a time related to its ID */
74       putdown(id);
75       gras_os_sleep(id / 100.0);
76    }
77    
78    xbt_mutex_lock(mut_end);
79    running_threads--;
80    xbt_cond_signal(cond_end);
81    xbt_mutex_unlock(mut_end);
82
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);
87 }
88
89 int philosopher (int argc,char *argv[]);
90 int philosopher (int argc,char *argv[]) {
91   int i;
92   xbt_thread_t *philosophers;
93    
94   gras_init(&argc,argv);
95   xbt_assert0(argc>=2,"This program expects one argument (the amount of philosophers)");
96
97   INFO0("Wait 1 sec to check that gras_os_sleep do works");
98   gras_os_sleep(1);
99    
100   /* initializations of the philosopher mecanisms */
101   philosopher_amount = atoi(argv[1]);
102   state = xbt_new0(int,philosopher_amount); 
103   id = xbt_new0(int,philosopher_amount); 
104   forks = xbt_new(xbt_cond_t,philosopher_amount);
105   philosophers = xbt_new(xbt_thread_t,philosopher_amount);
106      
107   mutex = xbt_mutex_init();
108   for (i=0; i<philosopher_amount; i++) {
109      state[i] = THINKING;
110      id[i] = i;
111      forks[i] = xbt_cond_init();
112   }
113    
114   /* setup the ending mecanism */
115   running_threads = philosopher_amount; 
116   cond_end = xbt_cond_init();
117   mut_end = xbt_mutex_init();
118   dead_end = xbt_mutex_init();
119   xbt_mutex_lock(dead_end);
120   
121   INFO0("Enough waiting, spawn the threads");
122   /* spawn threads */
123   for (i=0; i<philosopher_amount; i++) {
124      char *name = bprintf("thread %d",i);
125      philosophers[i] = xbt_thread_create(name,philo_thread,&id[i]);
126      free(name);
127   }
128   
129   /* wait for them */
130   xbt_mutex_lock(mut_end);
131   while (running_threads) 
132      xbt_cond_wait(cond_end,mut_end);
133   xbt_mutex_unlock(mut_end);
134        
135   INFO0("Cancel all childs");
136   /* nuke them threads */
137   for (i=0; i<philosopher_amount; i++) {
138     INFO1("Canceling %p",philosophers[i]);
139      xbt_thread_cancel(philosophers[i]);
140   }
141
142   xbt_mutex_unlock(dead_end);
143   gras_exit();
144   return 0;
145 }