Logo AND Algorithmique Numérique Distribuée

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