Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Cleanup toward persistent communications.
[simgrid.git] / src / smpi / smpi_mpi.c
1 /* $Id$tag */
2
3 #include "private.h"
4 #include "smpi_coll_private.h"
5 #include "smpi_mpi_dt_private.h"
6
7 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi, smpi,
8                                 "Logging specific to SMPI (mpi)");
9
10 /* MPI User level calls */
11
12 int MPI_Init(int* argc, char*** argv) {
13   smpi_process_init(argc, argv);
14   smpi_bench_begin(-1, NULL);
15   return MPI_SUCCESS;
16 }
17
18 int MPI_Finalize(void) {
19   smpi_bench_end(-1, NULL);
20   smpi_process_destroy();
21   return MPI_SUCCESS;
22 }
23
24 int MPI_Init_thread(int* argc, char*** argv, int required, int* provided) {
25   if(provided != NULL) {
26     *provided = MPI_THREAD_MULTIPLE;
27   }
28   return MPI_Init(argc, argv);
29 }
30
31 int MPI_Query_thread(int* provided) {
32   int retval;
33
34   smpi_bench_end(-1, NULL);
35   if(provided == NULL) {
36     retval = MPI_ERR_ARG;
37   } else {
38     *provided = MPI_THREAD_MULTIPLE;
39     retval = MPI_SUCCESS;
40   }
41   smpi_bench_begin(-1, NULL);
42   return retval;
43 }
44
45 int MPI_Is_thread_main(int* flag) {
46   int retval;
47
48   smpi_bench_end(-1, NULL);
49   if(flag == NULL) {
50     retval = MPI_ERR_ARG;
51   } else {
52     *flag = smpi_process_index() == 0;
53     retval = MPI_SUCCESS;
54   }
55   smpi_bench_begin(-1, NULL);
56   return retval;
57 }
58
59 int MPI_Abort(MPI_Comm comm, int errorcode) {
60   smpi_bench_end(-1, NULL);
61   smpi_process_destroy();
62   // FIXME: should kill all processes in comm instead
63   SIMIX_process_kill(SIMIX_process_self());
64   return MPI_SUCCESS;
65 }
66
67 double MPI_Wtime(void) {
68   double time;
69
70   smpi_bench_end(-1, NULL);
71   time = SIMIX_get_clock();
72   smpi_bench_begin(-1, NULL);
73   return time;
74 }
75
76 int MPI_Address(void *location, MPI_Aint *address) {
77   int retval;
78
79   smpi_bench_end(-1, NULL);
80   if(!address) {
81     retval = MPI_ERR_ARG;
82   } else {
83     *address = (MPI_Aint)location;
84   }
85   smpi_bench_begin(-1, NULL);
86   return retval;
87 }
88
89 int MPI_Type_free(MPI_Datatype* datatype) {
90   int retval;
91
92   smpi_bench_end(-1, NULL);
93   if(!datatype) {
94     retval = MPI_ERR_ARG;
95   } else {
96     // FIXME: always fail for now
97     retval = MPI_ERR_TYPE;
98   }
99   smpi_bench_begin(-1, NULL);
100   return retval;
101 }
102
103 int MPI_Type_size(MPI_Datatype datatype, size_t* size) {
104   int retval;
105
106   smpi_bench_end(-1, NULL);
107   if(datatype == MPI_DATATYPE_NULL) {
108     retval = MPI_ERR_TYPE;
109   } else if(size == NULL) {
110     retval = MPI_ERR_ARG;
111   } else {
112     *size = smpi_datatype_size(datatype);
113     retval = MPI_SUCCESS;
114   }
115   smpi_bench_begin(-1, NULL);
116   return retval;
117 }
118
119 int MPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint* lb, MPI_Aint* extent) {
120   int retval;
121
122   smpi_bench_end(-1, NULL);
123   if(datatype == MPI_DATATYPE_NULL) {
124     retval = MPI_ERR_TYPE;
125   } else if(lb == NULL || extent == NULL) {
126     retval = MPI_ERR_ARG;
127   } else {
128     retval = smpi_datatype_extent(datatype, lb, extent);
129   }
130   smpi_bench_begin(-1, NULL);
131   return retval;
132 }
133
134 int MPI_Type_extent(MPI_Datatype datatype, MPI_Aint* extent) {
135   int retval;
136   MPI_Aint dummy;
137
138   smpi_bench_end(-1, NULL);
139   if(datatype == MPI_DATATYPE_NULL) {
140     retval = MPI_ERR_TYPE;
141   } else if(extent == NULL) {
142     retval = MPI_ERR_ARG;
143   } else {
144     retval = smpi_datatype_extent(datatype, &dummy, extent);
145   }
146   smpi_bench_begin(-1, NULL);
147   return retval;
148 }
149
150 int MPI_Type_lb(MPI_Datatype datatype, MPI_Aint* disp) {
151   int retval;
152
153   smpi_bench_end(-1, NULL);
154   if(datatype == MPI_DATATYPE_NULL) {
155     retval = MPI_ERR_TYPE;
156   } else if(disp == NULL) {
157     retval = MPI_ERR_ARG;
158   } else {
159     *disp = smpi_datatype_lb(datatype);
160     retval = MPI_SUCCESS;
161   }
162   smpi_bench_begin(-1, NULL);
163   return retval;
164 }
165
166 int MPI_Type_ub(MPI_Datatype datatype, MPI_Aint* disp) {
167   int retval;
168
169   smpi_bench_end(-1, NULL);
170   if(datatype == MPI_DATATYPE_NULL) {
171     retval = MPI_ERR_TYPE;
172   } else if(disp == NULL) {
173     retval = MPI_ERR_ARG;
174   } else {
175     *disp = smpi_datatype_ub(datatype);
176     retval = MPI_SUCCESS;
177   }
178   smpi_bench_begin(-1, NULL);
179   return retval;
180 }
181
182 int MPI_Op_create(MPI_User_function* function, int commute, MPI_Op* op) {
183   int retval;
184
185   smpi_bench_end(-1, NULL);
186   if(function == NULL || op == NULL) {
187     retval = MPI_ERR_ARG;
188   } else {
189     *op = smpi_op_new(function, commute);
190     retval = MPI_SUCCESS;
191   }
192   smpi_bench_begin(-1, NULL);
193   return retval;
194 }
195
196 int MPI_Op_free(MPI_Op* op) {
197   int retval;
198
199   smpi_bench_end(-1, NULL);
200   if(op == NULL) {
201     retval = MPI_ERR_ARG;
202   } else if(*op == MPI_OP_NULL) {
203     retval = MPI_ERR_OP;
204   } else {
205     smpi_op_destroy(*op);
206     *op = MPI_OP_NULL;
207     retval = MPI_SUCCESS;
208   }
209   smpi_bench_begin(-1, NULL);
210   return retval;
211 }
212
213 int MPI_Group_free(MPI_Group *group) {
214   int retval;
215
216   smpi_bench_end(-1, NULL);
217   if(group == NULL) {
218     retval = MPI_ERR_ARG;
219   } else {
220     smpi_group_destroy(*group);
221     *group = MPI_GROUP_NULL;
222     retval = MPI_SUCCESS;
223   }
224   smpi_bench_begin(-1, NULL);
225   return retval;
226 }
227
228 int MPI_Group_size(MPI_Group group, int* size) {
229   int retval;
230
231   smpi_bench_end(-1, NULL);
232   if(group == MPI_GROUP_NULL) {
233     retval = MPI_ERR_GROUP;
234   } else if(size == NULL) {
235     retval = MPI_ERR_ARG;
236   } else {
237     *size = smpi_group_size(group);
238     retval = MPI_SUCCESS;
239   }
240   smpi_bench_begin(-1, NULL);
241   return retval;
242 }
243
244 int MPI_Group_rank(MPI_Group group, int* rank) {
245   int retval;
246
247   smpi_bench_end(-1, NULL);
248   if(group == MPI_GROUP_NULL) {
249     retval = MPI_ERR_GROUP;
250   } else if(rank == NULL) {
251     retval = MPI_ERR_ARG;
252   } else {
253     *rank = smpi_group_rank(group, smpi_process_index());
254     retval = MPI_SUCCESS;
255   }
256   smpi_bench_begin(-1, NULL);
257   return retval;
258 }
259
260 int MPI_Group_translate_ranks (MPI_Group group1, int n, int* ranks1, MPI_Group group2, int* ranks2) {
261   int retval, i, index;
262
263   smpi_bench_end(-1, NULL);
264   if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
265     retval = MPI_ERR_GROUP;
266   } else {
267     for(i = 0; i < n; i++) {
268       index = smpi_group_index(group1, ranks1[i]);
269       ranks2[i] = smpi_group_rank(group2, index);
270     }
271     retval = MPI_SUCCESS;
272   }
273   smpi_bench_begin(-1, NULL);
274   return retval;
275 }
276
277 int MPI_Group_compare(MPI_Group group1, MPI_Group group2, int* result) {
278   int retval;
279
280   smpi_bench_end(-1, NULL);
281   if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
282     retval = MPI_ERR_GROUP;
283   } else if(result == NULL) {
284     retval = MPI_ERR_ARG;
285   } else {
286     *result = smpi_group_compare(group1, group2);
287     retval = MPI_SUCCESS;
288   }
289   smpi_bench_begin(-1, NULL);
290   return retval;
291 }
292
293 int MPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group* newgroup) {
294   int retval, i, proc1, proc2, size, size2;
295
296   smpi_bench_end(-1, NULL);
297   if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
298     retval = MPI_ERR_GROUP;
299   } else if(newgroup == NULL) {
300     retval = MPI_ERR_ARG;
301   } else {
302     size = smpi_group_size(group1);
303     size2 = smpi_group_size(group2);
304     for(i = 0; i < size2; i++) {
305       proc2 = smpi_group_index(group2, i);
306       proc1 = smpi_group_rank(group1, proc2);
307       if(proc1 == MPI_UNDEFINED) {
308         size++;
309       }
310     }
311     if(size == 0) {
312       *newgroup = MPI_GROUP_EMPTY;
313     } else {
314       *newgroup = smpi_group_new(size);
315       size2 = smpi_group_size(group1);
316       for(i = 0; i < size2; i++) {
317         proc1 = smpi_group_index(group1, i);
318         smpi_group_set_mapping(*newgroup, proc1, i);
319       }
320       for(i = size2; i < size; i++) {
321         proc2 = smpi_group_index(group2, i - size2);
322         smpi_group_set_mapping(*newgroup, proc2, i);
323       }
324     }
325     smpi_group_use(*newgroup);
326     retval = MPI_SUCCESS;
327   }
328   smpi_bench_begin(-1, NULL);
329   return retval;
330 }
331
332 int MPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group* newgroup) {
333    int retval, i, proc1, proc2, size, size2;
334
335   smpi_bench_end(-1, NULL);
336   if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
337     retval = MPI_ERR_GROUP;
338   } else if(newgroup == NULL) {
339     retval = MPI_ERR_ARG;
340   } else {
341     size = smpi_group_size(group1);
342     size2 = smpi_group_size(group2);
343     for(i = 0; i < size2; i++) {
344       proc2 = smpi_group_index(group2, i);
345       proc1 = smpi_group_rank(group1, proc2);
346       if(proc1 == MPI_UNDEFINED) {
347         size--;
348       }
349     }
350     if(size == 0) {
351       *newgroup = MPI_GROUP_EMPTY;
352     } else {
353       *newgroup = smpi_group_new(size);
354       size2 = smpi_group_size(group1);
355       for(i = 0; i < size2; i++) {
356         proc1 = smpi_group_index(group1, i);
357         proc2 = smpi_group_rank(group2, proc1);
358         if(proc2 != MPI_UNDEFINED) {
359           smpi_group_set_mapping(*newgroup, proc1, i);
360         }
361       }
362     }
363     smpi_group_use(*newgroup);
364     retval = MPI_SUCCESS;
365   }
366   smpi_bench_begin(-1, NULL);
367   return retval;
368 }
369
370 int MPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group* newgroup) {
371   int retval, i, proc1, proc2, size, size2;
372
373   smpi_bench_end(-1, NULL);
374   if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
375     retval = MPI_ERR_GROUP;
376   } else if(newgroup == NULL) {
377     retval = MPI_ERR_ARG;
378   } else {
379     size = size2 = smpi_group_size(group1);
380     for(i = 0; i < size2; i++) {
381       proc1 = smpi_group_index(group1, i);
382       proc2 = smpi_group_rank(group2, proc1);
383       if(proc2 != MPI_UNDEFINED) {
384         size--;
385       }
386     }
387     if(size == 0) {
388       *newgroup = MPI_GROUP_EMPTY;
389     } else {
390       *newgroup = smpi_group_new(size);
391       for(i = 0; i < size2; i++) {
392         proc1 = smpi_group_index(group1, i);
393         proc2 = smpi_group_rank(group2, proc1);
394         if(proc2 == MPI_UNDEFINED) {
395           smpi_group_set_mapping(*newgroup, proc1, i);
396         }
397       }
398     }
399     smpi_group_use(*newgroup);
400     retval = MPI_SUCCESS;
401   }
402   smpi_bench_begin(-1, NULL);
403   return retval;
404 }
405
406 int MPI_Group_incl(MPI_Group group, int n, int* ranks, MPI_Group* newgroup) {
407   int retval, i, index;
408
409   smpi_bench_end(-1, NULL);
410   if(group == MPI_GROUP_NULL) {
411     retval = MPI_ERR_GROUP;
412   } else if(newgroup == NULL) {
413     retval = MPI_ERR_ARG;
414   } else {
415     if(n == 0) {
416       *newgroup = MPI_GROUP_EMPTY;
417     } else if(n == smpi_group_size(group)) {
418       *newgroup = group;
419     } else {
420       *newgroup = smpi_group_new(n);
421       for(i = 0; i < n; i++) {
422         index = smpi_group_index(group, ranks[i]);
423         smpi_group_set_mapping(*newgroup, index, i);
424       }
425     }
426     smpi_group_use(*newgroup);
427     retval = MPI_SUCCESS;
428   }
429   smpi_bench_begin(-1, NULL);
430   return retval;
431 }
432
433 int MPI_Group_excl(MPI_Group group, int n, int* ranks, MPI_Group* newgroup) {
434   int retval, i, size, rank, index;
435
436   smpi_bench_end(-1, NULL);
437   if(group == MPI_GROUP_NULL) {
438     retval = MPI_ERR_GROUP;
439   } else if(newgroup == NULL) {
440     retval = MPI_ERR_ARG;
441   } else {
442     if(n == 0) {
443       *newgroup = group;
444     } else if(n == smpi_group_size(group)) {
445       *newgroup = MPI_GROUP_EMPTY;
446     } else {
447       size = smpi_group_size(group) - n;
448       *newgroup = smpi_group_new(size);
449       rank = 0;
450       while(rank < size) {
451         for(i = 0; i < n; i++) {
452           if(ranks[i] == rank) {
453             break;
454           }
455         }
456         if(i >= n) {
457           index = smpi_group_index(group, rank);
458           smpi_group_set_mapping(*newgroup, index, rank);
459           rank++;
460         }
461       }
462     }
463     smpi_group_use(*newgroup);
464     retval = MPI_SUCCESS;
465   }
466   smpi_bench_begin(-1, NULL);
467   return retval;
468 }
469
470 int MPI_Group_range_incl(MPI_Group group, int n, int ranges[][3], MPI_Group* newgroup) {
471   int retval, i, j, rank, size, index;
472
473   smpi_bench_end(-1, NULL);
474   if(group == MPI_GROUP_NULL) {
475     retval = MPI_ERR_GROUP;
476   } else if(newgroup == NULL) {
477     retval = MPI_ERR_ARG;
478   } else {
479     if(n == 0) {
480       *newgroup = MPI_GROUP_EMPTY;
481     } else {
482       size = 0;
483       for(i = 0; i < n; i++) {
484         for(rank = ranges[i][0]; /* First */
485             rank >= 0 && rank <= ranges[i][1]; /* Last */
486             rank += ranges[i][2] /* Stride */) {
487           size++;
488         }
489       }
490       if(size == smpi_group_size(group)) {
491         *newgroup = group;
492       } else {
493         *newgroup = smpi_group_new(size);
494         j = 0;
495         for(i = 0; i < n; i++) {
496           for(rank = ranges[i][0]; /* First */
497               rank >= 0 && rank <= ranges[i][1]; /* Last */
498               rank += ranges[i][2] /* Stride */) {
499             index = smpi_group_index(group, rank);
500             smpi_group_set_mapping(*newgroup, index, j);
501             j++;
502           }
503         }
504       }
505     }
506     smpi_group_use(*newgroup);
507     retval = MPI_SUCCESS;
508   }
509   smpi_bench_begin(-1, NULL);
510   return retval;
511 }
512
513 int MPI_Group_range_excl(MPI_Group group, int n, int ranges[][3], MPI_Group* newgroup) {
514   int retval, i, newrank, rank, size, index, add;
515
516   smpi_bench_end(-1, NULL);
517   if(group == MPI_GROUP_NULL) {
518     retval = MPI_ERR_GROUP;
519   } else if(newgroup == NULL) {
520     retval = MPI_ERR_ARG;
521   } else {
522     if(n == 0) {
523       *newgroup = group;
524     } else {
525       size = smpi_group_size(group);
526       for(i = 0; i < n; i++) {
527         for(rank = ranges[i][0]; /* First */
528             rank >= 0 && rank <= ranges[i][1]; /* Last */
529             rank += ranges[i][2] /* Stride */) {
530           size--;
531         }
532       }
533       if(size == 0) {
534         *newgroup = MPI_GROUP_EMPTY;
535       } else {
536         *newgroup = smpi_group_new(size);
537         newrank = 0;
538         while(newrank < size) {
539           for(i = 0; i < n; i++) {
540             add = 1;
541             for(rank = ranges[i][0]; /* First */
542                 rank >= 0 && rank <= ranges[i][1]; /* Last */
543                 rank += ranges[i][2] /* Stride */) {
544               if(rank == newrank) {
545                 add = 0;
546                 break;
547               }
548             }
549             if(add == 1) {
550               index = smpi_group_index(group, newrank);
551               smpi_group_set_mapping(*newgroup, index, newrank);
552             }
553           }
554         }
555       }
556     }
557     smpi_group_use(*newgroup);
558     retval = MPI_SUCCESS;
559   }
560   smpi_bench_begin(-1, NULL);
561   return retval;
562 }
563
564 int MPI_Comm_rank(MPI_Comm comm, int* rank) {
565   int retval;
566
567   smpi_bench_end(-1, NULL);
568   if(comm == MPI_COMM_NULL) {
569     retval = MPI_ERR_COMM;
570   } else {
571     *rank = smpi_comm_rank(comm);
572     retval = MPI_SUCCESS;
573   }
574   smpi_bench_begin(-1, NULL);
575   return retval;
576 }
577
578 int MPI_Comm_size(MPI_Comm comm, int* size) {
579   int retval;
580
581   smpi_bench_end(-1, NULL);
582   if(comm == MPI_COMM_NULL) {
583     retval = MPI_ERR_COMM;
584   } else if(size == NULL) {
585     retval = MPI_ERR_ARG;
586   } else {
587     *size = smpi_comm_size(comm);
588     retval = MPI_SUCCESS;
589   }
590   smpi_bench_begin(-1, NULL);
591   return retval;
592 }
593
594 int MPI_Comm_group(MPI_Comm comm, MPI_Group* group) {
595   int retval;
596
597   smpi_bench_end(-1, NULL);
598   if(comm == MPI_COMM_NULL) {
599     retval = MPI_ERR_COMM;
600   } else if(group == NULL) {
601     retval = MPI_ERR_ARG;
602   } else {
603     *group = smpi_comm_group(comm);
604     retval = MPI_SUCCESS;
605   }
606   smpi_bench_begin(-1, NULL);
607   return retval;
608 }
609
610 int MPI_Comm_compare(MPI_Comm comm1, MPI_Comm comm2, int* result) {
611   int retval;
612
613   smpi_bench_end(-1, NULL);
614   if(comm1 == MPI_COMM_NULL || comm2 == MPI_COMM_NULL) {
615     retval = MPI_ERR_COMM;
616   } else if(result == NULL) {
617     retval = MPI_ERR_ARG;
618   } else {
619     if(comm1 == comm2) { /* Same communicators means same groups */
620       *result = MPI_IDENT;
621     } else {
622       *result = smpi_group_compare(smpi_comm_group(comm1), smpi_comm_group(comm2));
623       if(*result == MPI_IDENT) {
624         *result = MPI_CONGRUENT;
625       }
626     }
627     retval = MPI_SUCCESS;
628   }
629   smpi_bench_begin(-1, NULL);
630   return retval;
631 }
632
633 int MPI_Comm_dup(MPI_Comm comm, MPI_Comm* newcomm) {
634   int retval;
635
636   smpi_bench_end(-1, NULL);
637   if(comm == MPI_COMM_NULL) {
638     retval = MPI_ERR_COMM;
639   } else if(newcomm == NULL) {
640     retval = MPI_ERR_ARG;
641   } else {
642     *newcomm = smpi_comm_new(smpi_comm_group(comm));
643     retval = MPI_SUCCESS;
644   }
645   smpi_bench_begin(-1, NULL);
646   return retval;
647 }
648
649 int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm* newcomm) {
650   int retval;
651
652   smpi_bench_end(-1, NULL);
653   if(comm == MPI_COMM_NULL) {
654     retval = MPI_ERR_COMM;
655   } else if(group == MPI_GROUP_NULL) {
656     retval = MPI_ERR_GROUP;
657   } else if(newcomm == NULL) {
658     retval = MPI_ERR_ARG;
659   } else {
660     *newcomm = smpi_comm_new(group);
661     retval = MPI_SUCCESS;
662   }
663   smpi_bench_begin(-1, NULL);
664   return retval;
665 }
666
667 int MPI_Comm_free(MPI_Comm* comm) {
668   int retval;
669
670   smpi_bench_end(-1, NULL);
671   if(comm == NULL) {
672     retval = MPI_ERR_ARG;
673   } else if(*comm == MPI_COMM_NULL) {
674     retval = MPI_ERR_COMM;
675   } else {
676     smpi_comm_destroy(*comm);
677     *comm = MPI_COMM_NULL;
678     retval = MPI_SUCCESS;
679   }
680   smpi_bench_begin(-1, NULL);
681   return retval;
682 }
683
684 int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Request* request) {
685   int retval;
686   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
687
688   smpi_bench_end(rank, "Irecv");
689   if(request == NULL) {
690     retval = MPI_ERR_ARG;
691   } else if (comm == MPI_COMM_NULL) {
692     retval = MPI_ERR_COMM;
693   } else {
694     *request = smpi_mpi_irecv(buf, count, datatype, src, tag, comm);
695     retval = MPI_SUCCESS;
696   }
697   smpi_bench_begin(rank, "Irecv");
698   return retval;
699 }
700
701 int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request* request) {
702   int retval;
703   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
704
705   smpi_bench_end(rank, "Isend");
706   if(request == NULL) {
707     retval = MPI_ERR_ARG;
708   } else if (comm == MPI_COMM_NULL) {
709     retval = MPI_ERR_COMM;
710   } else {
711     *request = smpi_mpi_isend(buf, count, datatype, dst, tag, comm);
712     retval = MPI_SUCCESS;
713   }
714   smpi_bench_begin(rank, "Isend");
715   return retval;
716 }
717
718 int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Status* status) {
719   int retval;
720   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
721
722   smpi_bench_end(rank, "Recv");
723   if (comm == MPI_COMM_NULL) {
724     retval = MPI_ERR_COMM;
725   } else {
726     smpi_mpi_recv(buf, count, datatype, src, tag, comm, status);
727     retval = MPI_SUCCESS;
728   }
729   smpi_bench_begin(rank, "Recv");
730   return retval;
731 }
732
733 int MPI_Send(void* buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm) {
734   int retval;
735   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
736
737   smpi_bench_end(rank, "Send");
738   if (comm == MPI_COMM_NULL) {
739     retval = MPI_ERR_COMM;
740   } else {
741     smpi_mpi_send(buf, count, datatype, dst, tag, comm);
742     retval = MPI_SUCCESS;
743   }
744   smpi_bench_begin(rank, "Send");
745   return retval;
746 }
747
748 int MPI_Sendrecv(void* sendbuf, int sendcount, MPI_Datatype sendtype, int dst, int sendtag, void* recvbuf, int recvcount, MPI_Datatype recvtype, int src, int recvtag, MPI_Comm comm, MPI_Status* status) {
749   int retval;
750   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
751
752   smpi_bench_end(rank, "Sendrecv");
753   if (comm == MPI_COMM_NULL) {
754     retval = MPI_ERR_COMM;
755   } else if (sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
756     retval = MPI_ERR_TYPE;
757   } else {
758     smpi_mpi_sendrecv(sendbuf, sendcount, sendtype, dst, sendtag, recvbuf, recvcount, recvtype, src, recvtag, comm, status);
759     retval = MPI_SUCCESS;
760   }
761   smpi_bench_begin(rank, "Sendrecv");
762   return retval;
763 }
764
765 int MPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype, int dst, int sendtag, int src, int recvtag, MPI_Comm comm, MPI_Status* status) {
766   //TODO: suboptimal implementation
767   void* recvbuf;
768   int retval, size;
769
770   size = smpi_datatype_size(datatype) * count;
771   recvbuf = xbt_new(char, size);
772   retval = MPI_Sendrecv(buf, count, datatype, dst, sendtag, recvbuf, count, datatype, src, recvtag, comm, status);
773   memcpy(buf, recvbuf, size * sizeof(char));
774   xbt_free(recvbuf);
775   return retval;
776 }
777
778 int MPI_Test(MPI_Request* request, int* flag, MPI_Status* status) {
779   int retval;
780   int rank = request && (*request)->comm != MPI_COMM_NULL
781              ? smpi_comm_rank((*request)->comm)
782              : -1;
783
784   smpi_bench_end(rank, "Test");
785   if(request == NULL || flag == NULL) {
786     retval = MPI_ERR_ARG;
787   } else if(*request == MPI_REQUEST_NULL) {
788     retval = MPI_ERR_REQUEST;
789   } else {
790     *flag = smpi_mpi_test(request, status);
791     retval = MPI_SUCCESS;
792   }
793   smpi_bench_begin(rank, "Test");
794   return retval;
795 }
796
797 int MPI_Testany(int count, MPI_Request requests[], int* index, int* flag, MPI_Status* status) {
798   int retval;
799
800   smpi_bench_end(-1, NULL); //FIXME
801   if(index == NULL || flag == NULL) {
802     retval = MPI_ERR_ARG;
803   } else {
804     *flag = smpi_mpi_testany(count, requests, index, status);
805     retval = MPI_SUCCESS;
806   }
807   smpi_bench_begin(-1, NULL);
808   return retval;
809 }
810
811 int MPI_Wait(MPI_Request* request, MPI_Status* status) {
812   int retval;
813   int rank = request && (*request)->comm != MPI_COMM_NULL
814              ? smpi_comm_rank((*request)->comm)
815              : -1;
816
817   smpi_bench_end(rank, "Wait");
818   if(request == NULL) {
819     retval = MPI_ERR_ARG;
820   } else if(*request == MPI_REQUEST_NULL) {
821     retval = MPI_ERR_REQUEST;
822   } else {
823     smpi_mpi_wait(request, status);
824     retval = MPI_SUCCESS;
825   }
826   smpi_bench_begin(rank, "Wait");
827   return retval;
828 }
829
830 int MPI_Waitany(int count, MPI_Request requests[], int* index, MPI_Status* status) {
831   int retval;
832
833   smpi_bench_end(-1, NULL); //FIXME
834   if(index == NULL) {
835     retval = MPI_ERR_ARG;
836   } else {
837     *index = smpi_mpi_waitany(count, requests, status);
838     retval = MPI_SUCCESS;
839   }
840   smpi_bench_begin(-1, NULL);
841   return retval;
842 }
843
844 int MPI_Waitall(int count, MPI_Request requests[],  MPI_Status status[]) {
845   smpi_bench_end(-1, NULL); //FIXME
846   smpi_mpi_waitall(count, requests, status);
847   smpi_bench_begin(-1, NULL);
848   return MPI_SUCCESS;
849 }
850
851 int MPI_Waitsome(int incount, MPI_Request requests[], int* outcount, int* indices, MPI_Status status[]) {
852   int retval;
853
854   smpi_bench_end(-1, NULL); //FIXME
855   if(outcount == NULL || indices == NULL) {
856     retval = MPI_ERR_ARG;
857   } else {
858     *outcount = smpi_mpi_waitsome(incount, requests, indices, status);
859     retval = MPI_SUCCESS;
860   }
861   smpi_bench_begin(-1, NULL);
862   return retval;
863 }
864
865 int MPI_Bcast(void* buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) {
866   int retval;
867   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
868
869   smpi_bench_end(rank, "Bcast");
870   if(comm == MPI_COMM_NULL) {
871     retval = MPI_ERR_COMM;
872   } else {
873     smpi_mpi_bcast(buf, count, datatype, root, comm);
874     retval = MPI_SUCCESS;
875   }
876   smpi_bench_begin(rank, "Bcast");
877   return retval;
878 }
879
880 int MPI_Barrier(MPI_Comm comm) {
881   int retval;
882   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
883
884   smpi_bench_end(rank, "Barrier");
885   if(comm == MPI_COMM_NULL) {
886     retval = MPI_ERR_COMM;
887   } else {
888     smpi_mpi_barrier(comm);
889     retval = MPI_SUCCESS;
890   }
891   smpi_bench_begin(rank, "Barrier");
892   return retval;
893 }
894
895 int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) {
896   int retval;
897   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
898
899   smpi_bench_end(rank, "Gather");
900   if(comm == MPI_COMM_NULL) {
901     retval = MPI_ERR_COMM;
902   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
903     retval = MPI_ERR_TYPE;
904   } else {
905     smpi_mpi_gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm);
906     retval = MPI_SUCCESS;
907   }
908   smpi_bench_begin(rank, "Gather");
909   return retval;
910 }
911
912 int MPI_Gatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int* recvcounts, int* displs, MPI_Datatype recvtype, int root, MPI_Comm comm) {
913   int retval;
914   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
915
916   smpi_bench_end(rank, "Gatherv");
917   if(comm == MPI_COMM_NULL) {
918     retval = MPI_ERR_COMM;
919   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
920     retval = MPI_ERR_TYPE;
921   } else if(recvcounts == NULL || displs == NULL) {
922     retval = MPI_ERR_ARG;
923   } else {
924     smpi_mpi_gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm);
925     retval = MPI_SUCCESS;
926   }
927   smpi_bench_begin(rank, "Gatherv");
928   return retval;
929 }
930
931 int MPI_Allgather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) {
932   int retval;
933   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
934
935   smpi_bench_end(rank, "Allgather");
936   if(comm == MPI_COMM_NULL) {
937     retval = MPI_ERR_COMM;
938   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
939     retval = MPI_ERR_TYPE;
940   } else {
941     smpi_mpi_allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
942     retval = MPI_SUCCESS;
943   }
944   smpi_bench_begin(rank, "Allgather");
945   return retval;
946 }
947
948 int MPI_Allgatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int* recvcounts, int* displs, MPI_Datatype recvtype, MPI_Comm comm) {
949   int retval;
950   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
951
952   smpi_bench_end(rank, "Allgatherv");
953   if(comm == MPI_COMM_NULL) {
954     retval = MPI_ERR_COMM;
955   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
956     retval = MPI_ERR_TYPE;
957   } else if(recvcounts == NULL || displs == NULL) {
958     retval = MPI_ERR_ARG;
959   } else {
960     smpi_mpi_allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm);
961     retval = MPI_SUCCESS;
962   }
963   smpi_bench_begin(rank, "Allgatherv");
964   return retval;
965 }
966
967 int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) {
968   int retval;
969   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
970
971   smpi_bench_end(rank, "Scatter");
972   if(comm == MPI_COMM_NULL) {
973     retval = MPI_ERR_COMM;
974   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
975     retval = MPI_ERR_TYPE;
976   } else {
977     smpi_mpi_scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm);
978     retval = MPI_SUCCESS;
979   }
980   smpi_bench_begin(rank, "Scatter");
981   return retval;
982 }
983
984 int MPI_Scatterv(void* sendbuf, int* sendcounts, int* displs, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm) {
985   int retval;
986   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
987
988   smpi_bench_end(rank, "Scatterv");
989   if(comm == MPI_COMM_NULL) {
990     retval = MPI_ERR_COMM;
991   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
992     retval = MPI_ERR_TYPE;
993   } else if(sendcounts == NULL || displs == NULL) {
994     retval = MPI_ERR_ARG;
995   } else {
996     smpi_mpi_scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm);
997     retval = MPI_SUCCESS;
998   }
999   smpi_bench_begin(rank, "Scatterv");
1000   return retval;
1001 }
1002
1003 int MPI_Reduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) {
1004   int retval;
1005   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1006
1007   smpi_bench_end(rank, "Reduce");
1008   if(comm == MPI_COMM_NULL) {
1009     retval = MPI_ERR_COMM;
1010   } else if(datatype == MPI_DATATYPE_NULL || op == MPI_OP_NULL) {
1011     retval = MPI_ERR_ARG;
1012   } else {
1013     smpi_mpi_reduce(sendbuf, recvbuf, count, datatype, op, root, comm);
1014     retval = MPI_SUCCESS;
1015   }
1016   smpi_bench_begin(rank, "Reduce");
1017   return retval;
1018 }
1019
1020 int MPI_Allreduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) {
1021   int retval;
1022   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1023
1024   smpi_bench_end(rank, "Allreduce");
1025   if(comm == MPI_COMM_NULL) {
1026     retval = MPI_ERR_COMM;
1027   } else if(datatype == MPI_DATATYPE_NULL) {
1028     retval = MPI_ERR_TYPE;
1029   } else if(op == MPI_OP_NULL) {
1030     retval = MPI_ERR_OP;
1031   } else {
1032     smpi_mpi_allreduce(sendbuf, recvbuf, count, datatype, op, comm);
1033     retval = MPI_SUCCESS;
1034   }
1035   smpi_bench_begin(rank, "Allreduce");
1036   return retval;
1037 }
1038
1039 int MPI_Scan(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) {
1040   int retval;
1041   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1042
1043   smpi_bench_end(rank, "Scan");
1044   if(comm == MPI_COMM_NULL) {
1045     retval = MPI_ERR_COMM;
1046   } else if(datatype == MPI_DATATYPE_NULL) {
1047     retval = MPI_ERR_TYPE;
1048   } else if(op == MPI_OP_NULL) {
1049     retval = MPI_ERR_OP;
1050   } else {
1051     smpi_mpi_scan(sendbuf, recvbuf, count, datatype, op, comm);
1052     retval = MPI_SUCCESS;
1053   }
1054   smpi_bench_begin(rank, "Scan");
1055   return retval;
1056 }
1057
1058 int MPI_Reduce_scatter(void* sendbuf, void* recvbuf, int* recvcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) {
1059   int retval, i, size, count;
1060   int* displs;
1061   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1062
1063   smpi_bench_end(rank, "Reduce_scatter");
1064   if(comm == MPI_COMM_NULL) {
1065     retval = MPI_ERR_COMM;
1066   } else if(datatype == MPI_DATATYPE_NULL) {
1067     retval = MPI_ERR_TYPE;
1068   } else if(op == MPI_OP_NULL) {
1069     retval = MPI_ERR_OP;
1070   } else if(recvcounts == NULL) {
1071     retval = MPI_ERR_ARG;
1072   } else {
1073     /* arbitrarily choose root as rank 0 */
1074     /* TODO: faster direct implementation ? */
1075     size = smpi_comm_size(comm);
1076     count = 0;
1077     displs = xbt_new(int, size);
1078     for(i = 0; i < size; i++) {
1079       count += recvcounts[i];
1080       displs[i] = 0;
1081     }
1082     smpi_mpi_reduce(sendbuf, recvbuf, count, datatype, op, 0, comm);
1083     smpi_mpi_scatterv(recvbuf, recvcounts, displs, datatype, recvbuf, recvcounts[rank], datatype, 0, comm);
1084     xbt_free(displs);
1085     retval = MPI_SUCCESS;
1086   }
1087   smpi_bench_begin(rank, "Reduce_scatter");
1088   return retval;
1089 }
1090
1091 int MPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) {
1092   int retval, size, sendsize;
1093   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1094
1095   smpi_bench_end(rank, "Alltoall");
1096   if(comm == MPI_COMM_NULL) {
1097     retval = MPI_ERR_COMM;
1098   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
1099     retval = MPI_ERR_TYPE;
1100   } else {
1101     size = smpi_comm_size(comm);
1102     sendsize = smpi_datatype_size(sendtype) * sendcount;
1103     if(sendsize < 200 && size > 12) {
1104       retval = smpi_coll_tuned_alltoall_bruck(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
1105     } else if(sendsize < 3000) {
1106       retval = smpi_coll_tuned_alltoall_basic_linear(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
1107     } else {
1108       retval = smpi_coll_tuned_alltoall_pairwise(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
1109     }
1110   }
1111   smpi_bench_begin(rank, "Alltoall");
1112   return retval;
1113 }
1114
1115 int MPI_Alltoallv(void* sendbuf, int* sendcounts, int* senddisps, MPI_Datatype sendtype, void* recvbuf, int *recvcounts, int* recvdisps, MPI_Datatype recvtype, MPI_Comm comm) {
1116   int retval;
1117   int rank = comm != MPI_COMM_NULL ? smpi_comm_rank(comm) : -1;
1118
1119   smpi_bench_end(rank, "Alltoallv");
1120   if(comm == MPI_COMM_NULL) {
1121     retval = MPI_ERR_COMM;
1122   } else if(sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
1123     retval = MPI_ERR_TYPE;
1124   } else if(sendcounts == NULL || senddisps == NULL || recvcounts == NULL || recvdisps == NULL) {
1125     retval = MPI_ERR_ARG;
1126   } else {
1127     retval = smpi_coll_basic_alltoallv(sendbuf, sendcounts, senddisps, sendtype, recvbuf, recvcounts, recvdisps, recvtype, comm);
1128   }
1129   smpi_bench_begin(rank, "Alltoallv");
1130   return retval;
1131 }
1132
1133
1134 int MPI_Get_processor_name( char *name, int *resultlen ) {
1135   int retval = MPI_SUCCESS;
1136   smpi_bench_end(-1, NULL);
1137   strncpy( name , SIMIX_host_get_name(SIMIX_host_self()), MPI_MAX_PROCESSOR_NAME-1);
1138   *resultlen= strlen(name) > MPI_MAX_PROCESSOR_NAME ? MPI_MAX_PROCESSOR_NAME : strlen(name);
1139
1140   smpi_bench_begin(-1, NULL);
1141   return retval;
1142 }
1143