Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
[simgrid.git] / src / smpi / smpi_pmpi.cpp
1 /* Copyright (c) 2007-2017. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include <simgrid/s4u/host.hpp>
7 #include <xbt/ex.hpp>
8
9 #include "private.h"
10 #include "smpi_mpi_dt_private.h"
11
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_pmpi, smpi, "Logging specific to SMPI (pmpi)");
13
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
24 /* PMPI User level calls */
25 extern "C" { // Obviously, the C MPI interface should use the C linkage
26
27 int PMPI_Init(int *argc, char ***argv)
28 {
29   // PMPI_Init is call only one time by only by SMPI process
30   int already_init;
31   MPI_Initialized(&already_init);
32   if(already_init == 0){
33     smpi_process_init(argc, argv);
34     smpi_process_mark_as_initialized();
35     int rank = smpi_process_index();
36     TRACE_smpi_init(rank);
37     TRACE_smpi_computing_init(rank);
38     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
39     extra->type = TRACING_INIT;
40     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
41     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
42     smpi_bench_begin();
43   }
44
45   smpi_mpi_init();
46
47   return MPI_SUCCESS;
48 }
49
50 int PMPI_Finalize()
51 {
52   smpi_bench_end();
53   int rank = smpi_process_index();
54   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
55   extra->type = TRACING_FINALIZE;
56   TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
57
58   smpi_process_finalize();
59
60   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
61   TRACE_smpi_finalize(smpi_process_index());
62   smpi_process_destroy();
63   return MPI_SUCCESS;
64 }
65
66 int PMPI_Finalized(int* flag)
67 {
68   *flag=smpi_process_finalized();
69   return MPI_SUCCESS;
70 }
71
72 int PMPI_Get_version (int *version,int *subversion){
73   *version = MPI_VERSION;
74   *subversion= MPI_SUBVERSION;
75   return MPI_SUCCESS;
76 }
77
78 int PMPI_Get_library_version (char *version,int *len){
79   smpi_bench_end();
80   snprintf(version,MPI_MAX_LIBRARY_VERSION_STRING,"SMPI Version %d.%d. Copyright The Simgrid Team 2007-2015",
81            SIMGRID_VERSION_MAJOR, SIMGRID_VERSION_MINOR);
82   *len = strlen(version) > MPI_MAX_LIBRARY_VERSION_STRING ? MPI_MAX_LIBRARY_VERSION_STRING : strlen(version);
83   smpi_bench_begin();
84   return MPI_SUCCESS;
85 }
86
87 int PMPI_Init_thread(int *argc, char ***argv, int required, int *provided)
88 {
89   if (provided != nullptr) {
90     *provided = MPI_THREAD_SINGLE;
91   }
92   return MPI_Init(argc, argv);
93 }
94
95 int PMPI_Query_thread(int *provided)
96 {
97   if (provided == nullptr) {
98     return MPI_ERR_ARG;
99   } else {
100     *provided = MPI_THREAD_SINGLE;
101     return MPI_SUCCESS;
102   }
103 }
104
105 int PMPI_Is_thread_main(int *flag)
106 {
107   if (flag == nullptr) {
108     return MPI_ERR_ARG;
109   } else {
110     *flag = smpi_process_index() == 0;
111     return MPI_SUCCESS;
112   }
113 }
114
115 int PMPI_Abort(MPI_Comm comm, int errorcode)
116 {
117   smpi_bench_end();
118   smpi_process_destroy();
119   // FIXME: should kill all processes in comm instead
120   simcall_process_kill(SIMIX_process_self());
121   return MPI_SUCCESS;
122 }
123
124 double PMPI_Wtime()
125 {
126   return smpi_mpi_wtime();
127 }
128
129 extern double sg_maxmin_precision;
130 double PMPI_Wtick()
131 {
132   return sg_maxmin_precision;
133 }
134
135 int PMPI_Address(void *location, MPI_Aint * address)
136 {
137   if (address==nullptr) {
138     return MPI_ERR_ARG;
139   } else {
140     *address = reinterpret_cast<MPI_Aint>(location);
141     return MPI_SUCCESS;
142   }
143 }
144
145 int PMPI_Get_address(void *location, MPI_Aint * address)
146 {
147   return PMPI_Address(location, address);
148 }
149
150 int PMPI_Type_free(MPI_Datatype * datatype)
151 {
152   /* Free a predefined datatype is an error according to the standard, and should be checked for */
153   if (*datatype == MPI_DATATYPE_NULL) {
154     return MPI_ERR_ARG;
155   } else {
156     smpi_datatype_unuse(*datatype);
157     return MPI_SUCCESS;
158   }
159 }
160
161 int PMPI_Type_size(MPI_Datatype datatype, int *size)
162 {
163   if (datatype == MPI_DATATYPE_NULL) {
164     return MPI_ERR_TYPE;
165   } else if (size == nullptr) {
166     return MPI_ERR_ARG;
167   } else {
168     *size = static_cast<int>(smpi_datatype_size(datatype));
169     return MPI_SUCCESS;
170   }
171 }
172
173 int PMPI_Type_size_x(MPI_Datatype datatype, MPI_Count *size)
174 {
175   if (datatype == MPI_DATATYPE_NULL) {
176     return MPI_ERR_TYPE;
177   } else if (size == nullptr) {
178     return MPI_ERR_ARG;
179   } else {
180     *size = static_cast<MPI_Count>(smpi_datatype_size(datatype));
181     return MPI_SUCCESS;
182   }
183 }
184
185 int PMPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent)
186 {
187   if (datatype == MPI_DATATYPE_NULL) {
188     return MPI_ERR_TYPE;
189   } else if (lb == nullptr || extent == nullptr) {
190     return MPI_ERR_ARG;
191   } else {
192     return smpi_datatype_extent(datatype, lb, extent);
193   }
194 }
195
196 int PMPI_Type_get_true_extent(MPI_Datatype datatype, MPI_Aint * lb, MPI_Aint * extent)
197 {
198   return PMPI_Type_get_extent(datatype, lb, extent);
199 }
200
201 int PMPI_Type_extent(MPI_Datatype datatype, MPI_Aint * extent)
202 {
203   if (datatype == MPI_DATATYPE_NULL) {
204     return MPI_ERR_TYPE;
205   } else if (extent == nullptr) {
206     return MPI_ERR_ARG;
207   } else {
208     *extent = smpi_datatype_get_extent(datatype);
209     return MPI_SUCCESS;
210   }
211 }
212
213 int PMPI_Type_lb(MPI_Datatype datatype, MPI_Aint * disp)
214 {
215   if (datatype == MPI_DATATYPE_NULL) {
216     return MPI_ERR_TYPE;
217   } else if (disp == nullptr) {
218     return MPI_ERR_ARG;
219   } else {
220     *disp = smpi_datatype_lb(datatype);
221     return MPI_SUCCESS;
222   }
223 }
224
225 int PMPI_Type_ub(MPI_Datatype datatype, MPI_Aint * disp)
226 {
227   if (datatype == MPI_DATATYPE_NULL) {
228     return MPI_ERR_TYPE;
229   } else if (disp == nullptr) {
230     return MPI_ERR_ARG;
231   } else {
232     *disp = smpi_datatype_ub(datatype);
233     return MPI_SUCCESS;
234   }
235 }
236
237 int PMPI_Type_dup(MPI_Datatype datatype, MPI_Datatype *newtype){
238   if (datatype == MPI_DATATYPE_NULL) {
239     return MPI_ERR_TYPE;
240   } else {
241     return smpi_datatype_dup(datatype, newtype);
242   }
243 }
244
245 int PMPI_Op_create(MPI_User_function * function, int commute, MPI_Op * op)
246 {
247   if (function == nullptr || op == nullptr) {
248     return MPI_ERR_ARG;
249   } else {
250     *op = smpi_op_new(function, (commute!=0));
251     return MPI_SUCCESS;
252   }
253 }
254
255 int PMPI_Op_free(MPI_Op * op)
256 {
257   if (op == nullptr) {
258     return MPI_ERR_ARG;
259   } else if (*op == MPI_OP_NULL) {
260     return MPI_ERR_OP;
261   } else {
262     smpi_op_destroy(*op);
263     *op = MPI_OP_NULL;
264     return MPI_SUCCESS;
265   }
266 }
267
268 int PMPI_Group_free(MPI_Group * group)
269 {
270   if (group == nullptr) {
271     return MPI_ERR_ARG;
272   } else {
273     smpi_group_destroy(*group);
274     *group = MPI_GROUP_NULL;
275     return MPI_SUCCESS;
276   }
277 }
278
279 int PMPI_Group_size(MPI_Group group, int *size)
280 {
281   if (group == MPI_GROUP_NULL) {
282     return MPI_ERR_GROUP;
283   } else if (size == nullptr) {
284     return MPI_ERR_ARG;
285   } else {
286     *size = smpi_group_size(group);
287     return MPI_SUCCESS;
288   }
289 }
290
291 int PMPI_Group_rank(MPI_Group group, int *rank)
292 {
293   if (group == MPI_GROUP_NULL) {
294     return MPI_ERR_GROUP;
295   } else if (rank == nullptr) {
296     return MPI_ERR_ARG;
297   } else {
298     *rank = smpi_group_rank(group, smpi_process_index());
299     return MPI_SUCCESS;
300   }
301 }
302
303 int PMPI_Group_translate_ranks(MPI_Group group1, int n, int *ranks1, MPI_Group group2, int *ranks2)
304 {
305   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
306     return MPI_ERR_GROUP;
307   } else {
308     for (int i = 0; i < n; i++) {
309       if(ranks1[i]==MPI_PROC_NULL){
310         ranks2[i]=MPI_PROC_NULL;
311       }else{
312         int index = smpi_group_index(group1, ranks1[i]);
313         ranks2[i] = smpi_group_rank(group2, index);
314       }
315     }
316     return MPI_SUCCESS;
317   }
318 }
319
320 int PMPI_Group_compare(MPI_Group group1, MPI_Group group2, int *result)
321 {
322   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
323     return MPI_ERR_GROUP;
324   } else if (result == nullptr) {
325     return MPI_ERR_ARG;
326   } else {
327     *result = smpi_group_compare(group1, group2);
328     return MPI_SUCCESS;
329   }
330 }
331
332 int PMPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group * newgroup)
333 {
334
335   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
336     return MPI_ERR_GROUP;
337   } else if (newgroup == nullptr) {
338     return MPI_ERR_ARG;
339   } else {
340     int size  = smpi_group_size(group1);
341     int size2 = smpi_group_size(group2);
342     for (int i = 0; i < size2; i++) {
343       int proc2 = smpi_group_index(group2, i);
344       int proc1 = smpi_group_rank(group1, proc2);
345       if (proc1 == MPI_UNDEFINED) {
346         size++;
347       }
348     }
349     if (size == 0) {
350       *newgroup = MPI_GROUP_EMPTY;
351     } else {
352       *newgroup = smpi_group_new(size);
353       size2 = smpi_group_size(group1);
354       for (int i = 0; i < size2; i++) {
355         int proc1 = smpi_group_index(group1, i);
356         smpi_group_set_mapping(*newgroup, proc1, i);
357       }
358       for (int i = size2; i < size; i++) {
359         int proc2 = smpi_group_index(group2, i - size2);
360         smpi_group_set_mapping(*newgroup, proc2, i);
361       }
362     }
363     return MPI_SUCCESS;
364   }
365 }
366
367 int PMPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group * newgroup)
368 {
369
370   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
371     return MPI_ERR_GROUP;
372   } else if (newgroup == nullptr) {
373     return MPI_ERR_ARG;
374   } else {
375     int size = smpi_group_size(group2);
376     for (int i = 0; i < size; i++) {
377       int proc2 = smpi_group_index(group2, i);
378       int proc1 = smpi_group_rank(group1, proc2);
379       if (proc1 == MPI_UNDEFINED) {
380         size--;
381       }
382     }
383     if (size == 0) {
384       *newgroup = MPI_GROUP_EMPTY;
385     } else {
386       *newgroup = smpi_group_new(size);
387       int j=0;
388       for (int i = 0; i < smpi_group_size(group2); i++) {
389         int proc2 = smpi_group_index(group2, i);
390         int proc1 = smpi_group_rank(group1, proc2);
391         if (proc1 != MPI_UNDEFINED) {
392           smpi_group_set_mapping(*newgroup, proc2, j);
393           j++;
394         }
395       }
396     }
397     return MPI_SUCCESS;
398   }
399 }
400
401 int PMPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group * newgroup)
402 {
403   if (group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
404     return MPI_ERR_GROUP;
405   } else if (newgroup == nullptr) {
406     return MPI_ERR_ARG;
407   } else {
408     int size  = smpi_group_size(group1);
409     int size2 = size;
410     for (int i = 0; i < size2; i++) {
411       int proc1 = smpi_group_index(group1, i);
412       int proc2 = smpi_group_rank(group2, proc1);
413       if (proc2 != MPI_UNDEFINED) {
414         size--;
415       }
416     }
417     if (size == 0) {
418       *newgroup = MPI_GROUP_EMPTY;
419     } else {
420       *newgroup = smpi_group_new(size);
421       for (int i = 0; i < size2; i++) {
422         int proc1 = smpi_group_index(group1, i);
423         int proc2 = smpi_group_rank(group2, proc1);
424         if (proc2 == MPI_UNDEFINED) {
425           smpi_group_set_mapping(*newgroup, proc1, i);
426         }
427       }
428     }
429     return MPI_SUCCESS;
430   }
431 }
432
433 int PMPI_Group_incl(MPI_Group group, int n, int *ranks, MPI_Group * newgroup)
434 {
435   if (group == MPI_GROUP_NULL) {
436     return MPI_ERR_GROUP;
437   } else if (newgroup == nullptr) {
438     return MPI_ERR_ARG;
439   } else {
440     return smpi_group_incl(group, n, ranks, newgroup);
441   }
442 }
443
444 int PMPI_Group_excl(MPI_Group group, int n, int *ranks, MPI_Group * newgroup)
445 {
446   if (group == MPI_GROUP_NULL) {
447     return MPI_ERR_GROUP;
448   } else if (newgroup == nullptr) {
449     return MPI_ERR_ARG;
450   } else {
451     if (n == 0) {
452       *newgroup = group;
453       if (group != smpi_comm_group(MPI_COMM_WORLD)
454                 && group != smpi_comm_group(MPI_COMM_SELF) && group != MPI_GROUP_EMPTY)
455       smpi_group_use(group);
456     } else if (n == smpi_group_size(group)) {
457       *newgroup = MPI_GROUP_EMPTY;
458     } else {
459       int oldsize = smpi_group_size(group);
460       int newsize = oldsize - n;
461       *newgroup = smpi_group_new(newsize);
462
463       int* to_exclude=xbt_new0(int, smpi_group_size(group));
464       for (int i     = 0; i < oldsize; i++)
465         to_exclude[i]=0;
466       for (int i            = 0; i < n; i++)
467         to_exclude[ranks[i]]=1;
468
469       int j = 0;
470       for (int i = 0; i < oldsize; i++) {
471         if(to_exclude[i]==0){
472           int index = smpi_group_index(group, i);
473           smpi_group_set_mapping(*newgroup, index, j);
474           j++;
475         }
476       }
477
478       xbt_free(to_exclude);
479     }
480     return MPI_SUCCESS;
481   }
482 }
483
484 int PMPI_Group_range_incl(MPI_Group group, int n, int ranges[][3], MPI_Group * newgroup)
485 {
486   if (group == MPI_GROUP_NULL) {
487     return MPI_ERR_GROUP;
488   } else if (newgroup == nullptr) {
489     return MPI_ERR_ARG;
490   } else {
491     if (n == 0) {
492       *newgroup = MPI_GROUP_EMPTY;
493     } else {
494       int size = 0;
495       for (int i = 0; i < n; i++) {
496         for (int rank = ranges[i][0];                    /* First */
497              rank >= 0 && rank < smpi_group_size(group); /* Last */
498              ) {
499           size++;
500           if(rank == ranges[i][1]){/*already last ?*/
501             break;
502           }
503           rank += ranges[i][2]; /* Stride */
504           if (ranges[i][0] < ranges[i][1]) {
505             if (rank > ranges[i][1])
506               break;
507           } else {
508             if (rank < ranges[i][1])
509               break;
510           }
511         }
512       }
513
514       *newgroup = smpi_group_new(size);
515       int j     = 0;
516       for (int i = 0; i < n; i++) {
517         for (int rank = ranges[i][0];                    /* First */
518              rank >= 0 && rank < smpi_group_size(group); /* Last */
519              ) {
520           int index = smpi_group_index(group, rank);
521           smpi_group_set_mapping(*newgroup, index, j);
522           j++;
523           if(rank == ranges[i][1]){/*already last ?*/
524             break;
525           }
526           rank += ranges[i][2]; /* Stride */
527           if (ranges[i][0] < ranges[i][1]) {
528             if (rank > ranges[i][1])
529               break;
530           } else {
531             if (rank < ranges[i][1])
532               break;
533           }
534         }
535       }
536     }
537     return MPI_SUCCESS;
538   }
539 }
540
541 int PMPI_Group_range_excl(MPI_Group group, int n, int ranges[][3], MPI_Group * newgroup)
542 {
543   if (group == MPI_GROUP_NULL) {
544     return MPI_ERR_GROUP;
545   } else if (newgroup == nullptr) {
546     return MPI_ERR_ARG;
547   } else {
548     if (n == 0) {
549       *newgroup = group;
550       if (group != smpi_comm_group(MPI_COMM_WORLD) && group != smpi_comm_group(MPI_COMM_SELF) &&
551           group != MPI_GROUP_EMPTY)
552         smpi_group_use(group);
553     } else {
554       int size = smpi_group_size(group);
555       for (int i = 0; i < n; i++) {
556         for (int rank = ranges[i][0];                    /* First */
557              rank >= 0 && rank < smpi_group_size(group); /* Last */
558              ) {
559           size--;
560           if(rank == ranges[i][1]){/*already last ?*/
561             break;
562           }
563           rank += ranges[i][2]; /* Stride */
564           if (ranges[i][0] < ranges[i][1]) {
565             if (rank > ranges[i][1])
566               break;
567           } else {
568             if (rank < ranges[i][1])
569               break;
570           }
571         }
572       }
573       if (size == 0) {
574         *newgroup = MPI_GROUP_EMPTY;
575       } else {
576         *newgroup = smpi_group_new(size);
577         int newrank = 0;
578         int oldrank = 0;
579         while (newrank < size) {
580           int add = 1;
581           for (int i = 0; i < n; i++) {
582             for (int rank = ranges[i][0]; rank >= 0 && rank < smpi_group_size(group);) {
583               if(rank==oldrank){
584                 add = 0;
585                 break;
586               }
587               if(rank == ranges[i][1]){/*already last ?*/
588                 break;
589               }
590               rank += ranges[i][2]; /* Stride */
591               if (ranges[i][0]<ranges[i][1]){
592                 if (rank > ranges[i][1])
593                   break;
594               }else{
595                 if (rank < ranges[i][1])
596                   break;
597               }
598             }
599           }
600           if(add==1){
601             int index = smpi_group_index(group, oldrank);
602             smpi_group_set_mapping(*newgroup, index, newrank);
603             newrank++;
604           }
605           oldrank++;
606         }
607       }
608     }
609     return MPI_SUCCESS;
610   }
611 }
612
613 int PMPI_Comm_rank(MPI_Comm comm, int *rank)
614 {
615   if (comm == MPI_COMM_NULL) {
616     return MPI_ERR_COMM;
617   } else if (rank == nullptr) {
618     return MPI_ERR_ARG;
619   } else {
620     *rank = smpi_comm_rank(comm);
621     return MPI_SUCCESS;
622   }
623 }
624
625 int PMPI_Comm_size(MPI_Comm comm, int *size)
626 {
627   if (comm == MPI_COMM_NULL) {
628     return MPI_ERR_COMM;
629   } else if (size == nullptr) {
630     return MPI_ERR_ARG;
631   } else {
632     *size = smpi_comm_size(comm);
633     return MPI_SUCCESS;
634   }
635 }
636
637 int PMPI_Comm_get_name (MPI_Comm comm, char* name, int* len)
638 {
639   if (comm == MPI_COMM_NULL)  {
640     return MPI_ERR_COMM;
641   } else if (name == nullptr || len == nullptr)  {
642     return MPI_ERR_ARG;
643   } else {
644     smpi_comm_get_name(comm, name, len);
645     return MPI_SUCCESS;
646   }
647 }
648
649 int PMPI_Comm_group(MPI_Comm comm, MPI_Group * group)
650 {
651   if (comm == MPI_COMM_NULL) {
652     return MPI_ERR_COMM;
653   } else if (group == nullptr) {
654     return MPI_ERR_ARG;
655   } else {
656     *group = smpi_comm_group(comm);
657     if (*group != smpi_comm_group(MPI_COMM_WORLD) && *group != MPI_GROUP_NULL && *group != MPI_GROUP_EMPTY)
658       smpi_group_use(*group);
659     return MPI_SUCCESS;
660   }
661 }
662
663 int PMPI_Comm_compare(MPI_Comm comm1, MPI_Comm comm2, int *result)
664 {
665   if (comm1 == MPI_COMM_NULL || comm2 == MPI_COMM_NULL) {
666     return MPI_ERR_COMM;
667   } else if (result == nullptr) {
668     return MPI_ERR_ARG;
669   } else {
670     if (comm1 == comm2) {       /* Same communicators means same groups */
671       *result = MPI_IDENT;
672     } else {
673       *result = smpi_group_compare(smpi_comm_group(comm1), smpi_comm_group(comm2));
674       if (*result == MPI_IDENT) {
675         *result = MPI_CONGRUENT;
676       }
677     }
678     return MPI_SUCCESS;
679   }
680 }
681
682 int PMPI_Comm_dup(MPI_Comm comm, MPI_Comm * newcomm)
683 {
684   if (comm == MPI_COMM_NULL) {
685     return MPI_ERR_COMM;
686   } else if (newcomm == nullptr) {
687     return MPI_ERR_ARG;
688   } else {
689     return smpi_comm_dup(comm, newcomm);
690   }
691 }
692
693 int PMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm * newcomm)
694 {
695   if (comm == MPI_COMM_NULL) {
696     return MPI_ERR_COMM;
697   } else if (group == MPI_GROUP_NULL) {
698     return MPI_ERR_GROUP;
699   } else if (newcomm == nullptr) {
700     return MPI_ERR_ARG;
701   } else if(smpi_group_rank(group,smpi_process_index())==MPI_UNDEFINED){
702     *newcomm= MPI_COMM_NULL;
703     return MPI_SUCCESS;
704   }else{
705     smpi_group_use(group);
706     *newcomm = smpi_comm_new(group, nullptr);
707     return MPI_SUCCESS;
708   }
709 }
710
711 int PMPI_Comm_free(MPI_Comm * comm)
712 {
713   if (comm == nullptr) {
714     return MPI_ERR_ARG;
715   } else if (*comm == MPI_COMM_NULL) {
716     return MPI_ERR_COMM;
717   } else {
718     smpi_comm_destroy(*comm);
719     *comm = MPI_COMM_NULL;
720     return MPI_SUCCESS;
721   }
722 }
723
724 int PMPI_Comm_disconnect(MPI_Comm * comm)
725 {
726   /* TODO: wait until all communication in comm are done */
727   if (comm == nullptr) {
728     return MPI_ERR_ARG;
729   } else if (*comm == MPI_COMM_NULL) {
730     return MPI_ERR_COMM;
731   } else {
732     smpi_comm_destroy(*comm);
733     *comm = MPI_COMM_NULL;
734     return MPI_SUCCESS;
735   }
736 }
737
738 int PMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* comm_out)
739 {
740   int retval = 0;
741   smpi_bench_end();
742
743   if (comm_out == nullptr) {
744     retval = MPI_ERR_ARG;
745   } else if (comm == MPI_COMM_NULL) {
746     retval = MPI_ERR_COMM;
747   } else {
748     *comm_out = smpi_comm_split(comm, color, key);
749     retval = MPI_SUCCESS;
750   }
751   smpi_bench_begin();
752
753   return retval;
754 }
755
756 int PMPI_Comm_create_group(MPI_Comm comm, MPI_Group group, int, MPI_Comm* comm_out)
757 {
758   int retval = 0;
759   smpi_bench_end();
760
761   if (comm_out == nullptr) {
762     retval = MPI_ERR_ARG;
763   } else if (comm == MPI_COMM_NULL) {
764     retval = MPI_ERR_COMM;
765   } else {
766     retval = MPI_Comm_create(comm, group, comm_out);
767   }
768   smpi_bench_begin();
769
770   return retval;
771 }
772
773 int PMPI_Send_init(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request * request)
774 {
775   int retval = 0;
776
777   smpi_bench_end();
778   if (request == nullptr) {
779       retval = MPI_ERR_ARG;
780   } else if (comm == MPI_COMM_NULL) {
781       retval = MPI_ERR_COMM;
782   } else if (!is_datatype_valid(datatype)) {
783       retval = MPI_ERR_TYPE;
784   } else if (dst == MPI_PROC_NULL) {
785       retval = MPI_SUCCESS;
786   } else {
787       *request = smpi_mpi_send_init(buf, count, datatype, dst, tag, comm);
788       retval = MPI_SUCCESS;
789   }
790   smpi_bench_begin();
791   if (retval != MPI_SUCCESS && request != nullptr)
792     *request = MPI_REQUEST_NULL;
793   return retval;
794 }
795
796 int PMPI_Recv_init(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Request * request)
797 {
798   int retval = 0;
799
800   smpi_bench_end();
801   if (request == nullptr) {
802     retval = MPI_ERR_ARG;
803   } else if (comm == MPI_COMM_NULL) {
804     retval = MPI_ERR_COMM;
805   } else if (!is_datatype_valid(datatype)) {
806       retval = MPI_ERR_TYPE;
807   } else if (src == MPI_PROC_NULL) {
808     retval = MPI_SUCCESS;
809   } else {
810     *request = smpi_mpi_recv_init(buf, count, datatype, src, tag, comm);
811     retval = MPI_SUCCESS;
812   }
813   smpi_bench_begin();
814   if (retval != MPI_SUCCESS && request != nullptr)
815     *request = MPI_REQUEST_NULL;
816   return retval;
817 }
818
819 int PMPI_Ssend_init(void* buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request* request)
820 {
821   int retval = 0;
822
823   smpi_bench_end();
824   if (request == nullptr) {
825     retval = MPI_ERR_ARG;
826   } else if (comm == MPI_COMM_NULL) {
827     retval = MPI_ERR_COMM;
828   } else if (!is_datatype_valid(datatype)) {
829       retval = MPI_ERR_TYPE;
830   } else if (dst == MPI_PROC_NULL) {
831     retval = MPI_SUCCESS;
832   } else {
833     *request = smpi_mpi_ssend_init(buf, count, datatype, dst, tag, comm);
834     retval = MPI_SUCCESS;
835   }
836   smpi_bench_begin();
837   if (retval != MPI_SUCCESS && request != nullptr)
838     *request = MPI_REQUEST_NULL;
839   return retval;
840 }
841
842 int PMPI_Start(MPI_Request * request)
843 {
844   int retval = 0;
845
846   smpi_bench_end();
847   if (request == nullptr || *request == MPI_REQUEST_NULL) {
848     retval = MPI_ERR_REQUEST;
849   } else {
850     smpi_mpi_start(*request);
851     retval = MPI_SUCCESS;
852   }
853   smpi_bench_begin();
854   return retval;
855 }
856
857 int PMPI_Startall(int count, MPI_Request * requests)
858 {
859   int retval;
860   smpi_bench_end();
861   if (requests == nullptr) {
862     retval = MPI_ERR_ARG;
863   } else {
864     retval = MPI_SUCCESS;
865     for (int i = 0; i < count; i++) {
866       if(requests[i] == MPI_REQUEST_NULL) {
867         retval = MPI_ERR_REQUEST;
868       }
869     }
870     if(retval != MPI_ERR_REQUEST) {
871       smpi_mpi_startall(count, requests);
872     }
873   }
874   smpi_bench_begin();
875   return retval;
876 }
877
878 int PMPI_Request_free(MPI_Request * request)
879 {
880   int retval = 0;
881
882   smpi_bench_end();
883   if (*request == MPI_REQUEST_NULL) {
884     retval = MPI_ERR_ARG;
885   } else {
886     smpi_mpi_request_free(request);
887     retval = MPI_SUCCESS;
888   }
889   smpi_bench_begin();
890   return retval;
891 }
892
893 int PMPI_Irecv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Request * request)
894 {
895   int retval = 0;
896
897   smpi_bench_end();
898
899   if (request == nullptr) {
900     retval = MPI_ERR_ARG;
901   } else if (comm == MPI_COMM_NULL) {
902     retval = MPI_ERR_COMM;
903   } else if (src == MPI_PROC_NULL) {
904     *request = MPI_REQUEST_NULL;
905     retval = MPI_SUCCESS;
906   } else if (src!=MPI_ANY_SOURCE && (src >= smpi_group_size(smpi_comm_group(comm)) || src <0)){
907     retval = MPI_ERR_RANK;
908   } else if ((count < 0) || (buf==nullptr && count > 0)) {
909     retval = MPI_ERR_COUNT;
910   } else if (!is_datatype_valid(datatype)) {
911       retval = MPI_ERR_TYPE;
912   } else if(tag<0 && tag !=  MPI_ANY_TAG){
913     retval = MPI_ERR_TAG;
914   } else {
915
916     int rank = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
917     int src_traced = smpi_group_index(smpi_comm_group(comm), src);
918
919     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
920     extra->type = TRACING_IRECV;
921     extra->src = src_traced;
922     extra->dst = rank;
923     int known=0;
924     extra->datatype1 = encode_datatype(datatype, &known);
925     int dt_size_send = 1;
926     if(known==0)
927       dt_size_send = smpi_datatype_size(datatype);
928     extra->send_size = count*dt_size_send;
929     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, extra);
930
931     *request = smpi_mpi_irecv(buf, count, datatype, src, tag, comm);
932     retval = MPI_SUCCESS;
933
934     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
935     (*request)->recv = 1;
936   }
937
938   smpi_bench_begin();
939   if (retval != MPI_SUCCESS && request != nullptr)
940     *request = MPI_REQUEST_NULL;
941   return retval;
942 }
943
944
945 int PMPI_Isend(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request * request)
946 {
947   int retval = 0;
948
949   smpi_bench_end();
950   if (request == nullptr) {
951     retval = MPI_ERR_ARG;
952   } else if (comm == MPI_COMM_NULL) {
953     retval = MPI_ERR_COMM;
954   } else if (dst == MPI_PROC_NULL) {
955     *request = MPI_REQUEST_NULL;
956     retval = MPI_SUCCESS;
957   } else if (dst >= smpi_group_size(smpi_comm_group(comm)) || dst <0){
958     retval = MPI_ERR_RANK;
959   } else if ((count < 0) || (buf==nullptr && count > 0)) {
960     retval = MPI_ERR_COUNT;
961   } else if (!is_datatype_valid(datatype)) {
962       retval = MPI_ERR_TYPE;
963   } else if(tag<0 && tag !=  MPI_ANY_TAG){
964     retval = MPI_ERR_TAG;
965   } else {
966     int rank = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
967     int dst_traced = smpi_group_index(smpi_comm_group(comm), dst);
968     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
969     extra->type = TRACING_ISEND;
970     extra->src = rank;
971     extra->dst = dst_traced;
972     int known=0;
973     extra->datatype1 = encode_datatype(datatype, &known);
974     int dt_size_send = 1;
975     if(known==0)
976       dt_size_send = smpi_datatype_size(datatype);
977     extra->send_size = count*dt_size_send;
978     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, extra);
979     TRACE_smpi_send(rank, rank, dst_traced, tag, count*smpi_datatype_size(datatype));
980
981     *request = smpi_mpi_isend(buf, count, datatype, dst, tag, comm);
982     retval = MPI_SUCCESS;
983
984     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
985     (*request)->send = 1;
986   }
987
988   smpi_bench_begin();
989   if (retval != MPI_SUCCESS && request!=nullptr)
990     *request = MPI_REQUEST_NULL;
991   return retval;
992 }
993
994 int PMPI_Issend(void* buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request* request)
995 {
996   int retval = 0;
997
998   smpi_bench_end();
999   if (request == nullptr) {
1000     retval = MPI_ERR_ARG;
1001   } else if (comm == MPI_COMM_NULL) {
1002     retval = MPI_ERR_COMM;
1003   } else if (dst == MPI_PROC_NULL) {
1004     *request = MPI_REQUEST_NULL;
1005     retval = MPI_SUCCESS;
1006   } else if (dst >= smpi_group_size(smpi_comm_group(comm)) || dst <0){
1007     retval = MPI_ERR_RANK;
1008   } else if ((count < 0)|| (buf==nullptr && count > 0)) {
1009     retval = MPI_ERR_COUNT;
1010   } else if (!is_datatype_valid(datatype)) {
1011       retval = MPI_ERR_TYPE;
1012   } else if(tag<0 && tag !=  MPI_ANY_TAG){
1013     retval = MPI_ERR_TAG;
1014   } else {
1015     int rank = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1016     int dst_traced = smpi_group_index(smpi_comm_group(comm), dst);
1017     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1018     extra->type = TRACING_ISSEND;
1019     extra->src = rank;
1020     extra->dst = dst_traced;
1021     int known=0;
1022     extra->datatype1 = encode_datatype(datatype, &known);
1023     int dt_size_send = 1;
1024     if(known==0)
1025       dt_size_send = smpi_datatype_size(datatype);
1026     extra->send_size = count*dt_size_send;
1027     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, extra);
1028     TRACE_smpi_send(rank, rank, dst_traced, tag, count*smpi_datatype_size(datatype));
1029
1030     *request = smpi_mpi_issend(buf, count, datatype, dst, tag, comm);
1031     retval = MPI_SUCCESS;
1032
1033     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
1034     (*request)->send = 1;
1035   }
1036
1037   smpi_bench_begin();
1038   if (retval != MPI_SUCCESS && request!=nullptr)
1039     *request = MPI_REQUEST_NULL;
1040   return retval;
1041 }
1042
1043 int PMPI_Recv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Status * status)
1044 {
1045   int retval = 0;
1046
1047   smpi_bench_end();
1048   if (comm == MPI_COMM_NULL) {
1049     retval = MPI_ERR_COMM;
1050   } else if (src == MPI_PROC_NULL) {
1051     smpi_empty_status(status);
1052     status->MPI_SOURCE = MPI_PROC_NULL;
1053     retval = MPI_SUCCESS;
1054   } else if (src!=MPI_ANY_SOURCE && (src >= smpi_group_size(smpi_comm_group(comm)) || src <0)){
1055     retval = MPI_ERR_RANK;
1056   } else if ((count < 0) || (buf==nullptr && count > 0)) {
1057     retval = MPI_ERR_COUNT;
1058   } else if (!is_datatype_valid(datatype)) {
1059       retval = MPI_ERR_TYPE;
1060   } else if(tag<0 && tag !=  MPI_ANY_TAG){
1061     retval = MPI_ERR_TAG;
1062   } else {
1063     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1064     int src_traced         = smpi_group_index(smpi_comm_group(comm), src);
1065     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1066     extra->type            = TRACING_RECV;
1067     extra->src             = src_traced;
1068     extra->dst             = rank;
1069     int known              = 0;
1070     extra->datatype1       = encode_datatype(datatype, &known);
1071     int dt_size_send       = 1;
1072     if (known == 0)
1073       dt_size_send   = smpi_datatype_size(datatype);
1074     extra->send_size = count * dt_size_send;
1075     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, extra);
1076
1077     smpi_mpi_recv(buf, count, datatype, src, tag, comm, status);
1078     retval = MPI_SUCCESS;
1079
1080     // the src may not have been known at the beginning of the recv (MPI_ANY_SOURCE)
1081     if (status != MPI_STATUS_IGNORE) {
1082       src_traced = smpi_group_index(smpi_comm_group(comm), status->MPI_SOURCE);
1083       if (!TRACE_smpi_view_internals()) {
1084         TRACE_smpi_recv(rank, src_traced, rank, tag);
1085       }
1086     }
1087     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
1088   }
1089
1090   smpi_bench_begin();
1091   return retval;
1092 }
1093
1094 int PMPI_Send(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm)
1095 {
1096   int retval = 0;
1097
1098   smpi_bench_end();
1099
1100   if (comm == MPI_COMM_NULL) {
1101     retval = MPI_ERR_COMM;
1102   } else if (dst == MPI_PROC_NULL) {
1103     retval = MPI_SUCCESS;
1104   } else if (dst >= smpi_group_size(smpi_comm_group(comm)) || dst <0){
1105     retval = MPI_ERR_RANK;
1106   } else if ((count < 0) || (buf == nullptr && count > 0)) {
1107     retval = MPI_ERR_COUNT;
1108   } else if (!is_datatype_valid(datatype)) {
1109     retval = MPI_ERR_TYPE;
1110   } else if(tag < 0 && tag !=  MPI_ANY_TAG){
1111     retval = MPI_ERR_TAG;
1112   } else {
1113     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1114     int dst_traced         = smpi_group_index(smpi_comm_group(comm), dst);
1115     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1116     extra->type            = TRACING_SEND;
1117     extra->src             = rank;
1118     extra->dst             = dst_traced;
1119     int known              = 0;
1120     extra->datatype1       = encode_datatype(datatype, &known);
1121     int dt_size_send       = 1;
1122     if (known == 0) {
1123       dt_size_send = smpi_datatype_size(datatype);
1124     }
1125     extra->send_size = count*dt_size_send;
1126     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, extra);
1127     if (!TRACE_smpi_view_internals()) {
1128       TRACE_smpi_send(rank, rank, dst_traced, tag,count*smpi_datatype_size(datatype));
1129     }
1130
1131     smpi_mpi_send(buf, count, datatype, dst, tag, comm);
1132     retval = MPI_SUCCESS;
1133
1134     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
1135   }
1136
1137   smpi_bench_begin();
1138   return retval;
1139 }
1140
1141 int PMPI_Ssend(void* buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm) {
1142   int retval = 0;
1143
1144   smpi_bench_end();
1145
1146   if (comm == MPI_COMM_NULL) {
1147     retval = MPI_ERR_COMM;
1148   } else if (dst == MPI_PROC_NULL) {
1149     retval = MPI_SUCCESS;
1150   } else if (dst >= smpi_group_size(smpi_comm_group(comm)) || dst <0){
1151     retval = MPI_ERR_RANK;
1152   } else if ((count < 0) || (buf==nullptr && count > 0)) {
1153     retval = MPI_ERR_COUNT;
1154   } else if (!is_datatype_valid(datatype)){
1155     retval = MPI_ERR_TYPE;
1156   } else if(tag<0 && tag !=  MPI_ANY_TAG){
1157     retval = MPI_ERR_TAG;
1158   } else {
1159     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1160     int dst_traced         = smpi_group_index(smpi_comm_group(comm), dst);
1161     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1162     extra->type            = TRACING_SSEND;
1163     extra->src             = rank;
1164     extra->dst             = dst_traced;
1165     int known              = 0;
1166     extra->datatype1       = encode_datatype(datatype, &known);
1167     int dt_size_send       = 1;
1168     if(known == 0) {
1169       dt_size_send = smpi_datatype_size(datatype);
1170     }
1171     extra->send_size = count*dt_size_send;
1172     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, extra);
1173     TRACE_smpi_send(rank, rank, dst_traced, tag,count*smpi_datatype_size(datatype));
1174   
1175     smpi_mpi_ssend(buf, count, datatype, dst, tag, comm);
1176     retval = MPI_SUCCESS;
1177   
1178     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
1179   }
1180
1181   smpi_bench_begin();
1182   return retval;
1183 }
1184
1185 int PMPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype, int dst, int sendtag, void *recvbuf,
1186                  int recvcount, MPI_Datatype recvtype, int src, int recvtag, MPI_Comm comm, MPI_Status * status)
1187 {
1188   int retval = 0;
1189
1190   smpi_bench_end();
1191
1192   if (comm == MPI_COMM_NULL) {
1193     retval = MPI_ERR_COMM;
1194   } else if (!is_datatype_valid(sendtype) || !is_datatype_valid(recvtype)) {
1195     retval = MPI_ERR_TYPE;
1196   } else if (src == MPI_PROC_NULL || dst == MPI_PROC_NULL) {
1197     smpi_empty_status(status);
1198     status->MPI_SOURCE = MPI_PROC_NULL;
1199     retval             = MPI_SUCCESS;
1200   }else if (dst >= smpi_group_size(smpi_comm_group(comm)) || dst <0 ||
1201       (src!=MPI_ANY_SOURCE && (src >= smpi_group_size(smpi_comm_group(comm)) || src <0))){
1202     retval = MPI_ERR_RANK;
1203   } else if ((sendcount < 0 || recvcount<0) || 
1204       (sendbuf==nullptr && sendcount > 0) || (recvbuf==nullptr && recvcount>0)) {
1205     retval = MPI_ERR_COUNT;
1206   } else if((sendtag<0 && sendtag !=  MPI_ANY_TAG)||(recvtag<0 && recvtag != MPI_ANY_TAG)){
1207     retval = MPI_ERR_TAG;
1208   } else {
1209
1210   int rank = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1211   int dst_traced = smpi_group_index(smpi_comm_group(comm), dst);
1212   int src_traced = smpi_group_index(smpi_comm_group(comm), src);
1213   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1214   extra->type = TRACING_SENDRECV;
1215   extra->src = src_traced;
1216   extra->dst = dst_traced;
1217   int known=0;
1218   extra->datatype1 = encode_datatype(sendtype, &known);
1219   int dt_size_send = 1;
1220   if(known==0)
1221     dt_size_send = smpi_datatype_size(sendtype);
1222   extra->send_size = sendcount*dt_size_send;
1223   extra->datatype2 = encode_datatype(recvtype, &known);
1224   int dt_size_recv = 1;
1225   if(known==0)
1226     dt_size_recv = smpi_datatype_size(recvtype);
1227   extra->recv_size = recvcount*dt_size_recv;
1228
1229   TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__, extra);
1230   TRACE_smpi_send(rank, rank, dst_traced, sendtag,sendcount*smpi_datatype_size(sendtype));
1231
1232   smpi_mpi_sendrecv(sendbuf, sendcount, sendtype, dst, sendtag, recvbuf, recvcount, recvtype, src, recvtag, comm,
1233                     status);
1234   retval = MPI_SUCCESS;
1235
1236   TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
1237   TRACE_smpi_recv(rank, src_traced, rank, recvtag);
1238   }
1239
1240   smpi_bench_begin();
1241   return retval;
1242 }
1243
1244 int PMPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype, int dst, int sendtag, int src, int recvtag,
1245                           MPI_Comm comm, MPI_Status* status)
1246 {
1247   int retval = 0;
1248   if (!is_datatype_valid(datatype)) {
1249     return MPI_ERR_TYPE;
1250   } else if (count < 0) {
1251     return MPI_ERR_COUNT;
1252   } else {
1253     int size = smpi_datatype_get_extent(datatype) * count;
1254     void* recvbuf = xbt_new0(char, size);
1255     retval = MPI_Sendrecv(buf, count, datatype, dst, sendtag, recvbuf, count, datatype, src, recvtag, comm, status);
1256     if(retval==MPI_SUCCESS){
1257         smpi_datatype_copy(recvbuf, count, datatype, buf, count, datatype);
1258     }
1259     xbt_free(recvbuf);
1260
1261   }
1262   return retval;
1263 }
1264
1265 int PMPI_Test(MPI_Request * request, int *flag, MPI_Status * status)
1266 {
1267   int retval = 0;
1268   smpi_bench_end();
1269   if (request == nullptr || flag == nullptr) {
1270     retval = MPI_ERR_ARG;
1271   } else if (*request == MPI_REQUEST_NULL) {
1272     *flag= true;
1273     smpi_empty_status(status);
1274     retval = MPI_SUCCESS;
1275   } else {
1276     int rank = ((*request)->comm != MPI_COMM_NULL) ? smpi_process_index() : -1;
1277
1278     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1279     extra->type = TRACING_TEST;
1280     TRACE_smpi_testing_in(rank, extra);
1281
1282     *flag = smpi_mpi_test(request, status);
1283
1284     TRACE_smpi_testing_out(rank);
1285     retval = MPI_SUCCESS;
1286   }
1287   smpi_bench_begin();
1288   return retval;
1289 }
1290
1291 int PMPI_Testany(int count, MPI_Request requests[], int *index, int *flag, MPI_Status * status)
1292 {
1293   int retval = 0;
1294
1295   smpi_bench_end();
1296   if (index == nullptr || flag == nullptr) {
1297     retval = MPI_ERR_ARG;
1298   } else {
1299     *flag = smpi_mpi_testany(count, requests, index, status);
1300     retval = MPI_SUCCESS;
1301   }
1302   smpi_bench_begin();
1303   return retval;
1304 }
1305
1306 int PMPI_Testall(int count, MPI_Request* requests, int* flag, MPI_Status* statuses)
1307 {
1308   int retval = 0;
1309
1310   smpi_bench_end();
1311   if (flag == nullptr) {
1312     retval = MPI_ERR_ARG;
1313   } else {
1314     *flag = smpi_mpi_testall(count, requests, statuses);
1315     retval = MPI_SUCCESS;
1316   }
1317   smpi_bench_begin();
1318   return retval;
1319 }
1320
1321 int PMPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status* status) {
1322   int retval = 0;
1323   smpi_bench_end();
1324
1325   if (status == nullptr) {
1326     retval = MPI_ERR_ARG;
1327   } else if (comm == MPI_COMM_NULL) {
1328     retval = MPI_ERR_COMM;
1329   } else if (source == MPI_PROC_NULL) {
1330     smpi_empty_status(status);
1331     status->MPI_SOURCE = MPI_PROC_NULL;
1332     retval = MPI_SUCCESS;
1333   } else {
1334     smpi_mpi_probe(source, tag, comm, status);
1335     retval = MPI_SUCCESS;
1336   }
1337   smpi_bench_begin();
1338   return retval;
1339 }
1340
1341 int PMPI_Iprobe(int source, int tag, MPI_Comm comm, int* flag, MPI_Status* status) {
1342   int retval = 0;
1343   smpi_bench_end();
1344
1345   if ((flag == nullptr) || (status == nullptr)) {
1346     retval = MPI_ERR_ARG;
1347   } else if (comm == MPI_COMM_NULL) {
1348     retval = MPI_ERR_COMM;
1349   } else if (source == MPI_PROC_NULL) {
1350     *flag=true;
1351     smpi_empty_status(status);
1352     status->MPI_SOURCE = MPI_PROC_NULL;
1353     retval = MPI_SUCCESS;
1354   } else {
1355     smpi_mpi_iprobe(source, tag, comm, flag, status);
1356     retval = MPI_SUCCESS;
1357   }
1358   smpi_bench_begin();
1359   return retval;
1360 }
1361
1362 int PMPI_Wait(MPI_Request * request, MPI_Status * status)
1363 {
1364   int retval = 0;
1365
1366   smpi_bench_end();
1367
1368   smpi_empty_status(status);
1369
1370   if (request == nullptr) {
1371     retval = MPI_ERR_ARG;
1372   } else if (*request == MPI_REQUEST_NULL) {
1373     retval = MPI_SUCCESS;
1374   } else {
1375
1376     int rank = (request!=nullptr && (*request)->comm != MPI_COMM_NULL) ? smpi_process_index() : -1;
1377
1378     int src_traced = (*request)->src;
1379     int dst_traced = (*request)->dst;
1380     int tag_traced= (*request)->tag;
1381     MPI_Comm comm = (*request)->comm;
1382     int is_wait_for_receive = (*request)->recv;
1383     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1384     extra->type = TRACING_WAIT;
1385     TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__, extra);
1386
1387     smpi_mpi_wait(request, status);
1388     retval = MPI_SUCCESS;
1389
1390     //the src may not have been known at the beginning of the recv (MPI_ANY_SOURCE)
1391     TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__);
1392     if (is_wait_for_receive) {
1393       if(src_traced==MPI_ANY_SOURCE)
1394         src_traced = (status!=MPI_STATUS_IGNORE) ?
1395           smpi_group_rank(smpi_comm_group(comm), status->MPI_SOURCE) :
1396           src_traced;
1397       TRACE_smpi_recv(rank, src_traced, dst_traced, tag_traced);
1398     }
1399   }
1400
1401   smpi_bench_begin();
1402   return retval;
1403 }
1404
1405 int PMPI_Waitany(int count, MPI_Request requests[], int *index, MPI_Status * status)
1406 {
1407   if (index == nullptr)
1408     return MPI_ERR_ARG;
1409
1410   smpi_bench_end();
1411   //save requests information for tracing
1412   typedef struct {
1413     int src;
1414     int dst;
1415     int recv;
1416     int tag;
1417     MPI_Comm comm;
1418   } savedvalstype;
1419   savedvalstype* savedvals=nullptr;
1420   if(count>0){
1421     savedvals = xbt_new0(savedvalstype, count);
1422   }
1423   for (int i = 0; i < count; i++) {
1424     MPI_Request req = requests[i];      //already received requests are no longer valid
1425     if (req) {
1426       savedvals[i]=(savedvalstype){req->src, req->dst, req->recv, req->tag, req->comm};
1427     }
1428   }
1429   int rank_traced = smpi_process_index();
1430   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1431   extra->type = TRACING_WAITANY;
1432   extra->send_size=count;
1433   TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__,extra);
1434
1435   *index = smpi_mpi_waitany(count, requests, status);
1436
1437   if(*index!=MPI_UNDEFINED){
1438     int src_traced = savedvals[*index].src;
1439     //the src may not have been known at the beginning of the recv (MPI_ANY_SOURCE)
1440     int dst_traced = savedvals[*index].dst;
1441     int is_wait_for_receive = savedvals[*index].recv;
1442     if (is_wait_for_receive) {
1443       if(savedvals[*index].src==MPI_ANY_SOURCE)
1444         src_traced = (status != MPI_STATUSES_IGNORE)
1445                          ? smpi_group_rank(smpi_comm_group(savedvals[*index].comm), status->MPI_SOURCE)
1446                          : savedvals[*index].src;
1447       TRACE_smpi_recv(rank_traced, src_traced, dst_traced, savedvals[*index].tag);
1448     }
1449     TRACE_smpi_ptp_out(rank_traced, src_traced, dst_traced, __FUNCTION__);
1450   }
1451   xbt_free(savedvals);
1452
1453   smpi_bench_begin();
1454   return MPI_SUCCESS;
1455 }
1456
1457 int PMPI_Waitall(int count, MPI_Request requests[], MPI_Status status[])
1458 {
1459   smpi_bench_end();
1460   //save information from requests
1461   typedef struct {
1462     int src;
1463     int dst;
1464     int recv;
1465     int tag;
1466     int valid;
1467     MPI_Comm comm;
1468   } savedvalstype;
1469   savedvalstype* savedvals=xbt_new0(savedvalstype, count);
1470
1471   for (int i = 0; i < count; i++) {
1472     MPI_Request req = requests[i];
1473     if(req!=MPI_REQUEST_NULL){
1474       savedvals[i]=(savedvalstype){req->src, req->dst, req->recv, req->tag, 1, req->comm};
1475     }else{
1476       savedvals[i].valid=0;
1477     }
1478   }
1479   int rank_traced = smpi_process_index();
1480   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
1481   extra->type = TRACING_WAITALL;
1482   extra->send_size=count;
1483   TRACE_smpi_ptp_in(rank_traced, -1, -1, __FUNCTION__,extra);
1484
1485   int retval = smpi_mpi_waitall(count, requests, status);
1486
1487   for (int i = 0; i < count; i++) {
1488     if(savedvals[i].valid){
1489     //the src may not have been known at the beginning of the recv (MPI_ANY_SOURCE)
1490       int src_traced = savedvals[i].src;
1491       int dst_traced = savedvals[i].dst;
1492       int is_wait_for_receive = savedvals[i].recv;
1493       if (is_wait_for_receive) {
1494         if(src_traced==MPI_ANY_SOURCE)
1495         src_traced = (status!=MPI_STATUSES_IGNORE) ?
1496                           smpi_group_rank(smpi_comm_group(savedvals[i].comm), status[i].MPI_SOURCE) : savedvals[i].src;
1497         TRACE_smpi_recv(rank_traced, src_traced, dst_traced,savedvals[i].tag);
1498       }
1499     }
1500   }
1501   TRACE_smpi_ptp_out(rank_traced, -1, -1, __FUNCTION__);
1502   xbt_free(savedvals);
1503
1504   smpi_bench_begin();
1505   return retval;
1506 }
1507
1508 int PMPI_Waitsome(int incount, MPI_Request requests[], int *outcount, int *indices, MPI_Status status[])
1509 {
1510   int retval = 0;
1511
1512   smpi_bench_end();
1513   if (outcount == nullptr) {
1514     retval = MPI_ERR_ARG;
1515   } else {
1516     *outcount = smpi_mpi_waitsome(incount, requests, indices, status);
1517     retval = MPI_SUCCESS;
1518   }
1519   smpi_bench_begin();
1520   return retval;
1521 }
1522
1523 int PMPI_Testsome(int incount, MPI_Request requests[], int* outcount, int* indices, MPI_Status status[])
1524 {
1525   int retval = 0;
1526
1527   smpi_bench_end();
1528   if (outcount == nullptr) {
1529     retval = MPI_ERR_ARG;
1530   } else {
1531     *outcount = smpi_mpi_testsome(incount, requests, indices, status);
1532     retval    = MPI_SUCCESS;
1533   }
1534   smpi_bench_begin();
1535   return retval;
1536 }
1537
1538
1539 int PMPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm)
1540 {
1541   int retval = 0;
1542
1543   smpi_bench_end();
1544
1545   if (comm == MPI_COMM_NULL) {
1546     retval = MPI_ERR_COMM;
1547   } else if (!is_datatype_valid(datatype)) {
1548     retval = MPI_ERR_ARG;
1549   } else {
1550     int rank        = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1551     int root_traced = smpi_group_index(smpi_comm_group(comm), root);
1552
1553     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1554     extra->type            = TRACING_BCAST;
1555     extra->root            = root_traced;
1556     int known              = 0;
1557     extra->datatype1       = encode_datatype(datatype, &known);
1558     int dt_size_send       = 1;
1559     if (known == 0)
1560       dt_size_send   = smpi_datatype_size(datatype);
1561     extra->send_size = count * dt_size_send;
1562     TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
1563     if (smpi_comm_size(comm) > 1)
1564       mpi_coll_bcast_fun(buf, count, datatype, root, comm);
1565     retval = MPI_SUCCESS;
1566
1567     TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1568   }
1569   smpi_bench_begin();
1570   return retval;
1571 }
1572
1573 int PMPI_Barrier(MPI_Comm comm)
1574 {
1575   int retval = 0;
1576
1577   smpi_bench_end();
1578
1579   if (comm == MPI_COMM_NULL) {
1580     retval = MPI_ERR_COMM;
1581   } else {
1582     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1583     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1584     extra->type            = TRACING_BARRIER;
1585     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
1586
1587     mpi_coll_barrier_fun(comm);
1588     retval = MPI_SUCCESS;
1589
1590     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1591   }
1592
1593   smpi_bench_begin();
1594   return retval;
1595 }
1596
1597 int PMPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,void *recvbuf, int recvcount, MPI_Datatype recvtype,
1598                 int root, MPI_Comm comm)
1599 {
1600   int retval = 0;
1601
1602   smpi_bench_end();
1603
1604   if (comm == MPI_COMM_NULL) {
1605     retval = MPI_ERR_COMM;
1606   } else if ((( sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) ||
1607             ((smpi_comm_rank(comm) == root) && (recvtype == MPI_DATATYPE_NULL))){
1608     retval = MPI_ERR_TYPE;
1609   } else if ((( sendbuf != MPI_IN_PLACE) && (sendcount <0)) || ((smpi_comm_rank(comm) == root) && (recvcount <0))){
1610     retval = MPI_ERR_COUNT;
1611   } else {
1612
1613     char* sendtmpbuf = static_cast<char*>(sendbuf);
1614     int sendtmpcount = sendcount;
1615     MPI_Datatype sendtmptype = sendtype;
1616     if( (smpi_comm_rank(comm) == root) && (sendbuf == MPI_IN_PLACE )) {
1617       sendtmpcount=0;
1618       sendtmptype=recvtype;
1619     }
1620     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1621     int root_traced        = smpi_group_index(smpi_comm_group(comm), root);
1622     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1623     extra->type            = TRACING_GATHER;
1624     extra->root            = root_traced;
1625     int known              = 0;
1626     extra->datatype1       = encode_datatype(sendtmptype, &known);
1627     int dt_size_send       = 1;
1628     if (known == 0)
1629       dt_size_send   = smpi_datatype_size(sendtmptype);
1630     extra->send_size = sendtmpcount * dt_size_send;
1631     extra->datatype2 = encode_datatype(recvtype, &known);
1632     int dt_size_recv = 1;
1633     if ((smpi_comm_rank(comm) == root) && known == 0)
1634       dt_size_recv   = smpi_datatype_size(recvtype);
1635     extra->recv_size = recvcount * dt_size_recv;
1636
1637     TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
1638
1639     mpi_coll_gather_fun(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcount, recvtype, root, comm);
1640
1641     retval = MPI_SUCCESS;
1642     TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1643   }
1644
1645   smpi_bench_begin();
1646   return retval;
1647 }
1648
1649 int PMPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int *recvcounts, int *displs,
1650                 MPI_Datatype recvtype, int root, MPI_Comm comm)
1651 {
1652   int retval = 0;
1653
1654   smpi_bench_end();
1655
1656   if (comm == MPI_COMM_NULL) {
1657     retval = MPI_ERR_COMM;
1658   } else if ((( sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) ||
1659             ((smpi_comm_rank(comm) == root) && (recvtype == MPI_DATATYPE_NULL))){
1660     retval = MPI_ERR_TYPE;
1661   } else if (( sendbuf != MPI_IN_PLACE) && (sendcount <0)){
1662     retval = MPI_ERR_COUNT;
1663   } else if (recvcounts == nullptr || displs == nullptr) {
1664     retval = MPI_ERR_ARG;
1665   } else {
1666     char* sendtmpbuf = static_cast<char*>(sendbuf);
1667     int sendtmpcount = sendcount;
1668     MPI_Datatype sendtmptype = sendtype;
1669     if( (smpi_comm_rank(comm) == root) && (sendbuf == MPI_IN_PLACE )) {
1670       sendtmpcount=0;
1671       sendtmptype=recvtype;
1672     }
1673
1674     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1675     int root_traced        = smpi_group_index(smpi_comm_group(comm), root);
1676     int i                  = 0;
1677     int size               = smpi_comm_size(comm);
1678     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1679     extra->type            = TRACING_GATHERV;
1680     extra->num_processes   = size;
1681     extra->root            = root_traced;
1682     int known              = 0;
1683     extra->datatype1       = encode_datatype(sendtmptype, &known);
1684     int dt_size_send       = 1;
1685     if (known == 0)
1686       dt_size_send   = smpi_datatype_size(sendtype);
1687     extra->send_size = sendtmpcount * dt_size_send;
1688     extra->datatype2 = encode_datatype(recvtype, &known);
1689     int dt_size_recv = 1;
1690     if (known == 0)
1691       dt_size_recv = smpi_datatype_size(recvtype);
1692     if ((smpi_comm_rank(comm) == root)) {
1693       extra->recvcounts = xbt_new(int, size);
1694       for (i                 = 0; i < size; i++) // copy data to avoid bad free
1695         extra->recvcounts[i] = recvcounts[i] * dt_size_recv;
1696     }
1697     TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
1698
1699     smpi_mpi_gatherv(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcounts, displs, recvtype, root, comm);
1700     retval = MPI_SUCCESS;
1701     TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1702   }
1703
1704   smpi_bench_begin();
1705   return retval;
1706 }
1707
1708 int PMPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1709                    void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm)
1710 {
1711   int retval = 0;
1712
1713   smpi_bench_end();
1714
1715   if (comm == MPI_COMM_NULL) {
1716     retval = MPI_ERR_COMM;
1717   } else if ((( sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) ||
1718             (recvtype == MPI_DATATYPE_NULL)){
1719     retval = MPI_ERR_TYPE;
1720   } else if ((( sendbuf != MPI_IN_PLACE) && (sendcount <0)) ||
1721             (recvcount <0)){
1722     retval = MPI_ERR_COUNT;
1723   } else {
1724     if(sendbuf == MPI_IN_PLACE) {
1725       sendbuf=static_cast<char*>(recvbuf)+smpi_datatype_get_extent(recvtype)*recvcount*smpi_comm_rank(comm);
1726       sendcount=recvcount;
1727       sendtype=recvtype;
1728     }
1729     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1730     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1731     extra->type            = TRACING_ALLGATHER;
1732     int known              = 0;
1733     extra->datatype1       = encode_datatype(sendtype, &known);
1734     int dt_size_send       = 1;
1735     if (known == 0)
1736       dt_size_send   = smpi_datatype_size(sendtype);
1737     extra->send_size = sendcount * dt_size_send;
1738     extra->datatype2 = encode_datatype(recvtype, &known);
1739     int dt_size_recv = 1;
1740     if (known == 0)
1741       dt_size_recv   = smpi_datatype_size(recvtype);
1742     extra->recv_size = recvcount * dt_size_recv;
1743
1744     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
1745
1746     mpi_coll_allgather_fun(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
1747     retval = MPI_SUCCESS;
1748     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1749   }
1750   smpi_bench_begin();
1751   return retval;
1752 }
1753
1754 int PMPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1755                    void *recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype, MPI_Comm comm)
1756 {
1757   int retval = 0;
1758
1759   smpi_bench_end();
1760
1761   if (comm == MPI_COMM_NULL) {
1762     retval = MPI_ERR_COMM;
1763   } else if (((sendbuf != MPI_IN_PLACE) && (sendtype == MPI_DATATYPE_NULL)) || (recvtype == MPI_DATATYPE_NULL)) {
1764     retval = MPI_ERR_TYPE;
1765   } else if (( sendbuf != MPI_IN_PLACE) && (sendcount <0)){
1766     retval = MPI_ERR_COUNT;
1767   } else if (recvcounts == nullptr || displs == nullptr) {
1768     retval = MPI_ERR_ARG;
1769   } else {
1770
1771     if(sendbuf == MPI_IN_PLACE) {
1772       sendbuf=static_cast<char*>(recvbuf)+smpi_datatype_get_extent(recvtype)*displs[smpi_comm_rank(comm)];
1773       sendcount=recvcounts[smpi_comm_rank(comm)];
1774       sendtype=recvtype;
1775     }
1776     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1777     int i                  = 0;
1778     int size               = smpi_comm_size(comm);
1779     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1780     extra->type            = TRACING_ALLGATHERV;
1781     extra->num_processes   = size;
1782     int known              = 0;
1783     extra->datatype1       = encode_datatype(sendtype, &known);
1784     int dt_size_send       = 1;
1785     if (known == 0)
1786       dt_size_send   = smpi_datatype_size(sendtype);
1787     extra->send_size = sendcount * dt_size_send;
1788     extra->datatype2 = encode_datatype(recvtype, &known);
1789     int dt_size_recv = 1;
1790     if (known == 0)
1791       dt_size_recv    = smpi_datatype_size(recvtype);
1792     extra->recvcounts = xbt_new(int, size);
1793     for (i                 = 0; i < size; i++) // copy data to avoid bad free
1794       extra->recvcounts[i] = recvcounts[i] * dt_size_recv;
1795
1796     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
1797
1798     mpi_coll_allgatherv_fun(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, comm);
1799     retval = MPI_SUCCESS;
1800     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1801   }
1802
1803   smpi_bench_begin();
1804   return retval;
1805 }
1806
1807 int PMPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
1808                 void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
1809 {
1810   int retval = 0;
1811
1812   smpi_bench_end();
1813
1814   if (comm == MPI_COMM_NULL) {
1815     retval = MPI_ERR_COMM;
1816   } else if (((smpi_comm_rank(comm) == root) && (!is_datatype_valid(sendtype))) ||
1817              ((recvbuf != MPI_IN_PLACE) && (!is_datatype_valid(recvtype)))) {
1818     retval = MPI_ERR_TYPE;
1819   } else if ((sendbuf == recvbuf) ||
1820       ((smpi_comm_rank(comm)==root) && sendcount>0 && (sendbuf == nullptr))){
1821     retval = MPI_ERR_BUFFER;
1822   }else {
1823
1824     if (recvbuf == MPI_IN_PLACE) {
1825       recvtype  = sendtype;
1826       recvcount = sendcount;
1827     }
1828     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1829     int root_traced        = smpi_group_index(smpi_comm_group(comm), root);
1830     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1831     extra->type            = TRACING_SCATTER;
1832     extra->root            = root_traced;
1833     int known              = 0;
1834     extra->datatype1       = encode_datatype(sendtype, &known);
1835     int dt_size_send       = 1;
1836     if ((smpi_comm_rank(comm) == root) && known == 0)
1837       dt_size_send   = smpi_datatype_size(sendtype);
1838     extra->send_size = sendcount * dt_size_send;
1839     extra->datatype2 = encode_datatype(recvtype, &known);
1840     int dt_size_recv = 1;
1841     if (known == 0)
1842       dt_size_recv   = smpi_datatype_size(recvtype);
1843     extra->recv_size = recvcount * dt_size_recv;
1844     TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
1845
1846     mpi_coll_scatter_fun(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm);
1847     retval = MPI_SUCCESS;
1848     TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1849   }
1850
1851   smpi_bench_begin();
1852   return retval;
1853 }
1854
1855 int PMPI_Scatterv(void *sendbuf, int *sendcounts, int *displs,
1856                  MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
1857 {
1858   int retval = 0;
1859
1860   smpi_bench_end();
1861
1862   if (comm == MPI_COMM_NULL) {
1863     retval = MPI_ERR_COMM;
1864   } else if (sendcounts == nullptr || displs == nullptr) {
1865     retval = MPI_ERR_ARG;
1866   } else if (((smpi_comm_rank(comm) == root) && (sendtype == MPI_DATATYPE_NULL)) ||
1867              ((recvbuf != MPI_IN_PLACE) && (recvtype == MPI_DATATYPE_NULL))) {
1868     retval = MPI_ERR_TYPE;
1869   } else {
1870     if (recvbuf == MPI_IN_PLACE) {
1871       recvtype  = sendtype;
1872       recvcount = sendcounts[smpi_comm_rank(comm)];
1873     }
1874     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1875     int root_traced        = smpi_group_index(smpi_comm_group(comm), root);
1876     int i                  = 0;
1877     int size               = smpi_comm_size(comm);
1878     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1879     extra->type            = TRACING_SCATTERV;
1880     extra->num_processes   = size;
1881     extra->root            = root_traced;
1882     int known              = 0;
1883     extra->datatype1       = encode_datatype(sendtype, &known);
1884     int dt_size_send       = 1;
1885     if (known == 0)
1886       dt_size_send = smpi_datatype_size(sendtype);
1887     if ((smpi_comm_rank(comm) == root)) {
1888       extra->sendcounts = xbt_new(int, size);
1889       for (i                 = 0; i < size; i++) // copy data to avoid bad free
1890         extra->sendcounts[i] = sendcounts[i] * dt_size_send;
1891     }
1892     extra->datatype2 = encode_datatype(recvtype, &known);
1893     int dt_size_recv = 1;
1894     if (known == 0)
1895       dt_size_recv   = smpi_datatype_size(recvtype);
1896     extra->recv_size = recvcount * dt_size_recv;
1897     TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
1898
1899     smpi_mpi_scatterv(sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, root, comm);
1900
1901     retval = MPI_SUCCESS;
1902     TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1903   }
1904
1905   smpi_bench_begin();
1906   return retval;
1907 }
1908
1909 int PMPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
1910 {
1911   int retval = 0;
1912
1913   smpi_bench_end();
1914
1915   if (comm == MPI_COMM_NULL) {
1916     retval = MPI_ERR_COMM;
1917   } else if (!is_datatype_valid(datatype) || op == MPI_OP_NULL) {
1918     retval = MPI_ERR_ARG;
1919   } else {
1920     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1921     int root_traced        = smpi_group_index(smpi_comm_group(comm), root);
1922     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1923     extra->type            = TRACING_REDUCE;
1924     int known              = 0;
1925     extra->datatype1       = encode_datatype(datatype, &known);
1926     int dt_size_send       = 1;
1927     if (known == 0)
1928       dt_size_send   = smpi_datatype_size(datatype);
1929     extra->send_size = count * dt_size_send;
1930     extra->root      = root_traced;
1931
1932     TRACE_smpi_collective_in(rank, root_traced, __FUNCTION__, extra);
1933
1934     mpi_coll_reduce_fun(sendbuf, recvbuf, count, datatype, op, root, comm);
1935
1936     retval = MPI_SUCCESS;
1937     TRACE_smpi_collective_out(rank, root_traced, __FUNCTION__);
1938   }
1939
1940   smpi_bench_begin();
1941   return retval;
1942 }
1943
1944 int PMPI_Reduce_local(void *inbuf, void *inoutbuf, int count, MPI_Datatype datatype, MPI_Op op){
1945   int retval = 0;
1946
1947   smpi_bench_end();
1948   if (!is_datatype_valid(datatype) || op == MPI_OP_NULL) {
1949     retval = MPI_ERR_ARG;
1950   } else {
1951     smpi_op_apply(op, inbuf, inoutbuf, &count, &datatype);
1952     retval = MPI_SUCCESS;
1953   }
1954   smpi_bench_begin();
1955   return retval;
1956 }
1957
1958 int PMPI_Allreduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
1959 {
1960   int retval = 0;
1961
1962   smpi_bench_end();
1963
1964   if (comm == MPI_COMM_NULL) {
1965     retval = MPI_ERR_COMM;
1966   } else if (!is_datatype_valid(datatype)) {
1967     retval = MPI_ERR_TYPE;
1968   } else if (op == MPI_OP_NULL) {
1969     retval = MPI_ERR_OP;
1970   } else {
1971
1972     char* sendtmpbuf = static_cast<char*>(sendbuf);
1973     if( sendbuf == MPI_IN_PLACE ) {
1974       sendtmpbuf = static_cast<char*>(xbt_malloc(count*smpi_datatype_get_extent(datatype)));
1975       smpi_datatype_copy(recvbuf, count, datatype,sendtmpbuf, count, datatype);
1976     }
1977     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
1978     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
1979     extra->type            = TRACING_ALLREDUCE;
1980     int known              = 0;
1981     extra->datatype1       = encode_datatype(datatype, &known);
1982     int dt_size_send       = 1;
1983     if (known == 0)
1984       dt_size_send   = smpi_datatype_size(datatype);
1985     extra->send_size = count * dt_size_send;
1986
1987     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
1988
1989     mpi_coll_allreduce_fun(sendtmpbuf, recvbuf, count, datatype, op, comm);
1990
1991     if( sendbuf == MPI_IN_PLACE )
1992       xbt_free(sendtmpbuf);
1993
1994     retval = MPI_SUCCESS;
1995     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
1996   }
1997
1998   smpi_bench_begin();
1999   return retval;
2000 }
2001
2002 int PMPI_Scan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
2003 {
2004   int retval = 0;
2005
2006   smpi_bench_end();
2007
2008   if (comm == MPI_COMM_NULL) {
2009     retval = MPI_ERR_COMM;
2010   } else if (!is_datatype_valid(datatype)) {
2011     retval = MPI_ERR_TYPE;
2012   } else if (op == MPI_OP_NULL) {
2013     retval = MPI_ERR_OP;
2014   } else {
2015     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
2016     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
2017     extra->type            = TRACING_SCAN;
2018     int known              = 0;
2019     extra->datatype1       = encode_datatype(datatype, &known);
2020     int dt_size_send       = 1;
2021     if (known == 0)
2022       dt_size_send   = smpi_datatype_size(datatype);
2023     extra->send_size = count * dt_size_send;
2024
2025     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2026
2027     smpi_mpi_scan(sendbuf, recvbuf, count, datatype, op, comm);
2028
2029     retval = MPI_SUCCESS;
2030     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2031   }
2032
2033   smpi_bench_begin();
2034   return retval;
2035 }
2036
2037 int PMPI_Exscan(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm){
2038   int retval = 0;
2039
2040   smpi_bench_end();
2041
2042   if (comm == MPI_COMM_NULL) {
2043     retval = MPI_ERR_COMM;
2044   } else if (!is_datatype_valid(datatype)) {
2045     retval = MPI_ERR_TYPE;
2046   } else if (op == MPI_OP_NULL) {
2047     retval = MPI_ERR_OP;
2048   } else {
2049     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
2050     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
2051     extra->type            = TRACING_EXSCAN;
2052     int known              = 0;
2053     extra->datatype1       = encode_datatype(datatype, &known);
2054     int dt_size_send       = 1;
2055     if (known == 0)
2056       dt_size_send   = smpi_datatype_size(datatype);
2057     extra->send_size = count * dt_size_send;
2058     void* sendtmpbuf = sendbuf;
2059     if (sendbuf == MPI_IN_PLACE) {
2060       sendtmpbuf = static_cast<void*>(xbt_malloc(count * smpi_datatype_size(datatype)));
2061       memcpy(sendtmpbuf, recvbuf, count * smpi_datatype_size(datatype));
2062     }
2063     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2064
2065     smpi_mpi_exscan(sendtmpbuf, recvbuf, count, datatype, op, comm);
2066     retval = MPI_SUCCESS;
2067     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2068     if (sendbuf == MPI_IN_PLACE)
2069       xbt_free(sendtmpbuf);
2070   }
2071
2072   smpi_bench_begin();
2073   return retval;
2074 }
2075
2076 int PMPI_Reduce_scatter(void *sendbuf, void *recvbuf, int *recvcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
2077 {
2078   int retval = 0;
2079   smpi_bench_end();
2080
2081   if (comm == MPI_COMM_NULL) {
2082     retval = MPI_ERR_COMM;
2083   } else if (!is_datatype_valid(datatype)) {
2084     retval = MPI_ERR_TYPE;
2085   } else if (op == MPI_OP_NULL) {
2086     retval = MPI_ERR_OP;
2087   } else if (recvcounts == nullptr) {
2088     retval = MPI_ERR_ARG;
2089   } else {
2090     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
2091     int i                  = 0;
2092     int size               = smpi_comm_size(comm);
2093     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
2094     extra->type            = TRACING_REDUCE_SCATTER;
2095     extra->num_processes   = size;
2096     int known              = 0;
2097     extra->datatype1       = encode_datatype(datatype, &known);
2098     int dt_size_send       = 1;
2099     if (known == 0)
2100       dt_size_send    = smpi_datatype_size(datatype);
2101     extra->send_size  = 0;
2102     extra->recvcounts = xbt_new(int, size);
2103     int totalcount    = 0;
2104     for (i = 0; i < size; i++) { // copy data to avoid bad free
2105       extra->recvcounts[i] = recvcounts[i] * dt_size_send;
2106       totalcount += recvcounts[i];
2107     }
2108     void* sendtmpbuf = sendbuf;
2109     if (sendbuf == MPI_IN_PLACE) {
2110       sendtmpbuf = static_cast<void*>(xbt_malloc(totalcount * smpi_datatype_size(datatype)));
2111       memcpy(sendtmpbuf, recvbuf, totalcount * smpi_datatype_size(datatype));
2112     }
2113
2114     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2115
2116     mpi_coll_reduce_scatter_fun(sendtmpbuf, recvbuf, recvcounts, datatype, op, comm);
2117     retval = MPI_SUCCESS;
2118     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2119
2120     if (sendbuf == MPI_IN_PLACE)
2121       xbt_free(sendtmpbuf);
2122   }
2123
2124   smpi_bench_begin();
2125   return retval;
2126 }
2127
2128 int PMPI_Reduce_scatter_block(void *sendbuf, void *recvbuf, int recvcount,
2129                               MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
2130 {
2131   int retval;
2132   smpi_bench_end();
2133
2134   if (comm == MPI_COMM_NULL) {
2135     retval = MPI_ERR_COMM;
2136   } else if (!is_datatype_valid(datatype)) {
2137     retval = MPI_ERR_TYPE;
2138   } else if (op == MPI_OP_NULL) {
2139     retval = MPI_ERR_OP;
2140   } else if (recvcount < 0) {
2141     retval = MPI_ERR_ARG;
2142   } else {
2143     int count = smpi_comm_size(comm);
2144
2145     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
2146     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
2147     extra->type            = TRACING_REDUCE_SCATTER;
2148     extra->num_processes   = count;
2149     int known              = 0;
2150     extra->datatype1       = encode_datatype(datatype, &known);
2151     int dt_size_send       = 1;
2152     if (known == 0)
2153       dt_size_send    = smpi_datatype_size(datatype);
2154     extra->send_size  = 0;
2155     extra->recvcounts = xbt_new(int, count);
2156     for (int i             = 0; i < count; i++) // copy data to avoid bad free
2157       extra->recvcounts[i] = recvcount * dt_size_send;
2158     void* sendtmpbuf       = sendbuf;
2159     if (sendbuf == MPI_IN_PLACE) {
2160       sendtmpbuf = static_cast<void*>(xbt_malloc(recvcount * count * smpi_datatype_size(datatype)));
2161       memcpy(sendtmpbuf, recvbuf, recvcount * count * smpi_datatype_size(datatype));
2162     }
2163
2164     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2165
2166     int* recvcounts = static_cast<int*>(xbt_malloc(count * sizeof(int)));
2167     for (int i      = 0; i < count; i++)
2168       recvcounts[i] = recvcount;
2169     mpi_coll_reduce_scatter_fun(sendtmpbuf, recvbuf, recvcounts, datatype, op, comm);
2170     xbt_free(recvcounts);
2171     retval = MPI_SUCCESS;
2172
2173     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2174
2175     if (sendbuf == MPI_IN_PLACE)
2176       xbt_free(sendtmpbuf);
2177   }
2178
2179   smpi_bench_begin();
2180   return retval;
2181 }
2182
2183 int PMPI_Alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
2184                   MPI_Datatype recvtype, MPI_Comm comm)
2185 {
2186   int retval = 0;
2187   smpi_bench_end();
2188
2189   if (comm == MPI_COMM_NULL) {
2190     retval = MPI_ERR_COMM;
2191   } else if ((sendbuf != MPI_IN_PLACE && sendtype == MPI_DATATYPE_NULL) || recvtype == MPI_DATATYPE_NULL) {
2192     retval = MPI_ERR_TYPE;
2193   } else {
2194     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
2195     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
2196     extra->type            = TRACING_ALLTOALL;
2197
2198     void* sendtmpbuf         = static_cast<char*>(sendbuf);
2199     int sendtmpcount         = sendcount;
2200     MPI_Datatype sendtmptype = sendtype;
2201     if (sendbuf == MPI_IN_PLACE) {
2202       sendtmpbuf = static_cast<void*>(xbt_malloc(recvcount * smpi_comm_size(comm) * smpi_datatype_size(recvtype)));
2203       memcpy(sendtmpbuf, recvbuf, recvcount * smpi_comm_size(comm) * smpi_datatype_size(recvtype));
2204       sendtmpcount = recvcount;
2205       sendtmptype  = recvtype;
2206     }
2207
2208     int known        = 0;
2209     extra->datatype1 = encode_datatype(sendtmptype, &known);
2210     if (known == 0)
2211       extra->send_size = sendtmpcount * smpi_datatype_size(sendtmptype);
2212     else
2213       extra->send_size = sendtmpcount;
2214     extra->datatype2   = encode_datatype(recvtype, &known);
2215     if (known == 0)
2216       extra->recv_size = recvcount * smpi_datatype_size(recvtype);
2217     else
2218       extra->recv_size = recvcount;
2219
2220     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2221
2222     retval = mpi_coll_alltoall_fun(sendtmpbuf, sendtmpcount, sendtmptype, recvbuf, recvcount, recvtype, comm);
2223
2224     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2225
2226     if (sendbuf == MPI_IN_PLACE)
2227       xbt_free(sendtmpbuf);
2228   }
2229
2230   smpi_bench_begin();
2231   return retval;
2232 }
2233
2234 int PMPI_Alltoallv(void* sendbuf, int* sendcounts, int* senddisps, MPI_Datatype sendtype, void* recvbuf,
2235                    int* recvcounts, int* recvdisps, MPI_Datatype recvtype, MPI_Comm comm)
2236 {
2237   int retval = 0;
2238
2239   smpi_bench_end();
2240
2241   if (comm == MPI_COMM_NULL) {
2242     retval = MPI_ERR_COMM;
2243   } else if (sendtype == MPI_DATATYPE_NULL || recvtype == MPI_DATATYPE_NULL) {
2244     retval = MPI_ERR_TYPE;
2245   } else if ((sendbuf != MPI_IN_PLACE && (sendcounts == nullptr || senddisps == nullptr)) || recvcounts == nullptr ||
2246              recvdisps == nullptr) {
2247     retval = MPI_ERR_ARG;
2248   } else {
2249     int rank               = comm != MPI_COMM_NULL ? smpi_process_index() : -1;
2250     int i                  = 0;
2251     int size               = smpi_comm_size(comm);
2252     instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
2253     extra->type            = TRACING_ALLTOALLV;
2254     extra->send_size       = 0;
2255     extra->recv_size       = 0;
2256     extra->recvcounts      = xbt_new(int, size);
2257     extra->sendcounts      = xbt_new(int, size);
2258     int known              = 0;
2259     int dt_size_recv       = 1;
2260     extra->datatype2       = encode_datatype(recvtype, &known);
2261     dt_size_recv           = smpi_datatype_size(recvtype);
2262
2263     void* sendtmpbuf         = static_cast<char*>(sendbuf);
2264     int* sendtmpcounts       = sendcounts;
2265     int* sendtmpdisps        = senddisps;
2266     MPI_Datatype sendtmptype = sendtype;
2267     int maxsize              = 0;
2268     for (i = 0; i < size; i++) { // copy data to avoid bad free
2269       extra->recv_size += recvcounts[i] * dt_size_recv;
2270       extra->recvcounts[i] = recvcounts[i] * dt_size_recv;
2271       if (((recvdisps[i] + recvcounts[i]) * dt_size_recv) > maxsize)
2272         maxsize = (recvdisps[i] + recvcounts[i]) * dt_size_recv;
2273     }
2274
2275     if (sendbuf == MPI_IN_PLACE) {
2276       sendtmpbuf = static_cast<void*>(xbt_malloc(maxsize));
2277       memcpy(sendtmpbuf, recvbuf, maxsize);
2278       sendtmpcounts = static_cast<int*>(xbt_malloc(size * sizeof(int)));
2279       memcpy(sendtmpcounts, recvcounts, size * sizeof(int));
2280       sendtmpdisps = static_cast<int*>(xbt_malloc(size * sizeof(int)));
2281       memcpy(sendtmpdisps, recvdisps, size * sizeof(int));
2282       sendtmptype = recvtype;
2283     }
2284
2285     extra->datatype1 = encode_datatype(sendtmptype, &known);
2286     int dt_size_send = 1;
2287     dt_size_send     = smpi_datatype_size(sendtmptype);
2288
2289     for (i = 0; i < size; i++) { // copy data to avoid bad free
2290       extra->send_size += sendtmpcounts[i] * dt_size_send;
2291       extra->sendcounts[i] = sendtmpcounts[i] * dt_size_send;
2292     }
2293     extra->num_processes = size;
2294     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2295     retval = mpi_coll_alltoallv_fun(sendtmpbuf, sendtmpcounts, sendtmpdisps, sendtmptype, recvbuf, recvcounts,
2296                                     recvdisps, recvtype, comm);
2297     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2298
2299     if (sendbuf == MPI_IN_PLACE) {
2300       xbt_free(sendtmpbuf);
2301       xbt_free(sendtmpcounts);
2302       xbt_free(sendtmpdisps);
2303     }
2304   }
2305
2306   smpi_bench_begin();
2307   return retval;
2308 }
2309
2310
2311 int PMPI_Get_processor_name(char *name, int *resultlen)
2312 {
2313   strncpy(name, SIMIX_host_self()->cname(), strlen(SIMIX_host_self()->cname()) < MPI_MAX_PROCESSOR_NAME - 1
2314                                                 ? strlen(SIMIX_host_self()->cname()) + 1
2315                                                 : MPI_MAX_PROCESSOR_NAME - 1);
2316   *resultlen = strlen(name) > MPI_MAX_PROCESSOR_NAME ? MPI_MAX_PROCESSOR_NAME : strlen(name);
2317
2318   return MPI_SUCCESS;
2319 }
2320
2321 int PMPI_Get_count(MPI_Status * status, MPI_Datatype datatype, int *count)
2322 {
2323   if (status == nullptr || count == nullptr) {
2324     return MPI_ERR_ARG;
2325   } else if (!is_datatype_valid(datatype)) {
2326     return MPI_ERR_TYPE;
2327   } else {
2328     size_t size = smpi_datatype_size(datatype);
2329     if (size == 0) {
2330       *count = 0;
2331       return MPI_SUCCESS;
2332     } else if (status->count % size != 0) {
2333       return MPI_UNDEFINED;
2334     } else {
2335       *count = smpi_mpi_get_count(status, datatype);
2336       return MPI_SUCCESS;
2337     }
2338   }
2339 }
2340
2341 int PMPI_Type_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type) {
2342   if (old_type == MPI_DATATYPE_NULL) {
2343     return MPI_ERR_TYPE;
2344   } else if (count<0){
2345     return MPI_ERR_COUNT;
2346   } else {
2347     return smpi_datatype_contiguous(count, old_type, new_type, 0);
2348   }
2349 }
2350
2351 int PMPI_Type_commit(MPI_Datatype* datatype) {
2352   if (datatype == nullptr || *datatype == MPI_DATATYPE_NULL) {
2353     return MPI_ERR_TYPE;
2354   } else {
2355     smpi_datatype_commit(datatype);
2356     return MPI_SUCCESS;
2357   }
2358 }
2359
2360 int PMPI_Type_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type) {
2361   if (old_type == MPI_DATATYPE_NULL) {
2362     return MPI_ERR_TYPE;
2363   } else if (count<0 || blocklen<0){
2364     return MPI_ERR_COUNT;
2365   } else {
2366     return smpi_datatype_vector(count, blocklen, stride, old_type, new_type);
2367   }
2368 }
2369
2370 int PMPI_Type_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type) {
2371   if (old_type == MPI_DATATYPE_NULL) {
2372     return MPI_ERR_TYPE;
2373   } else if (count<0 || blocklen<0){
2374     return MPI_ERR_COUNT;
2375   } else {
2376     return smpi_datatype_hvector(count, blocklen, stride, old_type, new_type);
2377   }
2378 }
2379
2380 int PMPI_Type_create_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type) {
2381   return MPI_Type_hvector(count, blocklen, stride, old_type, new_type);
2382 }
2383
2384 int PMPI_Type_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type) {
2385   if (old_type == MPI_DATATYPE_NULL) {
2386     return MPI_ERR_TYPE;
2387   } else if (count<0){
2388     return MPI_ERR_COUNT;
2389   } else {
2390     return smpi_datatype_indexed(count, blocklens, indices, old_type, new_type);
2391   }
2392 }
2393
2394 int PMPI_Type_create_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type) {
2395   if (old_type == MPI_DATATYPE_NULL) {
2396     return MPI_ERR_TYPE;
2397   } else if (count<0){
2398     return MPI_ERR_COUNT;
2399   } else {
2400     return smpi_datatype_indexed(count, blocklens, indices, old_type, new_type);
2401   }
2402 }
2403
2404 int PMPI_Type_create_indexed_block(int count, int blocklength, int* indices, MPI_Datatype old_type,
2405                                    MPI_Datatype* new_type)
2406 {
2407   if (old_type == MPI_DATATYPE_NULL) {
2408     return MPI_ERR_TYPE;
2409   } else if (count<0){
2410     return MPI_ERR_COUNT;
2411   } else {
2412     int* blocklens=static_cast<int*>(xbt_malloc(blocklength*count*sizeof(int)));
2413     for (int i    = 0; i < count; i++)
2414       blocklens[i]=blocklength;
2415     int retval    = smpi_datatype_indexed(count, blocklens, indices, old_type, new_type);
2416     xbt_free(blocklens);
2417     return retval;
2418   }
2419 }
2420
2421 int PMPI_Type_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
2422 {
2423   if (old_type == MPI_DATATYPE_NULL) {
2424     return MPI_ERR_TYPE;
2425   } else if (count<0){
2426     return MPI_ERR_COUNT;
2427   } else {
2428     return smpi_datatype_hindexed(count, blocklens, indices, old_type, new_type);
2429   }
2430 }
2431
2432 int PMPI_Type_create_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type,
2433                               MPI_Datatype* new_type) {
2434   return PMPI_Type_hindexed(count, blocklens,indices,old_type,new_type);
2435 }
2436
2437 int PMPI_Type_create_hindexed_block(int count, int blocklength, MPI_Aint* indices, MPI_Datatype old_type,
2438                                     MPI_Datatype* new_type) {
2439   if (old_type == MPI_DATATYPE_NULL) {
2440     return MPI_ERR_TYPE;
2441   } else if (count<0){
2442     return MPI_ERR_COUNT;
2443   } else {
2444     int* blocklens=(int*)xbt_malloc(blocklength*count*sizeof(int));
2445     for (int i     = 0; i < count; i++)
2446       blocklens[i] = blocklength;
2447     int retval     = smpi_datatype_hindexed(count, blocklens, indices, old_type, new_type);
2448     xbt_free(blocklens);
2449     return retval;
2450   }
2451 }
2452
2453 int PMPI_Type_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type) {
2454   if (count<0){
2455     return MPI_ERR_COUNT;
2456   } else {
2457     return smpi_datatype_struct(count, blocklens, indices, old_types, new_type);
2458   }
2459 }
2460
2461 int PMPI_Type_create_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types,
2462                             MPI_Datatype* new_type) {
2463   return PMPI_Type_struct(count, blocklens, indices, old_types, new_type);
2464 }
2465
2466 int PMPI_Error_class(int errorcode, int* errorclass) {
2467   // assume smpi uses only standard mpi error codes
2468   *errorclass=errorcode;
2469   return MPI_SUCCESS;
2470 }
2471
2472 int PMPI_Initialized(int* flag) {
2473    *flag=smpi_process_initialized();
2474    return MPI_SUCCESS;
2475 }
2476
2477 /* The topo part of MPI_COMM_WORLD should always be nullptr. When other topologies will be implemented, not only should we
2478  * check if the topology is nullptr, but we should check if it is the good topology type (so we have to add a
2479  *  MPIR_Topo_Type field, and replace the MPI_Topology field by an union)*/
2480
2481 int PMPI_Cart_create(MPI_Comm comm_old, int ndims, int* dims, int* periodic, int reorder, MPI_Comm* comm_cart) {
2482   if (comm_old == MPI_COMM_NULL){
2483     return MPI_ERR_COMM;
2484   } else if (ndims < 0 || (ndims > 0 && (dims == nullptr || periodic == nullptr)) || comm_cart == nullptr) {
2485     return MPI_ERR_ARG;
2486   } else{
2487     return smpi_mpi_cart_create(comm_old, ndims, dims, periodic, reorder, comm_cart);
2488   }
2489 }
2490
2491 int PMPI_Cart_rank(MPI_Comm comm, int* coords, int* rank) {
2492   if(comm == MPI_COMM_NULL || smpi_comm_topo(comm) == nullptr) {
2493     return MPI_ERR_TOPOLOGY;
2494   }
2495   if (coords == nullptr) {
2496     return MPI_ERR_ARG;
2497   }
2498   return smpi_mpi_cart_rank(comm, coords, rank);
2499 }
2500
2501 int PMPI_Cart_shift(MPI_Comm comm, int direction, int displ, int* source, int* dest) {
2502   if(comm == MPI_COMM_NULL || smpi_comm_topo(comm) == nullptr) {
2503     return MPI_ERR_TOPOLOGY;
2504   }
2505   if (source == nullptr || dest == nullptr || direction < 0 ) {
2506     return MPI_ERR_ARG;
2507   }
2508   return smpi_mpi_cart_shift(comm, direction, displ, source, dest);
2509 }
2510
2511 int PMPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int* coords) {
2512   if(comm == MPI_COMM_NULL || smpi_comm_topo(comm) == nullptr) {
2513     return MPI_ERR_TOPOLOGY;
2514   }
2515   if (rank < 0 || rank >= smpi_comm_size(comm)) {
2516     return MPI_ERR_RANK;
2517   }
2518   if (maxdims <= 0) {
2519     return MPI_ERR_ARG;
2520   }
2521   if(coords == nullptr) {
2522     return MPI_ERR_ARG;
2523   }
2524   return smpi_mpi_cart_coords(comm, rank, maxdims, coords);
2525 }
2526
2527 int PMPI_Cart_get(MPI_Comm comm, int maxdims, int* dims, int* periods, int* coords) {
2528   if(comm == nullptr || smpi_comm_topo(comm) == nullptr) {
2529     return MPI_ERR_TOPOLOGY;
2530   }
2531   if(maxdims <= 0 || dims == nullptr || periods == nullptr || coords == nullptr) {
2532     return MPI_ERR_ARG;
2533   }
2534   return smpi_mpi_cart_get(comm, maxdims, dims, periods, coords);
2535 }
2536
2537 int PMPI_Cartdim_get(MPI_Comm comm, int* ndims) {
2538   if (comm == MPI_COMM_NULL || smpi_comm_topo(comm) == nullptr) {
2539     return MPI_ERR_TOPOLOGY;
2540   }
2541   if (ndims == nullptr) {
2542     return MPI_ERR_ARG;
2543   }
2544   return smpi_mpi_cartdim_get(comm, ndims);
2545 }
2546
2547 int PMPI_Dims_create(int nnodes, int ndims, int* dims) {
2548   if(dims == nullptr) {
2549     return MPI_ERR_ARG;
2550   }
2551   if (ndims < 1 || nnodes < 1) {
2552     return MPI_ERR_DIMS;
2553   }
2554
2555   return smpi_mpi_dims_create(nnodes, ndims, dims);
2556 }
2557
2558 int PMPI_Cart_sub(MPI_Comm comm, int* remain_dims, MPI_Comm* comm_new) {
2559   if(comm == MPI_COMM_NULL || smpi_comm_topo(comm) == nullptr) {
2560     return MPI_ERR_TOPOLOGY;
2561   }
2562   if (comm_new == nullptr) {
2563     return MPI_ERR_ARG;
2564   }
2565   return smpi_mpi_cart_sub(comm, remain_dims, comm_new);
2566 }
2567
2568 int PMPI_Type_create_resized(MPI_Datatype oldtype,MPI_Aint lb, MPI_Aint extent, MPI_Datatype *newtype){
2569   if (oldtype == MPI_DATATYPE_NULL) {
2570     return MPI_ERR_TYPE;
2571   }
2572   int blocks[3]         = {1, 1, 1};
2573   MPI_Aint disps[3]     = {lb, 0, lb + extent};
2574   MPI_Datatype types[3] = {MPI_LB, oldtype, MPI_UB};
2575
2576   s_smpi_mpi_struct_t* subtype = smpi_datatype_struct_create(blocks, disps, 3, types);
2577   smpi_datatype_create(newtype, oldtype->size, lb, lb + extent, sizeof(s_smpi_mpi_struct_t), subtype, DT_FLAG_VECTOR);
2578
2579   (*newtype)->flags &= ~DT_FLAG_COMMITED;
2580   return MPI_SUCCESS;
2581 }
2582
2583 int PMPI_Win_create( void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win){
2584   int retval = 0;
2585   smpi_bench_end();
2586   if (comm == MPI_COMM_NULL) {
2587     retval= MPI_ERR_COMM;
2588   }else if ((base == nullptr && size != 0) || disp_unit <= 0 || size < 0 ){
2589     retval= MPI_ERR_OTHER;
2590   }else{
2591     *win = smpi_mpi_win_create( base, size, disp_unit, info, comm);
2592     retval = MPI_SUCCESS;
2593   }
2594   smpi_bench_begin();
2595   return retval;
2596 }
2597
2598 int PMPI_Win_free( MPI_Win* win){
2599   int retval = 0;
2600   smpi_bench_end();
2601   if (win == nullptr || *win == MPI_WIN_NULL) {
2602     retval = MPI_ERR_WIN;
2603   }else{
2604     retval=smpi_mpi_win_free(win);
2605   }
2606   smpi_bench_begin();
2607   return retval;
2608 }
2609
2610 int PMPI_Win_set_name(MPI_Win  win, char * name)
2611 {
2612   if (win == MPI_WIN_NULL)  {
2613     return MPI_ERR_TYPE;
2614   } else if (name == nullptr)  {
2615     return MPI_ERR_ARG;
2616   } else {
2617     smpi_mpi_win_set_name(win, name);
2618     return MPI_SUCCESS;
2619   }
2620 }
2621
2622 int PMPI_Win_get_name(MPI_Win  win, char * name, int* len)
2623 {
2624   if (win == MPI_WIN_NULL)  {
2625     return MPI_ERR_WIN;
2626   } else if (name == nullptr)  {
2627     return MPI_ERR_ARG;
2628   } else {
2629     smpi_mpi_win_get_name(win, name, len);
2630     return MPI_SUCCESS;
2631   }
2632 }
2633
2634 int PMPI_Win_get_group(MPI_Win  win, MPI_Group * group){
2635   if (win == MPI_WIN_NULL)  {
2636     return MPI_ERR_WIN;
2637   }else {
2638     smpi_mpi_win_get_group(win, group);
2639     smpi_group_use(*group);
2640     return MPI_SUCCESS;
2641   }
2642 }
2643
2644 int PMPI_Win_fence( int assert,  MPI_Win win){
2645   int retval = 0;
2646   smpi_bench_end();
2647   if (win == MPI_WIN_NULL) {
2648     retval = MPI_ERR_WIN;
2649   } else {
2650   int rank = smpi_process_index();
2651   TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2652   retval = smpi_mpi_win_fence(assert, win);
2653   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2654   }
2655   smpi_bench_begin();
2656   return retval;
2657 }
2658
2659 int PMPI_Get( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2660               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win){
2661   int retval = 0;
2662   smpi_bench_end();
2663   if (win == MPI_WIN_NULL) {
2664     retval = MPI_ERR_WIN;
2665   } else if (target_rank == MPI_PROC_NULL) {
2666     retval = MPI_SUCCESS;
2667   } else if (target_rank <0){
2668     retval = MPI_ERR_RANK;
2669   } else if (target_disp <0){
2670     retval = MPI_ERR_ARG;
2671   } else if ((origin_count < 0 || target_count < 0) ||
2672              (origin_addr==nullptr && origin_count > 0)){
2673     retval = MPI_ERR_COUNT;
2674   } else if ((!is_datatype_valid(origin_datatype)) || (!is_datatype_valid(target_datatype))) {
2675     retval = MPI_ERR_TYPE;
2676   } else {
2677     int rank = smpi_process_index();
2678     MPI_Group group;
2679     smpi_mpi_win_get_group(win, &group);
2680     int src_traced = smpi_group_index(group, target_rank);
2681     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2682
2683     retval = smpi_mpi_get( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2684                            target_datatype, win);
2685
2686     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2687   }
2688   smpi_bench_begin();
2689   return retval;
2690 }
2691
2692 int PMPI_Put( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2693               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win){
2694   int retval = 0;
2695   smpi_bench_end();
2696   if (win == MPI_WIN_NULL) {
2697     retval = MPI_ERR_WIN;
2698   } else if (target_rank == MPI_PROC_NULL) {
2699     retval = MPI_SUCCESS;
2700   } else if (target_rank <0){
2701     retval = MPI_ERR_RANK;
2702   } else if (target_disp <0){
2703     retval = MPI_ERR_ARG;
2704   } else if ((origin_count < 0 || target_count < 0) ||
2705             (origin_addr==nullptr && origin_count > 0)){
2706     retval = MPI_ERR_COUNT;
2707   } else if ((!is_datatype_valid(origin_datatype)) || (!is_datatype_valid(target_datatype))) {
2708     retval = MPI_ERR_TYPE;
2709   } else {
2710     int rank = smpi_process_index();
2711     MPI_Group group;
2712     smpi_mpi_win_get_group(win, &group);
2713     int dst_traced = smpi_group_index(group, target_rank);
2714     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, nullptr);
2715     TRACE_smpi_send(rank, rank, dst_traced, SMPI_RMA_TAG, origin_count*smpi_datatype_size(origin_datatype));
2716
2717     retval = smpi_mpi_put( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2718                            target_datatype, win);
2719
2720     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
2721   }
2722   smpi_bench_begin();
2723   return retval;
2724 }
2725
2726 int PMPI_Accumulate( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2727               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win){
2728   int retval = 0;
2729   smpi_bench_end();
2730   if (win == MPI_WIN_NULL) {
2731     retval = MPI_ERR_WIN;
2732   } else if (target_rank == MPI_PROC_NULL) {
2733     retval = MPI_SUCCESS;
2734   } else if (target_rank <0){
2735     retval = MPI_ERR_RANK;
2736   } else if (target_disp <0){
2737     retval = MPI_ERR_ARG;
2738   } else if ((origin_count < 0 || target_count < 0) ||
2739              (origin_addr==nullptr && origin_count > 0)){
2740     retval = MPI_ERR_COUNT;
2741   } else if ((!is_datatype_valid(origin_datatype)) ||
2742             (!is_datatype_valid(target_datatype))) {
2743     retval = MPI_ERR_TYPE;
2744   } else if (op == MPI_OP_NULL) {
2745     retval = MPI_ERR_OP;
2746   } else {
2747     int rank = smpi_process_index();
2748     MPI_Group group;
2749     smpi_mpi_win_get_group(win, &group);
2750     int src_traced = smpi_group_index(group, target_rank);
2751     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2752
2753     retval = smpi_mpi_accumulate( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2754                                   target_datatype, op, win);
2755
2756     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2757   }
2758   smpi_bench_begin();
2759   return retval;
2760 }
2761
2762 int PMPI_Win_post(MPI_Group group, int assert, MPI_Win win){
2763   int retval = 0;
2764   smpi_bench_end();
2765   if (win == MPI_WIN_NULL) {
2766     retval = MPI_ERR_WIN;
2767   } else if (group==MPI_GROUP_NULL){
2768     retval = MPI_ERR_GROUP;
2769   } else {
2770     int rank = smpi_process_index();
2771     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2772     retval = smpi_mpi_win_post(group,assert,win);
2773     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2774   }
2775   smpi_bench_begin();
2776   return retval;
2777 }
2778
2779 int PMPI_Win_start(MPI_Group group, int assert, MPI_Win win){
2780   int retval = 0;
2781   smpi_bench_end();
2782   if (win == MPI_WIN_NULL) {
2783     retval = MPI_ERR_WIN;
2784   } else if (group==MPI_GROUP_NULL){
2785     retval = MPI_ERR_GROUP;
2786   } else {
2787     int rank = smpi_process_index();
2788     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2789     retval = smpi_mpi_win_start(group,assert,win);
2790     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2791   }
2792   smpi_bench_begin();
2793   return retval;
2794 }
2795
2796 int PMPI_Win_complete(MPI_Win win){
2797   int retval = 0;
2798   smpi_bench_end();
2799   if (win == MPI_WIN_NULL) {
2800     retval = MPI_ERR_WIN;
2801   } else {
2802     int rank = smpi_process_index();
2803     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2804
2805     retval = smpi_mpi_win_complete(win);
2806
2807     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2808   }
2809   smpi_bench_begin();
2810   return retval;
2811 }
2812
2813 int PMPI_Win_wait(MPI_Win win){
2814   int retval = 0;
2815   smpi_bench_end();
2816   if (win == MPI_WIN_NULL) {
2817     retval = MPI_ERR_WIN;
2818   } else {
2819     int rank = smpi_process_index();
2820     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2821
2822     retval = smpi_mpi_win_wait(win);
2823
2824     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2825   }
2826   smpi_bench_begin();
2827   return retval;
2828 }
2829
2830 int PMPI_Alloc_mem(MPI_Aint size, MPI_Info info, void *baseptr){
2831   void *ptr = xbt_malloc(size);
2832   if(ptr==nullptr)
2833     return MPI_ERR_NO_MEM;
2834   else {
2835     *static_cast<void**>(baseptr) = ptr;
2836     return MPI_SUCCESS;
2837   }
2838 }
2839
2840 int PMPI_Free_mem(void *baseptr){
2841   xbt_free(baseptr);
2842   return MPI_SUCCESS;
2843 }
2844
2845 int PMPI_Type_set_name(MPI_Datatype  datatype, char * name)
2846 {
2847   if (datatype == MPI_DATATYPE_NULL)  {
2848     return MPI_ERR_TYPE;
2849   } else if (name == nullptr)  {
2850     return MPI_ERR_ARG;
2851   } else {
2852     smpi_datatype_set_name(datatype, name);
2853     return MPI_SUCCESS;
2854   }
2855 }
2856
2857 int PMPI_Type_get_name(MPI_Datatype  datatype, char * name, int* len)
2858 {
2859   if (datatype == MPI_DATATYPE_NULL)  {
2860     return MPI_ERR_TYPE;
2861   } else if (name == nullptr)  {
2862     return MPI_ERR_ARG;
2863   } else {
2864     smpi_datatype_get_name(datatype, name, len);
2865     return MPI_SUCCESS;
2866   }
2867 }
2868
2869 MPI_Datatype PMPI_Type_f2c(MPI_Fint datatype){
2870   return smpi_type_f2c(datatype);
2871 }
2872
2873 MPI_Fint PMPI_Type_c2f(MPI_Datatype datatype){
2874   return smpi_type_c2f( datatype);
2875 }
2876
2877 MPI_Group PMPI_Group_f2c(MPI_Fint group){
2878   return smpi_group_f2c( group);
2879 }
2880
2881 MPI_Fint PMPI_Group_c2f(MPI_Group group){
2882   return smpi_group_c2f(group);
2883 }
2884
2885 MPI_Request PMPI_Request_f2c(MPI_Fint request){
2886   return smpi_request_f2c(request);
2887 }
2888
2889 MPI_Fint PMPI_Request_c2f(MPI_Request request) {
2890   return smpi_request_c2f(request);
2891 }
2892
2893 MPI_Win PMPI_Win_f2c(MPI_Fint win){
2894   return smpi_win_f2c(win);
2895 }
2896
2897 MPI_Fint PMPI_Win_c2f(MPI_Win win){
2898   return smpi_win_c2f(win);
2899 }
2900
2901 MPI_Op PMPI_Op_f2c(MPI_Fint op){
2902   return smpi_op_f2c(op);
2903 }
2904
2905 MPI_Fint PMPI_Op_c2f(MPI_Op op){
2906   return smpi_op_c2f(op);
2907 }
2908
2909 MPI_Comm PMPI_Comm_f2c(MPI_Fint comm){
2910   return smpi_comm_f2c(comm);
2911 }
2912
2913 MPI_Fint PMPI_Comm_c2f(MPI_Comm comm){
2914   return smpi_comm_c2f(comm);
2915 }
2916
2917 MPI_Info PMPI_Info_f2c(MPI_Fint info){
2918   return smpi_info_f2c(info);
2919 }
2920
2921 MPI_Fint PMPI_Info_c2f(MPI_Info info){
2922   return smpi_info_c2f(info);
2923 }
2924
2925 int PMPI_Keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state) {
2926   return smpi_comm_keyval_create(copy_fn, delete_fn, keyval, extra_state);
2927 }
2928
2929 int PMPI_Keyval_free(int* keyval) {
2930   return smpi_comm_keyval_free(keyval);
2931 }
2932
2933 int PMPI_Attr_delete(MPI_Comm comm, int keyval) {
2934   if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
2935        ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE)
2936     return MPI_ERR_ARG;
2937   else if (comm==MPI_COMM_NULL)
2938     return MPI_ERR_COMM;
2939   else
2940     return smpi_comm_attr_delete(comm, keyval);
2941 }
2942
2943 int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
2944   static int one = 1;
2945   static int zero = 0;
2946   static int tag_ub = 1000000;
2947   static int last_used_code = MPI_ERR_LASTCODE;
2948
2949   if (comm==MPI_COMM_NULL){
2950     *flag = 0;
2951     return MPI_ERR_COMM;
2952   }
2953
2954   switch (keyval) {
2955   case MPI_HOST:
2956   case MPI_IO:
2957   case MPI_APPNUM:
2958     *flag = 1;
2959     *static_cast<int**>(attr_value) = &zero;
2960     return MPI_SUCCESS;
2961   case MPI_UNIVERSE_SIZE:
2962     *flag = 1;
2963     *static_cast<int**>(attr_value) = &smpi_universe_size;
2964     return MPI_SUCCESS;
2965   case MPI_LASTUSEDCODE:
2966     *flag = 1;
2967     *static_cast<int**>(attr_value) = &last_used_code;
2968     return MPI_SUCCESS;
2969   case MPI_TAG_UB:
2970     *flag=1;
2971     *static_cast<int**>(attr_value) = &tag_ub;
2972     return MPI_SUCCESS;
2973   case MPI_WTIME_IS_GLOBAL:
2974     *flag = 1;
2975     *static_cast<int**>(attr_value) = &one;
2976     return MPI_SUCCESS;
2977   default:
2978     return smpi_comm_attr_get(comm, keyval, attr_value, flag);
2979   }
2980 }
2981
2982 int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
2983   if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
2984        ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE)
2985     return MPI_ERR_ARG;
2986   else if (comm==MPI_COMM_NULL)
2987     return MPI_ERR_COMM;
2988   else
2989   return smpi_comm_attr_put(comm, keyval, attr_value);
2990 }
2991
2992 int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
2993 {
2994   return PMPI_Attr_get(comm, comm_keyval, attribute_val,flag);
2995 }
2996
2997 int PMPI_Comm_set_attr (MPI_Comm comm, int comm_keyval, void *attribute_val)
2998 {
2999   return PMPI_Attr_put(comm, comm_keyval, attribute_val);
3000 }
3001
3002 int PMPI_Comm_delete_attr (MPI_Comm comm, int comm_keyval)
3003 {
3004   return PMPI_Attr_delete(comm, comm_keyval);
3005 }
3006
3007 int PMPI_Comm_create_keyval(MPI_Comm_copy_attr_function* copy_fn, MPI_Comm_delete_attr_function* delete_fn, int* keyval,
3008                             void* extra_state)
3009 {
3010   return PMPI_Keyval_create(copy_fn, delete_fn, keyval, extra_state);
3011 }
3012
3013 int PMPI_Comm_free_keyval(int* keyval) {
3014   return PMPI_Keyval_free(keyval);
3015 }
3016
3017 int PMPI_Type_get_attr (MPI_Datatype type, int type_keyval, void *attribute_val, int* flag)
3018 {
3019   if (type==MPI_DATATYPE_NULL)
3020     return MPI_ERR_TYPE;
3021   else
3022     return smpi_type_attr_get(type, type_keyval, attribute_val, flag);
3023 }
3024
3025 int PMPI_Type_set_attr (MPI_Datatype type, int type_keyval, void *attribute_val)
3026 {
3027   if (type==MPI_DATATYPE_NULL)
3028     return MPI_ERR_TYPE;
3029   else
3030     return smpi_type_attr_put(type, type_keyval, attribute_val);
3031 }
3032
3033 int PMPI_Type_delete_attr (MPI_Datatype type, int type_keyval)
3034 {
3035   if (type==MPI_DATATYPE_NULL)
3036     return MPI_ERR_TYPE;
3037   else
3038     return smpi_type_attr_delete(type, type_keyval);
3039 }
3040
3041 int PMPI_Type_create_keyval(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval,
3042                             void* extra_state)
3043 {
3044   return smpi_type_keyval_create(copy_fn, delete_fn, keyval, extra_state);
3045 }
3046
3047 int PMPI_Type_free_keyval(int* keyval) {
3048   return smpi_type_keyval_free(keyval);
3049 }
3050
3051 int PMPI_Info_create( MPI_Info *info){
3052   if (info == nullptr)
3053     return MPI_ERR_ARG;
3054   *info = xbt_new(s_smpi_mpi_info_t, 1);
3055   (*info)->info_dict= xbt_dict_new_homogeneous(xbt_free_f);
3056   (*info)->refcount=1;
3057   return MPI_SUCCESS;
3058 }
3059
3060 int PMPI_Info_set( MPI_Info info, char *key, char *value){
3061   if (info == nullptr || key == nullptr || value == nullptr)
3062     return MPI_ERR_ARG;
3063
3064   xbt_dict_set(info->info_dict, key, xbt_strdup(value), nullptr);
3065   return MPI_SUCCESS;
3066 }
3067
3068 int PMPI_Info_free( MPI_Info *info){
3069   if (info == nullptr || *info==nullptr)
3070     return MPI_ERR_ARG;
3071   (*info)->refcount--;
3072   if((*info)->refcount==0){
3073     xbt_dict_free(&((*info)->info_dict));
3074     xbt_free(*info);
3075   }
3076   *info=MPI_INFO_NULL;
3077   return MPI_SUCCESS;
3078 }
3079
3080 int PMPI_Info_get(MPI_Info info,char *key,int valuelen, char *value, int *flag){
3081   *flag=false;
3082   if (info == nullptr || key == nullptr || valuelen <0)
3083     return MPI_ERR_ARG;
3084   if (value == nullptr)
3085     return MPI_ERR_INFO_VALUE;
3086   char* tmpvalue=static_cast<char*>(xbt_dict_get_or_null(info->info_dict, key));
3087   if(tmpvalue){
3088     memset(value, 0, valuelen);
3089     memcpy(value,tmpvalue, (strlen(tmpvalue) + 1 < static_cast<size_t>(valuelen)) ? strlen(tmpvalue) + 1 : valuelen);
3090     *flag=true;
3091   }
3092   return MPI_SUCCESS;
3093 }
3094
3095 int PMPI_Info_dup(MPI_Info info, MPI_Info *newinfo){
3096   if (info == nullptr || newinfo==nullptr)
3097     return MPI_ERR_ARG;
3098   *newinfo = xbt_new(s_smpi_mpi_info_t, 1);
3099   (*newinfo)->info_dict= xbt_dict_new_homogeneous(xbt_free_f);
3100   (*newinfo)->refcount=1;
3101   xbt_dict_cursor_t cursor = nullptr;
3102   int *key;
3103   void* data;
3104   xbt_dict_foreach(info->info_dict,cursor,key,data){
3105     xbt_dict_set((*newinfo)->info_dict, reinterpret_cast<char*>(key), xbt_strdup(reinterpret_cast<char*>(data)), nullptr);
3106   }
3107   return MPI_SUCCESS;
3108 }
3109
3110 int PMPI_Info_delete(MPI_Info info, char *key){
3111   if (info == nullptr || key==nullptr)
3112     return MPI_ERR_ARG;
3113   try {
3114     xbt_dict_remove(info->info_dict, key);
3115   }
3116   catch(xbt_ex& e){
3117     return MPI_ERR_INFO_NOKEY;
3118   }
3119   return MPI_SUCCESS;
3120 }
3121
3122 int PMPI_Info_get_nkeys( MPI_Info info, int *nkeys){
3123   if (info == nullptr || nkeys==nullptr)
3124     return MPI_ERR_ARG;
3125   *nkeys=xbt_dict_size(info->info_dict);
3126   return MPI_SUCCESS;
3127 }
3128
3129 int PMPI_Info_get_nthkey( MPI_Info info, int n, char *key){
3130   if (info == nullptr || key==nullptr || n<0 || n> MPI_MAX_INFO_KEY)
3131     return MPI_ERR_ARG;
3132
3133   xbt_dict_cursor_t cursor = nullptr;
3134   char *keyn;
3135   void* data;
3136   int num=0;
3137   xbt_dict_foreach(info->info_dict,cursor,keyn,data){
3138     if(num==n){
3139       strncpy(key,keyn,strlen(keyn)+1);
3140       xbt_dict_cursor_free(&cursor);
3141       return MPI_SUCCESS;
3142     }
3143     num++;
3144   }
3145   return MPI_ERR_ARG;
3146 }
3147
3148 int PMPI_Info_get_valuelen( MPI_Info info, char *key, int *valuelen, int *flag){
3149   *flag=false;
3150   if (info == nullptr || key == nullptr || valuelen==nullptr)
3151     return MPI_ERR_ARG;
3152   char* tmpvalue=(char*)xbt_dict_get_or_null(info->info_dict, key);
3153   if(tmpvalue){
3154     *valuelen=strlen(tmpvalue);
3155     *flag=true;
3156   }
3157   return MPI_SUCCESS;
3158 }
3159
3160 int PMPI_Unpack(void* inbuf, int incount, int* position, void* outbuf, int outcount, MPI_Datatype type, MPI_Comm comm) {
3161   if(incount<0 || outcount < 0 || inbuf==nullptr || outbuf==nullptr)
3162     return MPI_ERR_ARG;
3163   if(!is_datatype_valid(type))
3164     return MPI_ERR_TYPE;
3165   if(comm==MPI_COMM_NULL)
3166     return MPI_ERR_COMM;
3167   return smpi_mpi_unpack(inbuf, incount, position, outbuf,outcount,type, comm);
3168 }
3169
3170 int PMPI_Pack(void* inbuf, int incount, MPI_Datatype type, void* outbuf, int outcount, int* position, MPI_Comm comm) {
3171   if(incount<0 || outcount < 0|| inbuf==nullptr || outbuf==nullptr)
3172     return MPI_ERR_ARG;
3173   if(!is_datatype_valid(type))
3174     return MPI_ERR_TYPE;
3175   if(comm==MPI_COMM_NULL)
3176     return MPI_ERR_COMM;
3177   return smpi_mpi_pack(inbuf, incount, type, outbuf,outcount,position, comm);
3178 }
3179
3180 int PMPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, int* size) {
3181   if(incount<0)
3182     return MPI_ERR_ARG;
3183   if(!is_datatype_valid(datatype))
3184     return MPI_ERR_TYPE;
3185   if(comm==MPI_COMM_NULL)
3186     return MPI_ERR_COMM;
3187
3188   *size=incount*smpi_datatype_size(datatype);
3189
3190   return MPI_SUCCESS;
3191 }
3192
3193 } // extern "C"