Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
No need to lock on request pop.
[simgrid.git] / src / simix / smx_network.c
1 /* Copyright (c) 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "private.h"
8 #include "xbt/log.h"
9 #include "mc/mc.h"
10 #include "xbt/dict.h"
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_network, simix,
13                                 "Logging specific to SIMIX (network)");
14
15 static xbt_dict_t rdv_points = NULL;
16
17 static XBT_INLINE void SIMIX_comm_start(smx_action_t action);
18 static void SIMIX_comm_finish(smx_action_t action);
19 static void SIMIX_waitany_req_remove_from_actions(smx_req_t req);
20 static void SIMIX_comm_copy_data(smx_action_t comm);
21 static smx_action_t SIMIX_comm_new(e_smx_comm_type_t type);
22 static XBT_INLINE void SIMIX_comm_wait_for_completion(smx_action_t comm,
23                                                       double timeout);
24 static XBT_INLINE void SIMIX_rdv_push(smx_rdv_t rdv, smx_action_t comm);
25 static XBT_INLINE void SIMIX_rdv_remove(smx_rdv_t rdv, smx_action_t comm);
26 static smx_action_t SIMIX_rdv_get_request(smx_rdv_t rdv, e_smx_comm_type_t type,
27                                                                                   int (*match_fun)(void *, void *), void *);
28 static void SIMIX_rdv_free(void *data);
29
30 void SIMIX_network_init(void)
31 {
32   rdv_points = xbt_dict_new();
33 }
34
35 void SIMIX_network_exit(void)
36 {
37   xbt_dict_free(&rdv_points);
38 }
39
40 /******************************************************************************/
41 /*                           Rendez-Vous Points                               */
42 /******************************************************************************/
43
44 smx_rdv_t SIMIX_rdv_create(const char *name)
45 {
46   /* two processes may have pushed the same rdv_create request at the same time */
47   smx_rdv_t rdv = name ? xbt_dict_get_or_null(rdv_points, name) : NULL;
48
49   if (!rdv) {
50     rdv = xbt_new0(s_smx_rvpoint_t, 1);
51     rdv->name = name ? xbt_strdup(name) : NULL;
52     rdv->comm_fifo = xbt_fifo_new();
53
54     if (name)
55       xbt_dict_set(rdv_points, name, rdv, SIMIX_rdv_free);
56   }
57   return rdv;
58 }
59
60 void SIMIX_rdv_destroy(smx_rdv_t rdv)
61 {
62   if (rdv->name)
63     xbt_dict_remove(rdv_points, rdv->name); 
64 }
65
66 void SIMIX_rdv_free(void *data)
67 {
68   smx_rdv_t rdv = (smx_rdv_t) data;
69   if (rdv->name)
70     xbt_free(rdv->name);
71   xbt_fifo_free(rdv->comm_fifo);
72   xbt_free(rdv);  
73 }
74
75 smx_rdv_t SIMIX_rdv_get_by_name(const char *name)
76 {
77   return xbt_dict_get_or_null(rdv_points, name);
78 }
79
80 int SIMIX_rdv_comm_count_by_host(smx_rdv_t rdv, smx_host_t host)
81 {
82   smx_action_t comm = NULL;
83   xbt_fifo_item_t item = NULL;
84   int count = 0;
85
86   xbt_fifo_foreach(rdv->comm_fifo, item, comm, smx_action_t) {
87     if (comm->comm.src_proc->smx_host == host)
88       count++;
89   }
90
91   return count;
92 }
93
94 smx_action_t SIMIX_rdv_get_head(smx_rdv_t rdv)
95 {
96   return xbt_fifo_get_item_content(xbt_fifo_get_first_item(rdv->comm_fifo));
97 }
98
99 /**
100  *  \brief Push a communication request into a rendez-vous point
101  *  \param rdv The rendez-vous point
102  *  \param comm The communication request
103  */
104 static XBT_INLINE void SIMIX_rdv_push(smx_rdv_t rdv, smx_action_t comm)
105 {
106   xbt_fifo_push(rdv->comm_fifo, comm);
107   comm->comm.rdv = rdv;
108 }
109
110 /**
111  *  \brief Remove a communication request from a rendez-vous point
112  *  \param rdv The rendez-vous point
113  *  \param comm The communication request
114  */
115 static XBT_INLINE void SIMIX_rdv_remove(smx_rdv_t rdv, smx_action_t comm)
116 {
117   xbt_fifo_remove(rdv->comm_fifo, comm);
118   comm->comm.rdv = NULL;
119 }
120
121 /**
122  *  \brief Checks if there is a communication request queued in a rendez-vous matching our needs
123  *  \param type The type of communication we are looking for (comm_send, comm_recv)
124  *  \return The communication request if found, NULL otherwise
125  */
126 smx_action_t SIMIX_rdv_get_request(smx_rdv_t rdv, e_smx_comm_type_t type,
127                                                                    int (*match_fun)(void *, void *), void *data)
128 {
129   smx_action_t req;
130   xbt_fifo_item_t item;
131
132   xbt_fifo_foreach(rdv->comm_fifo, item, req, smx_action_t){
133         if(req->comm.type == type && (!match_fun || match_fun(data, req->comm.data))){
134           xbt_fifo_remove_item(rdv->comm_fifo, item);
135           req->comm.refcount++;
136           req->comm.rdv = NULL;
137           return req;
138         }
139   }
140
141   DEBUG0("Communication request not found");
142   return NULL;
143 }
144
145 /******************************************************************************/
146 /*                            Comunication Actions                            */
147 /******************************************************************************/
148
149 /**
150  *  \brief Creates a new comunicate action
151  *  \param type The type of request (comm_send, comm_recv)
152  *  \return The new comunicate action
153  */
154 smx_action_t SIMIX_comm_new(e_smx_comm_type_t type)
155 {
156   smx_action_t act;
157
158   /* alloc structures */
159   act = xbt_new0(s_smx_action_t, 1);
160   act->type = SIMIX_ACTION_COMMUNICATE;
161   act->state = SIMIX_WAITING;
162   act->request_list = xbt_fifo_new();
163
164   /* set communication */
165   act->comm.type = type;
166   act->comm.refcount = 1;
167
168 #ifdef HAVE_TRACING
169   act->category = NULL;
170 #endif
171
172   DEBUG1("Create communicate action %p", act);
173
174   return act;
175 }
176
177 /**
178  *  \brief Destroy a communicate action
179  *  \param action The communicate action to be destroyed
180  */
181 void SIMIX_comm_destroy(smx_action_t action)
182 {
183   DEBUG1("Destroy action %p", action);
184
185   if (action->comm.refcount <= 0)
186     xbt_die(bprintf("the refcount of comm %p is already 0 before decreasing it. That's a bug!",action));
187
188 #ifdef HAVE_LATENCY_BOUND_TRACKING
189   //save is latency limited flag to use afterwards
190   if (action->comm.surf_comm) {
191     DEBUG2("adding key %p with latency limited value %d to the dict", action,
192            SIMIX_comm_is_latency_bounded(action));
193     xbt_dicti_set(simix_global->latency_limited_dict, (uintptr_t) action,
194                   SIMIX_comm_is_latency_bounded(action));
195   }
196 #endif
197
198   action->comm.refcount--;
199   if (action->comm.refcount > 0)
200     return;
201   VERB2("Really free communication %p; refcount is now %d", action,
202         action->comm.refcount);
203
204 #ifdef HAVE_TRACING
205   TRACE_smx_action_destroy(action);
206 #endif
207
208   if (action->name)
209     xbt_free(action->name);
210
211   xbt_fifo_free(action->request_list);
212
213   SIMIX_comm_destroy_internal_actions(action);
214
215   xbt_free(action);
216 }
217
218 void SIMIX_comm_destroy_internal_actions(smx_action_t action)
219 {
220   if (action->comm.surf_comm){
221     action->comm.surf_comm->model_type->action_unref(action->comm.surf_comm);
222     action->comm.surf_comm = NULL;
223   }
224
225   if (action->comm.src_timeout){
226     action->comm.src_timeout->model_type->action_unref(action->comm.src_timeout);
227     action->comm.src_timeout = NULL;
228   }
229
230   if (action->comm.dst_timeout){
231     action->comm.dst_timeout->model_type->action_unref(action->comm.dst_timeout);
232     action->comm.dst_timeout = NULL;
233   }
234 }
235
236 smx_action_t SIMIX_comm_isend(smx_process_t src_proc, smx_rdv_t rdv,
237                               double task_size, double rate,
238                               void *src_buff, size_t src_buff_size,
239                               int (*match_fun)(void *, void *), void *data)
240 {
241   smx_action_t action;
242
243   /* Look for communication request matching our needs.
244      If it is not found then create it and push it into the rendez-vous point */
245   action = SIMIX_rdv_get_request(rdv, SIMIX_COMM_RECEIVE, match_fun, data);
246
247   if (!action) {
248     action = SIMIX_comm_new(SIMIX_COMM_SEND);
249     SIMIX_rdv_push(rdv, action);
250   } else {
251     action->state = SIMIX_READY;
252     action->comm.type = SIMIX_COMM_READY;
253   }
254
255   /* Setup the communication request */
256   action->comm.src_proc = src_proc;
257   action->comm.task_size = task_size;
258   action->comm.rate = rate;
259   action->comm.src_buff = src_buff;
260   action->comm.src_buff_size = src_buff_size;
261   action->comm.data = data;
262
263   if (MC_IS_ENABLED) {
264     action->state = SIMIX_RUNNING;
265     return action;
266   }
267
268   SIMIX_comm_start(action);
269   return action;
270 }
271
272 smx_action_t SIMIX_comm_irecv(smx_process_t dst_proc, smx_rdv_t rdv,
273                       void *dst_buff, size_t *dst_buff_size,
274                       int (*match_fun)(void *, void *), void *data)
275 {
276   smx_action_t action;
277
278   /* Look for communication request matching our needs.
279    * If it is not found then create it and push it into the rendez-vous point
280    */
281   action = SIMIX_rdv_get_request(rdv, SIMIX_COMM_SEND, match_fun, data);
282
283   if (!action) {
284     action = SIMIX_comm_new(SIMIX_COMM_RECEIVE);
285     SIMIX_rdv_push(rdv, action);
286   } else {
287     action->state = SIMIX_READY;
288     action->comm.type = SIMIX_COMM_READY;
289   }
290
291   /* Setup communication request */
292   action->comm.dst_proc = dst_proc;
293   action->comm.dst_buff = dst_buff;
294   action->comm.dst_buff_size = dst_buff_size;
295
296   if (MC_IS_ENABLED) {
297     action->state = SIMIX_RUNNING;
298     return action;
299   }
300
301   SIMIX_comm_start(action);
302   return action;
303 }
304
305 void SIMIX_pre_comm_wait(smx_req_t req)
306 {
307   smx_action_t action = req->comm_wait.comm;
308   double timeout = req->comm_wait.timeout;
309   surf_action_t sleep;
310
311   /* Associate this request to the action */
312   xbt_fifo_push(action->request_list, req);
313   req->issuer->waiting_action = action;
314
315   if (MC_IS_ENABLED){
316     action->state = SIMIX_DONE;
317     SIMIX_comm_finish(action);
318   }
319
320   /* If the action has already finish perform the error handling, */
321   /* otherwise set up a waiting timeout on the right side         */
322   if (action->state != SIMIX_WAITING && action->state != SIMIX_RUNNING) {
323     SIMIX_comm_finish(action);
324   } else { /* if (timeout >= 0) { we need a surf sleep action even when there is no timeout, otherwise surf won't tell us when the host fails */
325     sleep = surf_workstation_model->extension.workstation.sleep(req->issuer->smx_host->host, timeout);
326     surf_workstation_model->action_data_set(sleep, action);
327
328     if (req->issuer == action->comm.src_proc)
329       action->comm.src_timeout = sleep;
330     else
331       action->comm.dst_timeout = sleep;
332   }
333 }
334
335 void SIMIX_pre_comm_test(smx_req_t req)
336 {
337   smx_action_t action = req->comm_test.comm;
338   req->comm_test.result = (action->state != SIMIX_WAITING && action->state != SIMIX_RUNNING);
339
340   if (req->comm_test.result) {
341     xbt_fifo_push(action->request_list, req);
342     SIMIX_comm_finish(action);
343   }
344   else {
345     SIMIX_request_answer(req);
346   }
347 }
348
349 void SIMIX_pre_comm_testany(smx_req_t req)
350 {
351   unsigned int cursor;
352   smx_action_t action;
353   req->comm_testany.result = -1;
354   xbt_dynar_foreach(req->comm_testany.comms,cursor,action) {
355     if (action->state != SIMIX_WAITING && action->state != SIMIX_RUNNING) {
356       req->comm_testany.result = cursor;
357       xbt_fifo_push(action->request_list, req);
358       SIMIX_comm_finish(action);
359       break;
360     }
361   }
362   SIMIX_request_answer(req);
363 }
364
365 void SIMIX_pre_comm_waitany(smx_req_t req)
366 {
367   smx_action_t action;
368   unsigned int cursor = 0;
369   xbt_dynar_t actions = req->comm_waitany.comms;
370   xbt_dynar_foreach(actions, cursor, action){
371     /* Associate this request to the action */
372     xbt_fifo_push(action->request_list, req);
373     if (action->state != SIMIX_WAITING && action->state != SIMIX_RUNNING){
374       SIMIX_comm_finish(action);
375       break;
376     }
377   }
378 }
379
380 void SIMIX_waitany_req_remove_from_actions(smx_req_t req)
381 {
382   smx_action_t action;
383   unsigned int cursor = 0;
384   xbt_dynar_t actions = req->comm_waitany.comms;
385
386   xbt_dynar_foreach(actions, cursor, action){
387     xbt_fifo_remove(action->request_list, req);
388   }
389 }
390
391 /**
392  *  \brief Start the simulation of a communication request
393  *  \param action The communication action
394  */
395 static XBT_INLINE void SIMIX_comm_start(smx_action_t action)
396 {
397   /* If both the sender and the receiver are already there, start the communication */
398   if (action->state == SIMIX_READY) {
399     smx_host_t sender = action->comm.src_proc->smx_host;
400     smx_host_t receiver = action->comm.dst_proc->smx_host;
401
402     DEBUG3("Starting communication %p from '%s' to '%s'", action,
403            SIMIX_host_get_name(sender), SIMIX_host_get_name(receiver));
404
405     action->comm.surf_comm = surf_workstation_model->extension.workstation.
406         communicate(sender->host, receiver->host, action->comm.task_size, action->comm.rate);
407
408     surf_workstation_model->action_data_set(action->comm.surf_comm, action);
409
410     action->state = SIMIX_RUNNING;
411
412 #ifdef HAVE_TRACING
413     TRACE_smx_action_communicate(action, action->comm.src_proc);
414 #endif
415
416     /* If a link is failed, detect it immediately */
417     if (surf_workstation_model->action_state_get(action->comm.surf_comm) == SURF_ACTION_FAILED) {
418       DEBUG2("Communication from '%s' to '%s' failed to start because of a link failure",
419           SIMIX_host_get_name(sender), SIMIX_host_get_name(receiver));
420       action->state = SIMIX_LINK_FAILURE;
421       SIMIX_comm_destroy_internal_actions(action);
422     }
423
424     /* If any of the process is suspend, create the action but stop its execution,
425        it will be restarted when the sender process resume */
426     if (SIMIX_process_is_suspended(action->comm.src_proc) ||
427         SIMIX_process_is_suspended(action->comm.dst_proc)) {
428       /* FIXME: check what should happen with the action state */
429       surf_workstation_model->suspend(action->comm.surf_comm);
430     }
431   }
432 }
433
434 void SIMIX_comm_finish(smx_action_t action)
435 {
436   smx_req_t req;
437
438   while ((req = xbt_fifo_shift(action->request_list))) {
439
440     /* If a waitany request is waiting for this action to finish, then remove
441        it from the other actions in the waitany list. Afterwards, get the
442        position of the actual action in the waitany request's actions dynar and
443        return it as the result of the call */
444     if (req->call == REQ_COMM_WAITANY) {
445       SIMIX_waitany_req_remove_from_actions(req);
446       req->comm_waitany.result = xbt_dynar_search(req->comm_waitany.comms, &action);
447     }
448
449     /* If the action is still in a rendez-vous point then remove from it */
450     if (action->comm.rdv)
451       SIMIX_rdv_remove(action->comm.rdv, action);
452
453     DEBUG1("SIMIX_comm_finish: action state = %d", action->state);
454
455     /* Check out for errors */
456     switch (action->state) {
457
458       case SIMIX_DONE:
459         DEBUG1("Communication %p complete!", action);
460         SIMIX_comm_copy_data(action);
461         break;
462
463       case SIMIX_SRC_TIMEOUT:
464         TRY {
465           THROW0(timeout_error, 0, "Communication timeouted because of sender");
466         }
467         CATCH(req->issuer->running_ctx->exception) {
468           req->issuer->doexception = 1;
469         }
470         break;
471
472       case SIMIX_DST_TIMEOUT:
473         TRY {
474           THROW0(timeout_error, 0, "Communication timeouted because of receiver");
475         }
476         CATCH(req->issuer->running_ctx->exception) {
477           req->issuer->doexception = 1;
478         }
479         break;
480
481       case SIMIX_SRC_HOST_FAILURE:
482         TRY {
483           if (req->issuer == action->comm.src_proc)
484             THROW0(host_error, 0, "Host failed");
485           else
486             THROW0(network_error, 0, "Remote peer failed");
487         }
488         CATCH(req->issuer->running_ctx->exception) {
489           req->issuer->doexception = 1;
490         }
491         break;
492
493       case SIMIX_DST_HOST_FAILURE:
494         TRY {
495           if (req->issuer == action->comm.dst_proc)
496             THROW0(host_error, 0, "Host failed");
497           else
498             THROW0(network_error, 0, "Remote peer failed");
499         }
500         CATCH(req->issuer->running_ctx->exception) {
501           req->issuer->doexception = 1;
502         }
503         break;
504
505       case SIMIX_LINK_FAILURE:
506         TRY {
507           DEBUG5("Link failure in action %p between '%s' and '%s': posting an exception to the issuer: %s (%p)",
508               action, action->comm.src_proc->smx_host->name, action->comm.dst_proc->smx_host->name,
509               req->issuer->name, req->issuer);
510           THROW0(network_error, 0, "Link failure");
511         }
512         CATCH(req->issuer->running_ctx->exception) {
513           req->issuer->doexception = 1;
514         }
515         break;
516
517       default:
518         THROW_IMPOSSIBLE;
519     }
520     req->issuer->waiting_action = NULL;
521     SIMIX_request_answer(req);
522   }
523 }
524
525 void SIMIX_post_comm(smx_action_t action)
526 {
527   /* Update action state */
528   if (action->comm.src_timeout &&
529      surf_workstation_model->action_state_get(action->comm.src_timeout) == SURF_ACTION_DONE)
530      action->state = SIMIX_SRC_TIMEOUT;
531   else if (action->comm.dst_timeout &&
532           surf_workstation_model->action_state_get(action->comm.dst_timeout) == SURF_ACTION_DONE)
533      action->state = SIMIX_DST_TIMEOUT;
534   else if (action->comm.src_timeout &&
535           surf_workstation_model->action_state_get(action->comm.src_timeout) == SURF_ACTION_FAILED)
536      action->state = SIMIX_SRC_HOST_FAILURE;
537   else if (action->comm.dst_timeout &&
538           surf_workstation_model->action_state_get(action->comm.dst_timeout) == SURF_ACTION_FAILED)
539      action->state = SIMIX_DST_HOST_FAILURE;
540   else if (action->comm.surf_comm &&
541           surf_workstation_model->action_state_get(action->comm.surf_comm) == SURF_ACTION_FAILED)
542      action->state = SIMIX_LINK_FAILURE;
543   else
544     action->state = SIMIX_DONE;
545
546   DEBUG1("SIMIX_post_comm: action state = %d", action->state);
547
548   /* After this point the surf actions associated with the simix communicate
549      action are no longer needed, thus we delete them. */
550   SIMIX_comm_destroy_internal_actions(action);
551
552   /* If there are requests associated with the action, then answer them */
553   if (xbt_fifo_size(action->request_list))
554     SIMIX_comm_finish(action);
555 }
556
557 void SIMIX_comm_cancel(smx_action_t action)
558 {
559   /* If the action is a waiting state means that it is still in a rdv */
560   /* so remove from it and delete it */
561   if (action->state == SIMIX_WAITING) {
562     SIMIX_rdv_remove(action->comm.rdv, action);
563     action->state = SIMIX_FAILED;
564   } else {
565     surf_workstation_model->action_cancel(action->comm.surf_comm);
566   }
567 }
568
569 void SIMIX_comm_suspend(smx_action_t action)
570 {
571   /*FIXME: shall we suspend also the timeout actions? */
572   surf_workstation_model->suspend(action->comm.surf_comm);
573 }
574
575 void SIMIX_comm_resume(smx_action_t action)
576 {
577   /*FIXME: check what happen with the timeouts */
578   surf_workstation_model->resume(action->comm.surf_comm);
579 }
580
581
582 /************* Action Getters **************/
583
584 /**
585  *  \brief get the amount remaining from the communication
586  *  \param action The communication
587  */
588 double SIMIX_comm_get_remains(smx_action_t action)
589 {
590   double remains;
591
592   switch (action->state) {
593
594     case SIMIX_RUNNING:
595       remains = surf_workstation_model->get_remains(action->comm.surf_comm);
596       break;
597
598     case SIMIX_WAITING:
599     case SIMIX_READY:
600       remains = 0; /*FIXME: check what should be returned */
601       break;
602
603     default:
604       remains = 0; /*FIXME: is this correct? */
605       break;
606   }
607   return remains;
608 }
609
610 e_smx_state_t SIMIX_comm_get_state(smx_action_t action)
611 {
612   return action->state;
613 }
614
615 /**
616  *  \brief Return the user data associated to the communication
617  *  \param action The communication
618  *  \return the user data
619  */
620 void* SIMIX_comm_get_data(smx_action_t action)
621 {
622   return action->comm.data;
623 }
624
625 void* SIMIX_comm_get_src_buff(smx_action_t action)
626 {
627   return action->comm.src_buff;
628 }
629
630 void* SIMIX_comm_get_dst_buff(smx_action_t action)
631 {
632   return action->comm.dst_buff;
633 }
634
635 size_t SIMIX_comm_get_src_buff_size(smx_action_t action)
636 {
637   return action->comm.src_buff_size;
638 }
639
640 size_t SIMIX_comm_get_dst_buff_size(smx_action_t action)
641 {
642   size_t buff_size;
643
644   if (action->comm.dst_buff_size)
645     buff_size = *(action->comm.dst_buff_size);
646   else
647     buff_size = 0;
648
649   return buff_size;
650 }
651
652 smx_process_t SIMIX_comm_get_src_proc(smx_action_t action)
653 {
654   return action->comm.src_proc;
655 }
656
657 smx_process_t SIMIX_comm_get_dst_proc(smx_action_t action)
658 {
659   return action->comm.dst_proc;
660 }
661
662 #ifdef HAVE_LATENCY_BOUND_TRACKING
663 /**
664  *  \brief verify if communication is latency bounded
665  *  \param comm The communication
666  */
667 XBT_INLINE int SIMIX_comm_is_latency_bounded(smx_action_t action)
668 {
669   //try to find comm on the list of finished flows
670   uintptr_t key = 0;
671   uintptr_t data = 0;
672   xbt_dict_cursor_t cursor;
673   xbt_dict_foreach(simix_global->latency_limited_dict, cursor, key, data) {
674     DEBUG2("comparing key=%p with comm=%p", (void *) key, (void *) action);
675     if ((void *) action == (void *) key) {
676       DEBUG2("key %p found, return value latency limited value %d",
677              (void *) key, (int) data);
678       xbt_dict_cursor_free(&cursor);
679       return (int) data;
680     }
681   }
682
683   return surf_workstation_model->get_latency_limited(action->comm.surf_comm);
684 }
685 #endif
686
687 /******************************************************************************/
688 /*                    SIMIX_comm_copy_data callbacks                       */
689 /******************************************************************************/
690 static void (*SIMIX_comm_copy_data_callback) (smx_action_t, size_t) =
691     &SIMIX_comm_copy_pointer_callback;
692
693 void
694 SIMIX_comm_set_copy_data_callback(void (*callback) (smx_action_t, size_t))
695 {
696   SIMIX_comm_copy_data_callback = callback;
697 }
698
699 void SIMIX_comm_copy_pointer_callback(smx_action_t comm, size_t buff_size)
700 {
701   xbt_assert1((buff_size == sizeof(void *)),
702               "Cannot copy %zu bytes: must be sizeof(void*)", buff_size);
703   *(void **) (comm->comm.dst_buff) = comm->comm.src_buff;
704 }
705
706 void SIMIX_comm_copy_buffer_callback(smx_action_t comm, size_t buff_size)
707 {
708   memcpy(comm->comm.dst_buff, comm->comm.src_buff, buff_size);
709 }
710
711 /**
712  *  \brief Copy the communication data from the sender's buffer to the receiver's one
713  *  \param comm The communication
714  */
715 void SIMIX_comm_copy_data(smx_action_t comm)
716 {
717   size_t buff_size = comm->comm.src_buff_size;
718   /* If there is no data to be copy then return */
719   if (!comm->comm.src_buff || !comm->comm.dst_buff || comm->comm.copied == 1)
720     return;
721
722   DEBUG6("Copying comm %p data from %s (%p) -> %s (%p) (%zu bytes)",
723          comm,
724          comm->comm.src_proc->smx_host->name, comm->comm.src_buff,
725          comm->comm.dst_proc->smx_host->name, comm->comm.dst_buff, buff_size);
726
727   /* Copy at most dst_buff_size bytes of the message to receiver's buffer */
728   if (comm->comm.dst_buff_size)
729     buff_size = MIN(buff_size, *(comm->comm.dst_buff_size));
730
731   /* Update the receiver's buffer size to the copied amount */
732   if (comm->comm.dst_buff_size)
733     *comm->comm.dst_buff_size = buff_size;
734
735   if (buff_size == 0)
736     return;
737
738   (*SIMIX_comm_copy_data_callback) (comm, buff_size);
739
740   /* Set the copied flag so we copy data only once */
741   /* (this function might be called from both communication ends) */
742   comm->comm.copied = 1;
743 }