Logo AND Algorithmique Numérique Distribuée

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