3 /* Copyright (c) 2007 Arnaud Legrand, Bruno Donnassolo.
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. */
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_synchro, simix,
14 "Logging specific to SIMIX (synchronization)");
17 /****************************** Synchronization *******************************/
19 /*********************************** Mutex ************************************/
22 * \brief Initialize a mutex.
24 * Allocs and creates the data for the mutex. It have to be called before the utilisation of the mutex.
27 smx_mutex_t SIMIX_mutex_init()
29 smx_mutex_t m = xbt_new0(s_smx_mutex_t,1);
30 s_smx_process_t p; /* useful to initialize sleeping swag */
31 /* structures initialization */
33 m->sleeping = xbt_swag_new(xbt_swag_offset(p, synchro_hookup));
38 * \brief Locks a mutex.
40 * Tries to lock a mutex, if the mutex isn't used yet, the process can continue its execution, else it'll be blocked here. You have to call #SIMIX_mutex_unlock to free the mutex.
41 * \param mutex The mutex
43 void SIMIX_mutex_lock(smx_mutex_t mutex)
45 smx_process_t self = SIMIX_process_self();
46 xbt_assert0((mutex != NULL), "Invalid parameters");
50 /* somebody using the mutex, block */
51 xbt_swag_insert(self, mutex->sleeping);
52 self->simdata->mutex = mutex;
53 /* wait for some process make the unlock and wake up me from mutex->sleeping */
55 self->simdata->mutex = NULL;
57 /* verify if the process was suspended */
58 while (self->simdata->suspended) {
72 * \brief Tries to lock a mutex.
74 * Tries to lock a mutex, return 1 if the mutex is free, 0 else. This function does not block the process if the mutex is used.
75 * \param mutex The mutex
76 * \return 1 - mutex free, 0 - mutex used
78 int SIMIX_mutex_trylock(smx_mutex_t mutex)
80 xbt_assert0((mutex != NULL), "Invalid parameters");
91 * \brief Unlocks a mutex.
93 * Unlocks the mutex and wakes up a process blocked on it. If there are no process sleeping, only sets the mutex as free.
94 * \param mutex The mutex
96 void SIMIX_mutex_unlock(smx_mutex_t mutex)
98 smx_process_t p; /*process to wake up */
100 xbt_assert0((mutex != NULL), "Invalid parameters");
102 if (xbt_swag_size(mutex->sleeping) > 0) {
103 p = xbt_swag_extract(mutex->sleeping);
105 xbt_swag_insert(p, simix_global->process_to_run);
108 /* nobody to wake up */
115 * \brief Destroys a mutex.
117 * Destroys and frees the mutex's memory.
118 * \param mutex A mutex
120 void SIMIX_mutex_destroy(smx_mutex_t mutex)
125 xbt_swag_free(mutex->sleeping);
131 /******************************** Conditional *********************************/
134 * \brief Initialize a condition.
136 * Allocs and creates the data for the condition. It have to be called before the utilisation of the condition.
137 * \return A condition
139 smx_cond_t SIMIX_cond_init()
141 smx_cond_t cond = xbt_new0(s_smx_cond_t,1);
144 cond->sleeping = xbt_swag_new(xbt_swag_offset(p,synchro_hookup));
145 cond->actions = xbt_fifo_new();
151 * \brief Signalizes a condition.
153 * Signalizes a condition and wakes up a sleping process. If there are no process sleeping, no action is done.
154 * \param cond A condition
156 void SIMIX_cond_signal(smx_cond_t cond)
158 DEBUG1("Signal condition %p",cond);
159 xbt_assert0((cond != NULL), "Invalid parameters");
160 smx_process_t proc = NULL;
162 if (xbt_swag_size(cond->sleeping) >= 1) {
163 proc = xbt_swag_extract(cond->sleeping);
164 xbt_swag_insert(proc, simix_global->process_to_run);
171 * \brief Waits on a condition.
173 * Blocks a process until the signal is called. This functions frees the mutex associated and locks it after its execution.
174 * \param cond A condition
175 * \param mutex A mutex
177 void SIMIX_cond_wait(smx_cond_t cond,smx_mutex_t mutex)
179 smx_action_t act_sleep;
180 xbt_assert0((mutex != NULL), "Invalid parameters");
182 DEBUG1("Wait condition %p",cond);
185 SIMIX_mutex_unlock(mutex);
186 /* create an action null only if there are no actions already on the condition, usefull if the host crashs */
187 if (xbt_fifo_size(cond->actions) ==0 ) {
188 act_sleep = SIMIX_action_sleep(SIMIX_host_self(), -1);
189 SIMIX_register_action_to_condition(act_sleep,cond);
190 SIMIX_register_condition_to_action(act_sleep,cond);
191 __SIMIX_cond_wait(cond);
192 xbt_fifo_pop(act_sleep->cond_list);
193 SIMIX_action_destroy(act_sleep);
196 __SIMIX_cond_wait(cond);
198 /* get the mutex again */
199 SIMIX_mutex_lock(cond->mutex);
204 xbt_fifo_t SIMIX_cond_get_actions(smx_cond_t cond)
206 xbt_assert0((cond != NULL), "Invalid parameters");
207 return cond->actions;
210 void __SIMIX_cond_wait(smx_cond_t cond)
212 smx_process_t self = SIMIX_process_self();
213 xbt_assert0((cond != NULL), "Invalid parameters");
217 self->simdata->cond = cond;
218 xbt_swag_insert(self, cond->sleeping);
220 self->simdata->cond = NULL;
221 while (self->simdata->suspended) {
229 * \brief Waits on a condition with timeout.
231 * Same behavior of #SIMIX_cond_wait, but waits a maximum time and throws an timeout_error if it happens.
232 * \param cond A condition
233 * \param mutex A mutex
234 * \param max_duration Timeout time
236 void SIMIX_cond_wait_timeout(smx_cond_t cond,smx_mutex_t mutex, double max_duration)
238 xbt_assert0((mutex != NULL), "Invalid parameters");
239 smx_action_t act_sleep;
241 DEBUG1("Timed wait condition %p",cond);
244 SIMIX_mutex_unlock(mutex);
245 if (max_duration >=0) {
246 act_sleep = SIMIX_action_sleep(SIMIX_host_self(), max_duration);
247 SIMIX_register_action_to_condition(act_sleep,cond);
248 SIMIX_register_condition_to_action(act_sleep,cond);
249 __SIMIX_cond_wait(cond);
250 xbt_fifo_remove(act_sleep->cond_list,cond);
251 if ( SIMIX_action_get_state(act_sleep) == SURF_ACTION_DONE) {
252 SIMIX_action_destroy(act_sleep);
253 THROW0(timeout_error,0,"Condition timeout");
256 SIMIX_action_destroy(act_sleep);
261 __SIMIX_cond_wait(cond);
263 /* get the mutex again */
264 SIMIX_mutex_lock(cond->mutex);
270 * \brief Broadcasts a condition.
272 * Signalizes a condition and wakes up ALL sleping process. If there are no process sleeping, no action is done.
273 * \param cond A condition
275 void SIMIX_cond_broadcast(smx_cond_t cond)
277 xbt_assert0((cond != NULL), "Invalid parameters");
278 smx_process_t proc = NULL;
279 smx_process_t proc_next = NULL;
281 DEBUG1("Broadcast condition %p",cond);
282 xbt_swag_foreach_safe(proc,proc_next,cond->sleeping) {
283 xbt_swag_remove(proc,cond->sleeping);
284 xbt_swag_insert(proc, simix_global->process_to_run);
291 * \brief Destroys a contidion.
293 * Destroys and frees the condition's memory.
294 * \param cond A condition
296 void SIMIX_cond_destroy(smx_cond_t cond)
298 DEBUG1("Destroy condition %p",cond);
302 xbt_fifo_item_t item = NULL;
303 smx_action_t action = NULL;
305 xbt_assert0( xbt_swag_size(cond->sleeping) == 0 , "Cannot destroy conditional since someone is still using it");
306 xbt_swag_free(cond->sleeping);
308 xbt_fifo_foreach(cond->actions,item,action,smx_action_t) {
309 SIMIX_unregister_condition_to_action(action, cond);
311 xbt_fifo_free(cond->actions);
318 * \brief Set a condition to an action
320 * Creates the "link" between an action and a condition. You have to call this function when you create an action and want to wait its ending.
321 * \param action SIMIX action
322 * \param cond SIMIX cond
324 void SIMIX_register_condition_to_action(smx_action_t action, smx_cond_t cond)
326 xbt_assert0( (action != NULL) && (cond != NULL), "Invalid parameters");
328 DEBUG2("Register condition %p to action %p",cond,action);
329 xbt_fifo_push(action->cond_list,cond);
333 * \brief Unset a condition to an action
335 * Destroys the "link" between an action and a condition.
336 * \param action SIMIX action
337 * \param cond SIMIX cond
339 void SIMIX_unregister_condition_to_action(smx_action_t action, smx_cond_t cond)
341 xbt_assert0( (action != NULL) && (cond != NULL), "Invalid parameters");
343 while(xbt_fifo_remove(action->cond_list,cond)) {}