Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
ec3da349453a187add75368b061845000ffdc11a
[simgrid.git] / src / smpi / smpi_pmpi.c
1 /* Copyright (c) 2007, 2008, 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 "smpi_mpi_dt_private.h"
9
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_pmpi, smpi,
11                                 "Logging specific to SMPI (pmpi)");
12
13 #ifdef HAVE_TRACING
14 //this function need to be here because of the calls to smpi_bench
15 void TRACE_smpi_set_category(const char *category)
16 {
17   //need to end bench otherwise categories for execution tasks are wrong
18   smpi_bench_end();
19   TRACE_internal_smpi_set_category (category);
20   //begin bench after changing process's category
21   smpi_bench_begin();
22 }
23 #endif
24
25 /* PMPI User level calls */
26
27 int PMPI_Init(int *argc, char ***argv)
28 {
29   smpi_process_init(argc, argv);
30 #ifdef HAVE_TRACING
31   TRACE_smpi_init(smpi_process_index());
32 #endif
33   smpi_bench_begin();
34   return MPI_SUCCESS;
35 }
36
37 int PMPI_Finalize(void)
38 {
39   smpi_bench_end();
40 #ifdef HAVE_TRACING
41   TRACE_smpi_finalize(smpi_process_index());
42 #endif
43   smpi_process_destroy();
44   return MPI_SUCCESS;
45 }
46
47 int PMPI_Init_thread(int *argc, char ***argv, int required, int *provided)
48 {
49   if (provided != NULL) {
50     *provided = MPI_THREAD_MULTIPLE;
51   }
52   return MPI_Init(argc, argv);
53 }
54
55 int PMPI_Query_thread(int *provided)
56 {
57   int retval;
58
59   smpi_bench_end();
60   if (provided == NULL) {
61     retval = MPI_ERR_ARG;
62   } else {
63     *provided = MPI_THREAD_MULTIPLE;
64     retval = MPI_SUCCESS;
65   }
66   smpi_bench_begin();
67   return retval;
68 }
69
70 int PMPI_Is_thread_main(int *flag)
71 {
72   int retval;
73
74   smpi_bench_end();
75   if (flag == NULL) {
76     retval = MPI_ERR_ARG;
77   } else {
78     *flag = smpi_process_index() == 0;
79     retval = MPI_SUCCESS;
80   }
81   smpi_bench_begin();
82   return retval;
83 }
84
85 int PMPI_Abort(MPI_Comm comm, int errorcode)
86 {
87   smpi_bench_end();
88   smpi_process_destroy();
89   // FIXME: should kill all processes in comm instead
90   SIMIX_req_process_kill(SIMIX_process_self());
91   return MPI_SUCCESS;
92 }
93
94 double PMPI_Wtime(void)
95 {
96   double time;
97
98   smpi_bench_end();
99   time = SIMIX_get_clock();
100   smpi_bench_begin();
101   return time;
102 }
103
104 int PMPI_Address(void *location, MPI_Aint * address)
105 {
106   int retval;
107
108   smpi_bench_end();
109   if (!address) {
110     retval = MPI_ERR_ARG;
111   } else {
112     *address = (MPI_Aint) location;
113   }
114   smpi_bench_begin();
115   return retval;
116 }
117
118 int PMPI_Type_free(MPI_Datatype * datatype)
119 {
120   int retval;
121
122   smpi_bench_end();
123   if (!datatype) {
124     retval = MPI_ERR_ARG;
125   } else {
126     // FIXME: always fail for now
127     retval = MPI_ERR_TYPE;
128   }
129   smpi_bench_begin();
130   return retval;
131 }
132
133 int PMPI_Type_size(MPI_Datatype datatype, int *size)
134 {
135   int retval;
136
137   smpi_bench_end();
138   if (datatype == MPI_DATATYPE_NULL) {
139     retval = MPI_ERR_TYPE;
140   } else if (size == NULL) {
141     retval = MPI_ERR_ARG;
142   } else {
143     *size = (int) smpi_datatype_size(datatype);
144     retval = MPI_SUCCESS;
145   }
146   smpi_bench_begin();
147   return retval;
148 }
149
150 int PMPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent)
151 {
152   int retval;
153
154   smpi_bench_end();
155   if (datatype == MPI_DATATYPE_NULL) {
156     retval = MPI_ERR_TYPE;
157   } else if (lb == NULL || extent == NULL) {
158     retval = MPI_ERR_ARG;
159   } else {
160     retval = smpi_datatype_extent(datatype, lb, extent);
161   }
162   smpi_bench_begin();
163   return retval;
164 }
165
166 int PMPI_Type_extent(MPI_Datatype datatype, MPI_Aint * extent)
167 {
168   int retval;
169   MPI_Aint dummy;
170
171   smpi_bench_end();
172   if (datatype == MPI_DATATYPE_NULL) {
173     retval = MPI_ERR_TYPE;
174   } else if (extent == NULL) {
175     retval = MPI_ERR_ARG;
176   } else {
177     retval = smpi_datatype_extent(datatype, &dummy, extent);
178   }
179   smpi_bench_begin();
180   return retval;
181 }
182
183 int PMPI_Type_lb(MPI_Datatype datatype, MPI_Aint * disp)
184 {
185   int retval;
186
187   smpi_bench_end();
188   if (datatype == MPI_DATATYPE_NULL) {
189     retval = MPI_ERR_TYPE;
190   } else if (disp == NULL) {
191     retval = MPI_ERR_ARG;
192   } else {
193     *disp = smpi_datatype_lb(datatype);
194     retval = MPI_SUCCESS;
195   }
196   smpi_bench_begin();
197   return retval;
198 }
199
200 int PMPI_Type_ub(MPI_Datatype datatype, MPI_Aint * disp)
201 {
202   int retval;
203
204   smpi_bench_end();
205   if (datatype == MPI_DATATYPE_NULL) {
206     retval = MPI_ERR_TYPE;
207   } else if (disp == NULL) {
208     retval = MPI_ERR_ARG;
209   } else {
210     *disp = smpi_datatype_ub(datatype);
211     retval = MPI_SUCCESS;
212   }
213   smpi_bench_begin();
214   return retval;
215 }
216
217 int PMPI_Op_create(MPI_User_function * function, int commute, MPI_Op * op)
218 {
219   int retval;
220
221   smpi_bench_end();
222   if (function == NULL || op == NULL) {
223     retval = MPI_ERR_ARG;
224   } else {
225     *op = smpi_op_new(function, commute);
226     retval = MPI_SUCCESS;
227   }
228   smpi_bench_begin();
229   return retval;
230 }
231
232 int PMPI_Op_free(MPI_Op * op)
233 {
234   int retval;
235
236   smpi_bench_end();
237   if (op == NULL) {
238     retval = MPI_ERR_ARG;
239   } else if (*op == MPI_OP_NULL) {
240     retval = MPI_ERR_OP;
241   } else {
242     smpi_op_destroy(*op);
243     *op = MPI_OP_NULL;
244     retval = MPI_SUCCESS;
245   }
246   smpi_bench_begin();
247   return retval;
248 }
249
250 int PMPI_Group_free(MPI_Group * group)
251 {
252   int retval;
253
254   smpi_bench_end();
255   if (group == NULL) {
256     retval = MPI_ERR_ARG;
257   } else {
258     smpi_group_destroy(*group);
259     *group = MPI_GROUP_NULL;
260     retval = MPI_SUCCESS;
261   }
262   smpi_bench_begin();
263   return retval;
264 }
265
266 int PMPI_Group_size(MPI_Group group, int *size)
267 {
268   int retval;
269
270   smpi_bench_end();
271   if (group == MPI_GROUP_NULL) {
272     retval = MPI_ERR_GROUP;
273   } else if (size == NULL) {
274     retval = MPI_ERR_ARG;
275   } else {
276     *size = smpi_group_size(group);
277     retval = MPI_SUCCESS;
278   }
279   smpi_bench_begin();
280   return retval;
281 }
282
283 int PMPI_Group_rank(MPI_Group group, int *rank)
284 {
285   int retval;
286
287   smpi_bench_end();
288   if (group == MPI_GROUP_NULL) {
289     retval = MPI_ERR_GROUP;
290   } else if (rank == NULL) {
291     retval = MPI_ERR_ARG;
292   } else {
293     *rank = smpi_group_rank(group, smpi_process_index());
294     retval = MPI_SUCCESS;
295   }
296   smpi_bench_begin();
297   return retval;
298 }
299
300 int PMPI_Group_translate_ranks(MPI_Group group1, int n, int *ranks1,
301                               MPI_Group group2, int *ranks2)
302 {
303   int retval, i, index;
304
305   smpi_bench_end();
306   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
307     retval = MPI_ERR_GROUP;
308   } else {
309     for (i = 0; i < n; i++) {
310       index = smpi_group_index(group1, ranks1[i]);
311       ranks2[i] = smpi_group_rank(group2, index);
312     }
313     retval = MPI_SUCCESS;
314   }
315   smpi_bench_begin();
316   return retval;
317 }
318
319 int PMPI_Group_compare(MPI_Group group1, MPI_Group group2, int *result)
320 {
321   int retval;
322
323   smpi_bench_end();
324   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
325     retval = MPI_ERR_GROUP;
326   } else if (result == NULL) {
327     retval = MPI_ERR_ARG;
328   } else {
329     *result = smpi_group_compare(group1, group2);
330     retval = MPI_SUCCESS;
331   }
332   smpi_bench_begin();
333   return retval;
334 }
335
336 int PMPI_Group_union(MPI_Group group1, MPI_Group group2,
337                     MPI_Group * newgroup)
338 {
339   int retval, i, proc1, proc2, size, size2;
340
341   smpi_bench_end();
342   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
343     retval = MPI_ERR_GROUP;
344   } else if (newgroup == NULL) {
345     retval = MPI_ERR_ARG;
346   } else {
347     size = smpi_group_size(group1);
348     size2 = smpi_group_size(group2);
349     for (i = 0; i < size2; i++) {
350       proc2 = smpi_group_index(group2, i);
351       proc1 = smpi_group_rank(group1, proc2);
352       if (proc1 == MPI_UNDEFINED) {
353         size++;
354       }
355     }
356     if (size == 0) {
357       *newgroup = MPI_GROUP_EMPTY;
358     } else {
359       *newgroup = smpi_group_new(size);
360       size2 = smpi_group_size(group1);
361       for (i = 0; i < size2; i++) {
362         proc1 = smpi_group_index(group1, i);
363         smpi_group_set_mapping(*newgroup, proc1, i);
364       }
365       for (i = size2; i < size; i++) {
366         proc2 = smpi_group_index(group2, i - size2);
367         smpi_group_set_mapping(*newgroup, proc2, i);
368       }
369     }
370     smpi_group_use(*newgroup);
371     retval = MPI_SUCCESS;
372   }
373   smpi_bench_begin();
374   return retval;
375 }
376
377 int PMPI_Group_intersection(MPI_Group group1, MPI_Group group2,
378                            MPI_Group * newgroup)
379 {
380   int retval, i, proc1, proc2, size, size2;
381
382   smpi_bench_end();
383   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
384     retval = MPI_ERR_GROUP;
385   } else if (newgroup == NULL) {
386     retval = MPI_ERR_ARG;
387   } else {
388     size = smpi_group_size(group1);
389     size2 = smpi_group_size(group2);
390     for (i = 0; i < size2; i++) {
391       proc2 = smpi_group_index(group2, i);
392       proc1 = smpi_group_rank(group1, proc2);
393       if (proc1 == MPI_UNDEFINED) {
394         size--;
395       }
396     }
397     if (size == 0) {
398       *newgroup = MPI_GROUP_EMPTY;
399     } else {
400       *newgroup = smpi_group_new(size);
401       size2 = smpi_group_size(group1);
402       for (i = 0; i < size2; i++) {
403         proc1 = smpi_group_index(group1, i);
404         proc2 = smpi_group_rank(group2, proc1);
405         if (proc2 != MPI_UNDEFINED) {
406           smpi_group_set_mapping(*newgroup, proc1, i);
407         }
408       }
409     }
410     smpi_group_use(*newgroup);
411     retval = MPI_SUCCESS;
412   }
413   smpi_bench_begin();
414   return retval;
415 }
416
417 int PMPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group * newgroup)
418 {
419   int retval, i, proc1, proc2, size, size2;
420
421   smpi_bench_end();
422   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
423     retval = MPI_ERR_GROUP;
424   } else if (newgroup == NULL) {
425     retval = MPI_ERR_ARG;
426   } else {
427     size = size2 = smpi_group_size(group1);
428     for (i = 0; i < size2; i++) {
429       proc1 = smpi_group_index(group1, i);
430       proc2 = smpi_group_rank(group2, proc1);
431       if (proc2 != MPI_UNDEFINED) {
432         size--;
433       }
434     }
435     if (size == 0) {
436       *newgroup = MPI_GROUP_EMPTY;
437     } else {
438       *newgroup = smpi_group_new(size);
439       for (i = 0; i < size2; i++) {
440         proc1 = smpi_group_index(group1, i);
441         proc2 = smpi_group_rank(group2, proc1);
442         if (proc2 == MPI_UNDEFINED) {
443           smpi_group_set_mapping(*newgroup, proc1, i);
444         }
445       }
446     }
447     smpi_group_use(*newgroup);
448     retval = MPI_SUCCESS;
449   }
450   smpi_bench_begin();
451   return retval;
452 }
453
454 int PMPI_Group_incl(MPI_Group group, int n, int *ranks, MPI_Group * newgroup)
455 {
456   int retval, i, index;
457
458   smpi_bench_end();
459   if (group == MPI_GROUP_NULL) {
460     retval = MPI_ERR_GROUP;
461   } else if (newgroup == NULL) {
462     retval = MPI_ERR_ARG;
463   } else {
464     if (n == 0) {
465       *newgroup = MPI_GROUP_EMPTY;
466     } else if (n == smpi_group_size(group)) {
467       *newgroup = group;
468     } else {
469       *newgroup = smpi_group_new(n);
470       for (i = 0; i < n; i++) {
471         index = smpi_group_index(group, ranks[i]);
472         smpi_group_set_mapping(*newgroup, index, i);
473       }
474     }
475     smpi_group_use(*newgroup);
476     retval = MPI_SUCCESS;
477   }
478   smpi_bench_begin();
479   return retval;
480 }
481
482 int PMPI_Group_excl(MPI_Group group, int n, int *ranks, MPI_Group * newgroup)
483 {
484   int retval, i, size, rank, index;
485
486   smpi_bench_end();
487   if (group == MPI_GROUP_NULL) {
488     retval = MPI_ERR_GROUP;
489   } else if (newgroup == NULL) {
490     retval = MPI_ERR_ARG;
491   } else {
492     if (n == 0) {
493       *newgroup = group;
494     } else if (n == smpi_group_size(group)) {
495       *newgroup = MPI_GROUP_EMPTY;
496     } else {
497       size = smpi_group_size(group) - n;
498       *newgroup = smpi_group_new(size);
499       rank = 0;
500       while (rank < size) {
501         for (i = 0; i < n; i++) {
502           if (ranks[i] == rank) {
503             break;
504           }
505         }
506         if (i >= n) {
507           index = smpi_group_index(group, rank);
508           smpi_group_set_mapping(*newgroup, index, rank);
509           rank++;
510         }
511       }
512     }
513     smpi_group_use(*newgroup);
514     retval = MPI_SUCCESS;
515   }
516   smpi_bench_begin();
517   return retval;
518 }
519
520 int PMPI_Group_range_incl(MPI_Group group, int n, int ranges[][3],
521                          MPI_Group * newgroup)
522 {
523   int retval, i, j, rank, size, index;
524
525   smpi_bench_end();
526   if (group == MPI_GROUP_NULL) {
527     retval = MPI_ERR_GROUP;
528   } else if (newgroup == NULL) {
529     retval = MPI_ERR_ARG;
530   } else {
531     if (n == 0) {
532       *newgroup = MPI_GROUP_EMPTY;
533     } else {
534       size = 0;
535       for (i = 0; i < n; i++) {
536         for (rank = ranges[i][0];       /* First */
537              rank >= 0 && rank <= ranges[i][1]; /* Last */
538              rank += ranges[i][2] /* Stride */ ) {
539           size++;
540         }
541       }
542       if (size == smpi_group_size(group)) {
543         *newgroup = group;
544       } else {
545         *newgroup = smpi_group_new(size);
546         j = 0;
547         for (i = 0; i < n; i++) {
548           for (rank = ranges[i][0];     /* First */
549                rank >= 0 && rank <= ranges[i][1];       /* Last */
550                rank += ranges[i][2] /* Stride */ ) {
551             index = smpi_group_index(group, rank);
552             smpi_group_set_mapping(*newgroup, index, j);
553             j++;
554           }
555         }
556       }
557     }
558     smpi_group_use(*newgroup);
559     retval = MPI_SUCCESS;
560   }
561   smpi_bench_begin();
562   return retval;
563 }
564
565 int PMPI_Group_range_excl(MPI_Group group, int n, int ranges[][3],
566                          MPI_Group * newgroup)
567 {
568   int retval, i, newrank, rank, size, index, add;
569
570   smpi_bench_end();
571   if (group == MPI_GROUP_NULL) {
572     retval = MPI_ERR_GROUP;
573   } else if (newgroup == NULL) {
574     retval = MPI_ERR_ARG;
575   } else {
576     if (n == 0) {
577       *newgroup = group;
578     } else {
579       size = smpi_group_size(group);
580       for (i = 0; i < n; i++) {
581         for (rank = ranges[i][0];       /* First */
582              rank >= 0 && rank <= ranges[i][1]; /* Last */
583              rank += ranges[i][2] /* Stride */ ) {
584           size--;
585         }
586       }
587       if (size == 0) {
588         *newgroup = MPI_GROUP_EMPTY;
589       } else {
590         *newgroup = smpi_group_new(size);
591         newrank = 0;
592         while (newrank < size) {
593           for (i = 0; i < n; i++) {
594             add = 1;
595             for (rank = ranges[i][0];   /* First */
596                  rank >= 0 && rank <= ranges[i][1];     /* Last */
597                  rank += ranges[i][2] /* Stride */ ) {
598               if (rank == newrank) {
599                 add = 0;
600                 break;
601               }
602             }
603             if (add == 1) {
604               index = smpi_group_index(group, newrank);
605               smpi_group_set_mapping(*newgroup, index, newrank);
606             }
607           }
608         }
609       }
610     }
611     smpi_group_use(*newgroup);
612     retval = MPI_SUCCESS;
613   }
614   smpi_bench_begin();
615   return retval;
616 }
617
618 int PMPI_Comm_rank(MPI_Comm comm, int *rank)
619 {
620   int retval;
621
622   smpi_bench_end();
623   if (comm == MPI_COMM_NULL) {
624     retval = MPI_ERR_COMM;
625   } else if (rank == NULL) {
626     retval = MPI_ERR_ARG;
627   } else {
628     *rank = smpi_comm_rank(comm);
629     retval = MPI_SUCCESS;
630   }
631   smpi_bench_begin();
632   return retval;
633 }
634
635 int PMPI_Comm_size(MPI_Comm comm, int *size)
636 {
637   int retval;
638
639   smpi_bench_end();
640   if (comm == MPI_COMM_NULL) {
641     retval = MPI_ERR_COMM;
642   } else if (size == NULL) {
643     retval = MPI_ERR_ARG;
644   } else {
645     *size = smpi_comm_size(comm);
646     retval = MPI_SUCCESS;
647   }
648   smpi_bench_begin();
649   return retval;
650 }
651
652 int PMPI_Comm_get_name (MPI_Comm comm, char* name, int* len)
653 {
654   int retval;
655
656   smpi_bench_end();
657   if (comm == MPI_COMM_NULL)  {
658     retval = MPI_ERR_COMM;
659   } else if (name == NULL || len == NULL)  {
660     retval = MPI_ERR_ARG;
661   } else {
662     smpi_comm_get_name(comm, name, len);
663     retval = MPI_SUCCESS;
664   }
665   smpi_bench_begin();
666   return retval;
667 }
668
669 int PMPI_Comm_group(MPI_Comm comm, MPI_Group * group)
670 {
671   int retval;
672
673   smpi_bench_end();
674   if (comm == MPI_COMM_NULL) {
675     retval = MPI_ERR_COMM;
676   } else if (group == NULL) {
677     retval = MPI_ERR_ARG;
678   } else {
679     *group = smpi_comm_group(comm);
680     retval = MPI_SUCCESS;
681   }
682   smpi_bench_begin();
683   return retval;
684 }
685
686 int PMPI_Comm_compare(MPI_Comm comm1, MPI_Comm comm2, int *result)
687 {
688   int retval;
689
690   smpi_bench_end();
691   if (comm1 == MPI_COMM_NULL || comm2 == MPI_COMM_NULL) {
692     retval = MPI_ERR_COMM;
693   } else if (result == NULL) {
694     retval = MPI_ERR_ARG;
695   } else {
696     if (comm1 == comm2) {       /* Same communicators means same groups */
697       *result = MPI_IDENT;
698     } else {
699       *result =
700           smpi_group_compare(smpi_comm_group(comm1),
701                              smpi_comm_group(comm2));
702       if (*result == MPI_IDENT) {
703         *result = MPI_CONGRUENT;
704       }
705     }
706     retval = MPI_SUCCESS;
707   }
708   smpi_bench_begin();
709   return retval;
710 }
711
712 int PMPI_Comm_dup(MPI_Comm comm, MPI_Comm * newcomm)
713 {
714   int retval;
715
716   smpi_bench_end();
717   if (comm == MPI_COMM_NULL) {
718     retval = MPI_ERR_COMM;
719   } else if (newcomm == NULL) {
720     retval = MPI_ERR_ARG;
721   } else {
722     *newcomm = smpi_comm_new(smpi_comm_group(comm));
723     retval = MPI_SUCCESS;
724   }
725   smpi_bench_begin();
726   return retval;
727 }
728
729 int PMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm * newcomm)
730 {
731   int retval;
732
733   smpi_bench_end();
734   if (comm == MPI_COMM_NULL) {
735     retval = MPI_ERR_COMM;
736   } else if (group == MPI_GROUP_NULL) {
737     retval = MPI_ERR_GROUP;
738   } else if (newcomm == NULL) {
739     retval = MPI_ERR_ARG;
740   } else {
741     *newcomm = smpi_comm_new(group);
742     retval = MPI_SUCCESS;
743   }
744   smpi_bench_begin();
745   return retval;
746 }
747
748 int PMPI_Comm_free(MPI_Comm * comm)
749 {
750   int retval;
751
752   smpi_bench_end();
753   if (comm == NULL) {
754     retval = MPI_ERR_ARG;
755   } else if (*comm == MPI_COMM_NULL) {
756     retval = MPI_ERR_COMM;
757   } else {
758     smpi_comm_destroy(*comm);
759     *comm = MPI_COMM_NULL;
760     retval = MPI_SUCCESS;
761   }
762   smpi_bench_begin();
763   return retval;
764 }
765
766 int PMPI_Comm_disconnect(MPI_Comm * comm)
767 {
768   /* TODO: wait until all communication in comm are done */
769   int retval;
770
771   smpi_bench_end();
772   if (comm == NULL) {
773     retval = MPI_ERR_ARG;
774   } else if (*comm == MPI_COMM_NULL) {
775     retval = MPI_ERR_COMM;
776   } else {
777     smpi_comm_destroy(*comm);
778     *comm = MPI_COMM_NULL;
779     retval = MPI_SUCCESS;
780   }
781   smpi_bench_begin();
782   return retval;
783 }
784
785 int PMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* comm_out)
786 {
787   int retval;
788
789   smpi_bench_end();
790   if (comm_out == NULL) {
791     retval = MPI_ERR_ARG;
792   } else if (comm == MPI_COMM_NULL) {
793     retval = MPI_ERR_COMM;
794   } else {
795     *comm_out = smpi_comm_split(comm, color, key);
796     retval = MPI_SUCCESS;
797   }
798   smpi_bench_begin();
799   return retval;
800 }
801
802 int PMPI_Send_init(void *buf, int count, MPI_Datatype datatype, int dst,
803                   int tag, MPI_Comm comm, MPI_Request * request)
804 {
805   int retval;
806
807   smpi_bench_end();
808   if (request == NULL) {
809     retval = MPI_ERR_ARG;
810   } else if (comm == MPI_COMM_NULL) {
811     retval = MPI_ERR_COMM;
812   } else {
813     *request = smpi_mpi_send_init(buf, count, datatype, dst, tag, comm);
814     retval = MPI_SUCCESS;
815   }
816   smpi_bench_begin();
817   return retval;
818 }
819
820 int PMPI_Recv_init(void *buf, int count, MPI_Datatype datatype, int src,
821                   int tag, MPI_Comm comm, MPI_Request * request)
822 {
823   int retval;
824
825   smpi_bench_end();
826   if (request == NULL) {
827     retval = MPI_ERR_ARG;
828   } else if (comm == MPI_COMM_NULL) {
829     retval = MPI_ERR_COMM;
830   } else {
831     *request = smpi_mpi_recv_init(buf, count, datatype, src, tag, comm);
832     retval = MPI_SUCCESS;
833   }
834   smpi_bench_begin();
835   return retval;
836 }
837
838 int PMPI_Start(MPI_Request * request)
839 {
840   int retval;
841
842   smpi_bench_end();
843   if (request == NULL) {
844     retval = MPI_ERR_ARG;
845   } else {
846     smpi_mpi_start(*request);
847     retval = MPI_SUCCESS;
848   }
849   smpi_bench_begin();
850   return retval;
851 }
852
853 int PMPI_Startall(int count, MPI_Request * requests)
854 {
855   int retval;
856
857   smpi_bench_end();
858   if (requests == NULL) {
859     retval = MPI_ERR_ARG;
860   } else {
861     smpi_mpi_startall(count, requests);
862     retval = MPI_SUCCESS;
863   }
864   smpi_bench_begin();
865   return retval;
866 }
867
868 int PMPI_Request_free(MPI_Request * request)
869 {
870   int retval;
871
872   smpi_bench_end();
873   if (request == NULL) {
874     retval = MPI_ERR_ARG;
875   } else {
876     smpi_mpi_request_free(request);
877     retval = MPI_SUCCESS;
878   }
879   smpi_bench_begin();
880   return retval;
881 }
882
883 int PMPI_Irecv(void *buf, int count, MPI_Datatype datatype, int src,
884               int tag, MPI_Comm comm, MPI_Request * request)
885 {
886   int retval;
887
888   smpi_bench_end();
889 #ifdef HAVE_TRACING
890   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
891   int src_traced = smpi_group_rank(smpi_comm_group(comm), src);
892   TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__);
893 #endif
894   if (request == NULL) {
895     retval = MPI_ERR_ARG;
896   } else if (comm == MPI_COMM_NULL) {
897     retval = MPI_ERR_COMM;
898   } else {
899     *request = smpi_mpi_irecv(buf, count, datatype, src, tag, comm);
900     retval = MPI_SUCCESS;
901   }
902 #ifdef HAVE_TRACING
903   TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
904   (*request)->recv = 1;
905 #endif
906   smpi_bench_begin();
907   return retval;
908 }
909
910 int PMPI_Isend(void *buf, int count, MPI_Datatype datatype, int dst,
911               int tag, MPI_Comm comm, MPI_Request * request)
912 {
913   int retval;
914
915   smpi_bench_end();
916 #ifdef HAVE_TRACING
917   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
918   int dst_traced = smpi_group_rank(smpi_comm_group(comm), dst);
919   TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__);
920   TRACE_smpi_send(rank, rank, dst_traced);
921 #endif
922   if (request == NULL) {
923     retval = MPI_ERR_ARG;
924   } else if (comm == MPI_COMM_NULL) {
925     retval = MPI_ERR_COMM;
926   } else {
927     *request = smpi_mpi_isend(buf, count, datatype, dst, tag, comm);
928     retval = MPI_SUCCESS;
929   }
930 #ifdef HAVE_TRACING
931   TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
932   (*request)->send = 1;
933 #endif
934   smpi_bench_begin();
935   return retval;
936 }
937
938 int PMPI_Recv(void *buf, int count, MPI_Datatype datatype, int src, int tag,
939              MPI_Comm comm, MPI_Status * status)
940 {
941   int retval;
942
943   smpi_bench_end();
944 #ifdef HAVE_TRACING
945   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
946   int src_traced = smpi_group_rank(smpi_comm_group(comm), src);
947   TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__);
948 #endif
949   if (comm == MPI_COMM_NULL) {
950     retval = MPI_ERR_COMM;
951   } else {
952     smpi_mpi_recv(buf, count, datatype, src, tag, comm, status);
953     retval = MPI_SUCCESS;
954   }
955 #ifdef HAVE_TRACING
956   TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
957   TRACE_smpi_recv(rank, src_traced, rank);
958 #endif
959   smpi_bench_begin();
960   return retval;
961 }
962
963 int PMPI_Send(void *buf, int count, MPI_Datatype datatype, int dst, int tag,
964              MPI_Comm comm)
965 {
966   int retval;
967
968   smpi_bench_end();
969 #ifdef HAVE_TRACING
970   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
971   int dst_traced = smpi_group_rank(smpi_comm_group(comm), dst);
972   TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__);
973   TRACE_smpi_send(rank, rank, dst_traced);
974 #endif
975   if (comm == MPI_COMM_NULL) {
976     retval = MPI_ERR_COMM;
977   } else {
978     smpi_mpi_send(buf, count, datatype, dst, tag, comm);
979     retval = MPI_SUCCESS;
980   }
981 #ifdef HAVE_TRACING
982   TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
983 #endif
984   smpi_bench_begin();
985   return retval;
986 }
987
988 int PMPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
989                  int dst, int sendtag, void *recvbuf, int recvcount,
990                  MPI_Datatype recvtype, int src, int recvtag,
991                  MPI_Comm comm, MPI_Status * status)
992 {
993   int retval;
994
995   smpi_bench_end();
996 #ifdef HAVE_TRACING
997   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
998   int dst_traced = smpi_group_rank(smpi_comm_group(comm), dst);
999   int src_traced = smpi_group_rank(smpi_comm_group(comm), src);
1000   TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__);
1001   TRACE_smpi_send(rank, rank, dst_traced);
1002   TRACE_smpi_send(rank, src_traced, rank);
1003 #endif
1004   if (comm == MPI_COMM_NULL) {
1005     retval = MPI_ERR_COMM;
1006   } else if (sendtype == MPI_DATATYPE_NULL
1007              || recvtype == MPI_DATATYPE_NULL) {
1008     retval = MPI_ERR_TYPE;
1009   } else {
1010     smpi_mpi_sendrecv(sendbuf, sendcount, sendtype, dst, sendtag, recvbuf,
1011                       recvcount, recvtype, src, recvtag, comm, status);
1012     retval = MPI_SUCCESS;
1013   }
1014 #ifdef HAVE_TRACING
1015   TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
1016   TRACE_smpi_recv(rank, rank, dst_traced);
1017   TRACE_smpi_recv(rank, src_traced, rank);
1018 #endif
1019   smpi_bench_begin();
1020   return retval;
1021 }
1022
1023 int PMPI_Sendrecv_replace(void *buf, int count, MPI_Datatype datatype,
1024                          int dst, int sendtag, int src, int recvtag,
1025                          MPI_Comm comm, MPI_Status * status)
1026 {
1027   //TODO: suboptimal implementation
1028   void *recvbuf;
1029   int retval, size;
1030
1031   size = smpi_datatype_size(datatype) * count;
1032   recvbuf = xbt_new(char, size);
1033   retval =
1034       MPI_Sendrecv(buf, count, datatype, dst, sendtag, recvbuf, count,
1035                    datatype, src, recvtag, comm, status);
1036   memcpy(buf, recvbuf, size * sizeof(char));
1037   xbt_free(recvbuf);
1038   return retval;
1039 }
1040
1041 int PMPI_Test(MPI_Request * request, int *flag, MPI_Status * status)
1042 {
1043   int retval;
1044
1045   smpi_bench_end();
1046   if (request == NULL || flag == NULL) {
1047     retval = MPI_ERR_ARG;
1048   } else if (*request == MPI_REQUEST_NULL) {
1049     retval = MPI_ERR_REQUEST;
1050   } else {
1051     *flag = smpi_mpi_test(request, status);
1052     retval = MPI_SUCCESS;
1053   }
1054   smpi_bench_begin();
1055   return retval;
1056 }
1057
1058 int PMPI_Testany(int count, MPI_Request requests[], int *index, int *flag,
1059                 MPI_Status * status)
1060 {
1061   int retval;
1062
1063   smpi_bench_end();
1064   if (index == NULL || flag == NULL) {
1065     retval = MPI_ERR_ARG;
1066   } else {
1067     *flag = smpi_mpi_testany(count, requests, index, status);
1068     retval = MPI_SUCCESS;
1069   }
1070   smpi_bench_begin();
1071   return retval;
1072 }
1073
1074 int PMPI_Wait(MPI_Request * request, MPI_Status * status)
1075 {
1076   int retval;
1077
1078   smpi_bench_end();
1079 #ifdef HAVE_TRACING
1080   int rank = request && (*request)->comm != MPI_COMM_NULL
1081       ? smpi_comm_rank((*request)->comm)
1082       : -1;
1083   MPI_Group group = smpi_comm_group((*request)->comm);
1084   int src_traced = smpi_group_rank(group, (*request)->src);
1085   int dst_traced = smpi_group_rank(group, (*request)->dst);
1086   int is_wait_for_receive = (*request)->recv;
1087   TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__);
1088 #endif
1089   if (request == NULL) {
1090     retval = MPI_ERR_ARG;
1091   } else if (*request == MPI_REQUEST_NULL) {
1092     retval = MPI_ERR_REQUEST;
1093   } else {
1094     smpi_mpi_wait(request, status);
1095     retval = MPI_SUCCESS;
1096   }
1097 #ifdef HAVE_TRACING
1098   TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
1099   if (is_wait_for_receive) {
1100     TRACE_smpi_recv(rank, src_traced, dst_traced);
1101   }
1102 #endif
1103   smpi_bench_begin();
1104   return retval;
1105 }
1106
1107 int PMPI_Waitany(int count, MPI_Request requests[], int *index, MPI_Status * status)
1108 {
1109   int retval;
1110
1111   smpi_bench_end();
1112 #ifdef HAVE_TRACING
1113   //save requests information for tracing
1114   int i;
1115   xbt_dynar_t srcs = xbt_dynar_new(sizeof(int), xbt_free);
1116   xbt_dynar_t dsts = xbt_dynar_new(sizeof(int), xbt_free);
1117   xbt_dynar_t recvs = xbt_dynar_new(sizeof(int), xbt_free);
1118   for (i = 0; i < count; i++) {
1119     MPI_Request req = requests[i];      //already received requests are no longer valid
1120     if (req) {
1121       int *asrc = xbt_new(int, 1);
1122       int *adst = xbt_new(int, 1);
1123       int *arecv = xbt_new(int, 1);
1124       *asrc = req->src;
1125       *adst = req->dst;
1126       *arecv = req->recv;
1127       xbt_dynar_insert_at(srcs, i, asrc);
1128       xbt_dynar_insert_at(dsts, i, adst);
1129       xbt_dynar_insert_at(recvs, i, arecv);
1130     } else {
1131       int *t = xbt_new(int, 1);
1132       xbt_dynar_insert_at(srcs, i, t);
1133       xbt_dynar_insert_at(dsts, i, t);
1134       xbt_dynar_insert_at(recvs, i, t);
1135     }
1136   }
1137   int rank_traced = smpi_comm_rank(MPI_COMM_WORLD);
1138   TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__);
1139 #endif
1140   if (index == NULL) {
1141     retval = MPI_ERR_ARG;
1142   } else {
1143     *index = smpi_mpi_waitany(count, requests, status);
1144     retval = MPI_SUCCESS;
1145   }
1146 #ifdef HAVE_TRACING
1147   int src_traced, dst_traced, is_wait_for_receive;
1148   xbt_dynar_get_cpy(srcs, *index, &src_traced);
1149   xbt_dynar_get_cpy(dsts, *index, &dst_traced);
1150   xbt_dynar_get_cpy(recvs, *index, &is_wait_for_receive);
1151   if (is_wait_for_receive) {
1152     TRACE_smpi_recv(rank_traced, src_traced, dst_traced);
1153   }
1154   TRACE_smpi_ptp_out(rank_traced, src_traced, dst_traced, __FUNCTION__);
1155   //clean-up of dynars
1156   xbt_free(srcs);
1157   xbt_free(dsts);
1158   xbt_free(recvs);
1159 #endif
1160   smpi_bench_begin();
1161   return retval;
1162 }
1163
1164 int PMPI_Waitall(int count, MPI_Request requests[], MPI_Status status[])
1165 {
1166
1167   smpi_bench_end();
1168 #ifdef HAVE_TRACING
1169   //save information from requests
1170   int i;
1171   xbt_dynar_t srcs = xbt_dynar_new(sizeof(int), xbt_free);
1172   xbt_dynar_t dsts = xbt_dynar_new(sizeof(int), xbt_free);
1173   xbt_dynar_t recvs = xbt_dynar_new(sizeof(int), xbt_free);
1174   for (i = 0; i < count; i++) {
1175     MPI_Request req = requests[i];      //all req should be valid in Waitall
1176     int *asrc = xbt_new(int, 1);
1177     int *adst = xbt_new(int, 1);
1178     int *arecv = xbt_new(int, 1);
1179     *asrc = req->src;
1180     *adst = req->dst;
1181     *arecv = req->recv;
1182     xbt_dynar_insert_at(srcs, i, asrc);
1183     xbt_dynar_insert_at(dsts, i, adst);
1184     xbt_dynar_insert_at(recvs, i, arecv);
1185   }
1186   int rank_traced = smpi_comm_rank (MPI_COMM_WORLD);
1187   TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__);
1188 #endif
1189   smpi_mpi_waitall(count, requests, status);
1190 #ifdef HAVE_TRACING
1191   for (i = 0; i < count; i++) {
1192     int src_traced, dst_traced, is_wait_for_receive;
1193     xbt_dynar_get_cpy(srcs, i, &src_traced);
1194     xbt_dynar_get_cpy(dsts, i, &dst_traced);
1195     xbt_dynar_get_cpy(recvs, i, &is_wait_for_receive);
1196     if (is_wait_for_receive) {
1197       TRACE_smpi_recv(rank_traced, src_traced, dst_traced);
1198     }
1199   }
1200   TRACE_smpi_ptp_out(rank_traced, -1, -1, __FUNCTION__);
1201   //clean-up of dynars
1202   xbt_free(srcs);
1203   xbt_free(dsts);
1204   xbt_free(recvs);
1205 #endif
1206   smpi_bench_begin();
1207   return MPI_SUCCESS;
1208 }
1209
1210 int PMPI_Waitsome(int incount, MPI_Request requests[], int *outcount,
1211                  int *indices, MPI_Status status[])
1212 {
1213   int retval;
1214
1215   smpi_bench_end();
1216   if (outcount == NULL || indices == NULL) {
1217     retval = MPI_ERR_ARG;
1218   } else {
1219     *outcount = smpi_mpi_waitsome(incount, requests, indices, status);
1220     retval = MPI_SUCCESS;
1221   }
1222   smpi_bench_begin();
1223   return retval;
1224 }
1225
1226 int PMPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm)
1227 {
1228   int retval;
1229
1230   smpi_bench_end();
1231 #ifdef HAVE_TRACING
1232   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1233   int root_traced = smpi_group_rank(smpi_comm_group(comm), root);
1234   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
1235 #endif
1236   if (comm == MPI_COMM_NULL) {
1237     retval = MPI_ERR_COMM;
1238   } else {
1239     smpi_mpi_bcast(buf, count, datatype, root, comm);
1240     retval = MPI_SUCCESS;
1241   }
1242 #ifdef HAVE_TRACING
1243   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1244 #endif
1245   smpi_bench_begin();
1246   return retval;
1247 }
1248
1249 int PMPI_Barrier(MPI_Comm comm)
1250 {
1251   int retval;
1252
1253   smpi_bench_end();
1254 #ifdef HAVE_TRACING
1255   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1256   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1257 #endif
1258   if (comm == MPI_COMM_NULL) {
1259     retval = MPI_ERR_COMM;
1260   } else {
1261     smpi_mpi_barrier(comm);
1262     retval = MPI_SUCCESS;
1263   }
1264 #ifdef HAVE_TRACING
1265   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1266 #endif
1267   smpi_bench_begin();
1268   return retval;
1269 }
1270
1271 int PMPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1272                void *recvbuf, int recvcount, MPI_Datatype recvtype,
1273                int root, MPI_Comm comm)
1274 {
1275   int retval;
1276
1277   smpi_bench_end();
1278 #ifdef HAVE_TRACING
1279   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1280   int root_traced = smpi_group_rank(smpi_comm_group(comm), root);
1281   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
1282 #endif
1283   if (comm == MPI_COMM_NULL) {
1284     retval = MPI_ERR_COMM;
1285   } else if (sendtype == MPI_DATATYPE_NULL
1286              || recvtype == MPI_DATATYPE_NULL) {
1287     retval = MPI_ERR_TYPE;
1288   } else {
1289     smpi_mpi_gather(sendbuf, sendcount, sendtype, recvbuf, recvcount,
1290                     recvtype, root, comm);
1291     retval = MPI_SUCCESS;
1292   }
1293 #ifdef HAVE_TRACING
1294   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1295 #endif
1296   smpi_bench_begin();
1297   return retval;
1298 }
1299
1300 int PMPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1301                 void *recvbuf, int *recvcounts, int *displs,
1302                 MPI_Datatype recvtype, int root, MPI_Comm comm)
1303 {
1304   int retval;
1305
1306   smpi_bench_end();
1307 #ifdef HAVE_TRACING
1308   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1309   int root_traced = smpi_group_rank(smpi_comm_group(comm), root);
1310   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
1311 #endif
1312   if (comm == MPI_COMM_NULL) {
1313     retval = MPI_ERR_COMM;
1314   } else if (sendtype == MPI_DATATYPE_NULL
1315              || recvtype == MPI_DATATYPE_NULL) {
1316     retval = MPI_ERR_TYPE;
1317   } else if (recvcounts == NULL || displs == NULL) {
1318     retval = MPI_ERR_ARG;
1319   } else {
1320     smpi_mpi_gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts,
1321                      displs, recvtype, root, comm);
1322     retval = MPI_SUCCESS;
1323   }
1324 #ifdef HAVE_TRACING
1325   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1326 #endif
1327   smpi_bench_begin();
1328   return retval;
1329 }
1330
1331 int PMPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1332                   void *recvbuf, int recvcount, MPI_Datatype recvtype,
1333                   MPI_Comm comm)
1334 {
1335   int retval;
1336
1337   smpi_bench_end();
1338 #ifdef HAVE_TRACING
1339   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1340   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1341 #endif
1342   if (comm == MPI_COMM_NULL) {
1343     retval = MPI_ERR_COMM;
1344   } else if (sendtype == MPI_DATATYPE_NULL
1345              || recvtype == MPI_DATATYPE_NULL) {
1346     retval = MPI_ERR_TYPE;
1347   } else {
1348     smpi_mpi_allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount,
1349                        recvtype, comm);
1350     retval = MPI_SUCCESS;
1351   }
1352 #ifdef HAVE_TRACING
1353   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1354 #endif
1355   smpi_bench_begin();
1356   return retval;
1357 }
1358
1359 int PMPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1360                    void *recvbuf, int *recvcounts, int *displs,
1361                    MPI_Datatype recvtype, MPI_Comm comm)
1362 {
1363   int retval;
1364
1365   smpi_bench_end();
1366 #ifdef HAVE_TRACING
1367   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1368   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1369 #endif
1370   if (comm == MPI_COMM_NULL) {
1371     retval = MPI_ERR_COMM;
1372   } else if (sendtype == MPI_DATATYPE_NULL
1373              || recvtype == MPI_DATATYPE_NULL) {
1374     retval = MPI_ERR_TYPE;
1375   } else if (recvcounts == NULL || displs == NULL) {
1376     retval = MPI_ERR_ARG;
1377   } else {
1378     smpi_mpi_allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts,
1379                         displs, recvtype, comm);
1380     retval = MPI_SUCCESS;
1381   }
1382 #ifdef HAVE_TRACING
1383   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1384 #endif
1385   smpi_bench_begin();
1386   return retval;
1387 }
1388
1389 int PMPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1390                 void *recvbuf, int recvcount, MPI_Datatype recvtype,
1391                 int root, MPI_Comm comm)
1392 {
1393   int retval;
1394
1395   smpi_bench_end();
1396 #ifdef HAVE_TRACING
1397   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1398   int root_traced = smpi_group_rank(smpi_comm_group(comm), root);
1399   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
1400 #endif
1401   if (comm == MPI_COMM_NULL) {
1402     retval = MPI_ERR_COMM;
1403   } else if (sendtype == MPI_DATATYPE_NULL
1404              || recvtype == MPI_DATATYPE_NULL) {
1405     retval = MPI_ERR_TYPE;
1406   } else {
1407     smpi_mpi_scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount,
1408                      recvtype, root, comm);
1409     retval = MPI_SUCCESS;
1410   }
1411 #ifdef HAVE_TRACING
1412   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1413 #endif
1414   smpi_bench_begin();
1415   return retval;
1416 }
1417
1418 int PMPI_Scatterv(void *sendbuf, int *sendcounts, int *displs,
1419                  MPI_Datatype sendtype, void *recvbuf, int recvcount,
1420                  MPI_Datatype recvtype, int root, MPI_Comm comm)
1421 {
1422   int retval;
1423
1424   smpi_bench_end();
1425 #ifdef HAVE_TRACING
1426   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1427   int root_traced = smpi_group_rank(smpi_comm_group(comm), root);
1428   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
1429 #endif
1430   if (comm == MPI_COMM_NULL) {
1431     retval = MPI_ERR_COMM;
1432   } else if (sendtype == MPI_DATATYPE_NULL
1433              || recvtype == MPI_DATATYPE_NULL) {
1434     retval = MPI_ERR_TYPE;
1435   } else if (sendcounts == NULL || displs == NULL) {
1436     retval = MPI_ERR_ARG;
1437   } else {
1438     smpi_mpi_scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf,
1439                       recvcount, recvtype, root, comm);
1440     retval = MPI_SUCCESS;
1441   }
1442 #ifdef HAVE_TRACING
1443   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1444 #endif
1445   smpi_bench_begin();
1446   return retval;
1447 }
1448
1449 int PMPI_Reduce(void *sendbuf, void *recvbuf, int count,
1450                MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
1451 {
1452   int retval;
1453
1454   smpi_bench_end();
1455 #ifdef HAVE_TRACING
1456   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1457   int root_traced = smpi_group_rank(smpi_comm_group(comm), root);
1458   TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__);
1459 #endif
1460   if (comm == MPI_COMM_NULL) {
1461     retval = MPI_ERR_COMM;
1462   } else if (datatype == MPI_DATATYPE_NULL || op == MPI_OP_NULL) {
1463     retval = MPI_ERR_ARG;
1464   } else {
1465     smpi_mpi_reduce(sendbuf, recvbuf, count, datatype, op, root, comm);
1466     retval = MPI_SUCCESS;
1467   }
1468 #ifdef HAVE_TRACING
1469   TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1470 #endif
1471   smpi_bench_begin();
1472   return retval;
1473 }
1474
1475 int PMPI_Allreduce(void *sendbuf, void *recvbuf, int count,
1476                   MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
1477 {
1478   int retval;
1479
1480   smpi_bench_end();
1481 #ifdef HAVE_TRACING
1482   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1483   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1484 #endif
1485   if (comm == MPI_COMM_NULL) {
1486     retval = MPI_ERR_COMM;
1487   } else if (datatype == MPI_DATATYPE_NULL) {
1488     retval = MPI_ERR_TYPE;
1489   } else if (op == MPI_OP_NULL) {
1490     retval = MPI_ERR_OP;
1491   } else {
1492     smpi_mpi_allreduce(sendbuf, recvbuf, count, datatype, op, comm);
1493     retval = MPI_SUCCESS;
1494   }
1495 #ifdef HAVE_TRACING
1496   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1497 #endif
1498   smpi_bench_begin();
1499   return retval;
1500 }
1501
1502 int PMPI_Scan(void *sendbuf, void *recvbuf, int count,
1503              MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
1504 {
1505   int retval;
1506
1507   smpi_bench_end();
1508 #ifdef HAVE_TRACING
1509   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1510   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1511 #endif
1512   if (comm == MPI_COMM_NULL) {
1513     retval = MPI_ERR_COMM;
1514   } else if (datatype == MPI_DATATYPE_NULL) {
1515     retval = MPI_ERR_TYPE;
1516   } else if (op == MPI_OP_NULL) {
1517     retval = MPI_ERR_OP;
1518   } else {
1519     smpi_mpi_scan(sendbuf, recvbuf, count, datatype, op, comm);
1520     retval = MPI_SUCCESS;
1521   }
1522 #ifdef HAVE_TRACING
1523   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1524 #endif
1525   smpi_bench_begin();
1526   return retval;
1527 }
1528
1529 int PMPI_Reduce_scatter(void *sendbuf, void *recvbuf, int *recvcounts,
1530                        MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
1531 {
1532   int retval, i, size, count;
1533   int *displs;
1534   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1535
1536   smpi_bench_end();
1537 #ifdef HAVE_TRACING
1538   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1539 #endif
1540   if (comm == MPI_COMM_NULL) {
1541     retval = MPI_ERR_COMM;
1542   } else if (datatype == MPI_DATATYPE_NULL) {
1543     retval = MPI_ERR_TYPE;
1544   } else if (op == MPI_OP_NULL) {
1545     retval = MPI_ERR_OP;
1546   } else if (recvcounts == NULL) {
1547     retval = MPI_ERR_ARG;
1548   } else {
1549     /* arbitrarily choose root as rank 0 */
1550     /* TODO: faster direct implementation ? */
1551     size = smpi_comm_size(comm);
1552     count = 0;
1553     displs = xbt_new(int, size);
1554     for (i = 0; i < size; i++) {
1555       count += recvcounts[i];
1556       displs[i] = 0;
1557     }
1558     smpi_mpi_reduce(sendbuf, recvbuf, count, datatype, op, 0, comm);
1559     smpi_mpi_scatterv(recvbuf, recvcounts, displs, datatype, recvbuf,
1560                       recvcounts[rank], datatype, 0, comm);
1561     xbt_free(displs);
1562     retval = MPI_SUCCESS;
1563   }
1564 #ifdef HAVE_TRACING
1565   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1566 #endif
1567   smpi_bench_begin();
1568   return retval;
1569 }
1570
1571 int PMPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1572                  void *recvbuf, int recvcount, MPI_Datatype recvtype,
1573                  MPI_Comm comm)
1574 {
1575   int retval, size, sendsize;
1576
1577   smpi_bench_end();
1578 #ifdef HAVE_TRACING
1579   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1580   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1581 #endif
1582   if (comm == MPI_COMM_NULL) {
1583     retval = MPI_ERR_COMM;
1584   } else if (sendtype == MPI_DATATYPE_NULL
1585              || recvtype == MPI_DATATYPE_NULL) {
1586     retval = MPI_ERR_TYPE;
1587   } else {
1588     size = smpi_comm_size(comm);
1589     sendsize = smpi_datatype_size(sendtype) * sendcount;
1590     if (sendsize < 200 && size > 12) {
1591       retval =
1592           smpi_coll_tuned_alltoall_bruck(sendbuf, sendcount, sendtype,
1593                                          recvbuf, recvcount, recvtype,
1594                                          comm);
1595     } else if (sendsize < 3000) {
1596       retval =
1597           smpi_coll_tuned_alltoall_basic_linear(sendbuf, sendcount,
1598                                                 sendtype, recvbuf,
1599                                                 recvcount, recvtype, comm);
1600     } else {
1601       retval =
1602           smpi_coll_tuned_alltoall_pairwise(sendbuf, sendcount, sendtype,
1603                                             recvbuf, recvcount, recvtype,
1604                                             comm);
1605     }
1606   }
1607 #ifdef HAVE_TRACING
1608   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1609 #endif
1610   smpi_bench_begin();
1611   return retval;
1612 }
1613
1614 int PMPI_Alltoallv(void *sendbuf, int *sendcounts, int *senddisps,
1615                   MPI_Datatype sendtype, void *recvbuf, int *recvcounts,
1616                   int *recvdisps, MPI_Datatype recvtype, MPI_Comm comm)
1617 {
1618   int retval;
1619
1620   smpi_bench_end();
1621 #ifdef HAVE_TRACING
1622   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1623   TRACE_smpi_collective_in(rank, -1, __FUNCTION__);
1624 #endif
1625   if (comm == MPI_COMM_NULL) {
1626     retval = MPI_ERR_COMM;
1627   } else if (sendtype == MPI_DATATYPE_NULL
1628              || recvtype == MPI_DATATYPE_NULL) {
1629     retval = MPI_ERR_TYPE;
1630   } else if (sendcounts == NULL || senddisps == NULL || recvcounts == NULL
1631              || recvdisps == NULL) {
1632     retval = MPI_ERR_ARG;
1633   } else {
1634     retval =
1635         smpi_coll_basic_alltoallv(sendbuf, sendcounts, senddisps, sendtype,
1636                                   recvbuf, recvcounts, recvdisps, recvtype,
1637                                   comm);
1638   }
1639 #ifdef HAVE_TRACING
1640   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1641 #endif
1642   smpi_bench_begin();
1643   return retval;
1644 }
1645
1646
1647 int PMPI_Get_processor_name(char *name, int *resultlen)
1648 {
1649   int retval = MPI_SUCCESS;
1650
1651   smpi_bench_end();
1652   strncpy(name, SIMIX_host_get_name(SIMIX_host_self()),
1653           MPI_MAX_PROCESSOR_NAME - 1);
1654   *resultlen =
1655       strlen(name) >
1656       MPI_MAX_PROCESSOR_NAME ? MPI_MAX_PROCESSOR_NAME : strlen(name);
1657
1658   smpi_bench_begin();
1659   return retval;
1660 }
1661
1662 int PMPI_Get_count(MPI_Status * status, MPI_Datatype datatype, int *count)
1663 {
1664   int retval = MPI_SUCCESS;
1665   size_t size;
1666
1667   smpi_bench_end();
1668   if (status == NULL || count == NULL) {
1669     retval = MPI_ERR_ARG;
1670   } else if (datatype == MPI_DATATYPE_NULL) {
1671     retval = MPI_ERR_TYPE;
1672   } else {
1673     size = smpi_datatype_size(datatype);
1674     if (size == 0) {
1675       *count = 0;
1676     } else if (status->count % size != 0) {
1677       retval = MPI_UNDEFINED;
1678     } else {
1679       *count = smpi_mpi_get_count(status, datatype);
1680     }
1681   }
1682   smpi_bench_begin();
1683   return retval;
1684 }
1685
1686 /* The following calls are not yet implemented and will fail at runtime. */
1687 /* Once implemented, please move them above this notice. */
1688
1689 static int not_yet_implemented(void) {
1690    xbt_die("Not yet implemented");
1691    return MPI_ERR_OTHER;
1692 }
1693
1694 int PMPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, int* size) {
1695    return not_yet_implemented();
1696 }
1697
1698 int PMPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int* coords) {
1699    return not_yet_implemented();
1700 }
1701
1702 int PMPI_Cart_create(MPI_Comm comm_old, int ndims, int* dims, int* periods, int reorder, MPI_Comm* comm_cart) {
1703    return not_yet_implemented();
1704 }
1705
1706 int PMPI_Cart_get(MPI_Comm comm, int maxdims, int* dims, int* periods, int* coords) {
1707    return not_yet_implemented();
1708 }
1709
1710 int PMPI_Cart_map(MPI_Comm comm_old, int ndims, int* dims, int* periods, int* newrank) {
1711    return not_yet_implemented();
1712 }
1713
1714 int PMPI_Cart_rank(MPI_Comm comm, int* coords, int* rank) {
1715    return not_yet_implemented();
1716 }
1717
1718 int PMPI_Cart_shift(MPI_Comm comm, int direction, int displ, int* source, int* dest) {
1719    return not_yet_implemented();
1720 }
1721
1722 int PMPI_Cart_sub(MPI_Comm comm, int* remain_dims, MPI_Comm* comm_new) {
1723    return not_yet_implemented();
1724 }
1725
1726 int PMPI_Cartdim_get(MPI_Comm comm, int* ndims) {
1727    return not_yet_implemented();
1728 }
1729
1730 int PMPI_Graph_create(MPI_Comm comm_old, int nnodes, int* index, int* edges, int reorder, MPI_Comm* comm_graph) {
1731    return not_yet_implemented();
1732 }
1733
1734 int PMPI_Graph_get(MPI_Comm comm, int maxindex, int maxedges, int* index, int* edges) {
1735    return not_yet_implemented();
1736 }
1737
1738 int PMPI_Graph_map(MPI_Comm comm_old, int nnodes, int* index, int* edges, int* newrank) {
1739    return not_yet_implemented();
1740 }
1741
1742 int PMPI_Graph_neighbors(MPI_Comm comm, int rank, int maxneighbors, int* neighbors) {
1743    return not_yet_implemented();
1744 }
1745
1746 int PMPI_Graph_neighbors_count(MPI_Comm comm, int rank, int* nneighbors) {
1747    return not_yet_implemented();
1748 }
1749
1750 int PMPI_Graphdims_get(MPI_Comm comm, int* nnodes, int* nedges) {
1751    return not_yet_implemented();
1752 }
1753
1754 int PMPI_Topo_test(MPI_Comm comm, int* top_type) {
1755    return not_yet_implemented();
1756 }
1757
1758 int PMPI_Error_class(int errorcode, int* errorclass) {
1759    return not_yet_implemented();
1760 }
1761
1762 int PMPI_Errhandler_create(MPI_Handler_function* function, MPI_Errhandler* errhandler) {
1763    return not_yet_implemented();
1764 }
1765
1766 int PMPI_Errhandler_free(MPI_Errhandler* errhandler) {
1767    return not_yet_implemented();
1768 }
1769
1770 int PMPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler* errhandler) {
1771    return not_yet_implemented();
1772 }
1773
1774 int PMPI_Error_string(int errorcode, char* string, int* resultlen) {
1775    return not_yet_implemented();
1776 }
1777
1778 int PMPI_Errhandler_set(MPI_Comm comm, MPI_Errhandler errhandler) {
1779    return not_yet_implemented();
1780 }
1781
1782 int PMPI_Type_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* newtype) {
1783    return not_yet_implemented();
1784 }
1785
1786 int PMPI_Cancel(MPI_Request* request) {
1787    return not_yet_implemented();
1788 }
1789
1790 int PMPI_Buffer_attach(void* buffer, int size) {
1791    return not_yet_implemented();
1792 }
1793
1794 int PMPI_Buffer_detach(void* buffer, int* size) {
1795    return not_yet_implemented();
1796 }
1797
1798 int PMPI_Testsome(int incount, MPI_Request* requests, int* outcount, int* indices, MPI_Status* statuses) {
1799    return not_yet_implemented();
1800 }
1801
1802 int PMPI_Comm_test_inter(MPI_Comm comm, int* flag) {
1803    return not_yet_implemented();
1804 }
1805
1806 int PMPI_Unpack(void* inbuf, int insize, int* position, void* outbuf, int outcount, MPI_Datatype type, MPI_Comm comm) {
1807    return not_yet_implemented();
1808 }
1809
1810 int PMPI_Type_commit(MPI_Datatype* datatype) {
1811    return not_yet_implemented();
1812 }
1813
1814 int PMPI_Type_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* newtype) {
1815    return not_yet_implemented();
1816 }
1817
1818 int PMPI_Type_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* newtype) {
1819    return not_yet_implemented();
1820 }
1821
1822 int PMPI_Type_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* newtype) {
1823    return not_yet_implemented();
1824 }
1825
1826 int PMPI_Type_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* newtype) {
1827    return not_yet_implemented();
1828 }
1829
1830 int PMPI_Type_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* newtype) {
1831    return not_yet_implemented();
1832 }
1833
1834 int PMPI_Ssend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
1835    return not_yet_implemented();
1836 }
1837
1838 int PMPI_Ssend_init(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request) {
1839    return not_yet_implemented();
1840 }
1841
1842 int PMPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm* comm_out) {
1843    return not_yet_implemented();
1844 }
1845
1846 int PMPI_Intercomm_merge(MPI_Comm comm, int high, MPI_Comm* comm_out) {
1847    return not_yet_implemented();
1848 }
1849
1850 int PMPI_Bsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
1851    return not_yet_implemented();
1852 }
1853
1854 int PMPI_Bsend_init(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request) {
1855    return not_yet_implemented();
1856 }
1857
1858 int PMPI_Ibsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request) {
1859    return not_yet_implemented();
1860 }
1861
1862 int PMPI_Comm_remote_group(MPI_Comm comm, MPI_Group* group) {
1863    return not_yet_implemented();
1864 }
1865
1866 int PMPI_Comm_remote_size(MPI_Comm comm, int* size) {
1867    return not_yet_implemented();
1868 }
1869
1870 int PMPI_Issend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request) {
1871    return not_yet_implemented();
1872 }
1873
1874 int PMPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status* status) {
1875    return not_yet_implemented();
1876 }
1877
1878 int PMPI_Attr_delete(MPI_Comm comm, int keyval) {
1879    return not_yet_implemented();
1880 }
1881
1882 int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
1883    return not_yet_implemented();
1884 }
1885
1886 int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
1887    return not_yet_implemented();
1888 }
1889
1890 int PMPI_Rsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
1891    return not_yet_implemented();
1892 }
1893
1894 int PMPI_Rsend_init(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request) {
1895    return not_yet_implemented();
1896 }
1897
1898 int PMPI_Irsend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request) {
1899    return not_yet_implemented();
1900 }
1901
1902 int PMPI_Keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state) {
1903    return not_yet_implemented();
1904 }
1905
1906 int PMPI_Keyval_free(int* keyval) {
1907    return not_yet_implemented();
1908 }
1909
1910 int PMPI_Test_cancelled(MPI_Status* status, int* flag) {
1911    return not_yet_implemented();
1912 }
1913
1914 int PMPI_Pack(void* inbuf, int incount, MPI_Datatype type, void* outbuf, int outcount, int* position, MPI_Comm comm) {
1915    return not_yet_implemented();
1916 }
1917
1918 int PMPI_Testall(int count, MPI_Request* requests, int* flag, MPI_Status* statuses) {
1919    return not_yet_implemented();
1920 }
1921
1922 int PMPI_Get_elements(MPI_Status* status, MPI_Datatype datatype, int* elements) {
1923    return not_yet_implemented();
1924 }
1925
1926 int PMPI_Dims_create(int nnodes, int ndims, int* dims) {
1927    return not_yet_implemented();
1928 }
1929
1930 int PMPI_Iprobe(int source, int tag, MPI_Comm comm, int* flag, MPI_Status* status) {
1931    return not_yet_implemented();
1932 }
1933
1934 int PMPI_Initialized(int* flag) {
1935    return not_yet_implemented();
1936 }