Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
635e0d77df90ede109aada77ea0fc23a4881ab0f
[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 = 1;
2131     dt_size_send     = sendtmptype->size();
2132
2133     for (i = 0; i < size; i++) { // copy data to avoid bad free
2134       extra->send_size += sendtmpcounts[i] * dt_size_send;
2135       extra->sendcounts[i] = sendtmpcounts[i] * dt_size_send;
2136     }
2137     extra->num_processes = size;
2138     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, extra);
2139     retval = simgrid::smpi::Colls::alltoallv(sendtmpbuf, sendtmpcounts, sendtmpdisps, sendtmptype, recvbuf, recvcounts,
2140                                     recvdisps, recvtype, comm);
2141     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2142
2143     if (sendbuf == MPI_IN_PLACE) {
2144       xbt_free(sendtmpbuf);
2145       xbt_free(sendtmpcounts);
2146       xbt_free(sendtmpdisps);
2147     }
2148   }
2149
2150   smpi_bench_begin();
2151   return retval;
2152 }
2153
2154
2155 int PMPI_Get_processor_name(char *name, int *resultlen)
2156 {
2157   strncpy(name, SIMIX_host_self()->cname(), strlen(SIMIX_host_self()->cname()) < MPI_MAX_PROCESSOR_NAME - 1
2158                                                 ? strlen(SIMIX_host_self()->cname()) + 1
2159                                                 : MPI_MAX_PROCESSOR_NAME - 1);
2160   *resultlen = strlen(name) > MPI_MAX_PROCESSOR_NAME ? MPI_MAX_PROCESSOR_NAME : strlen(name);
2161
2162   return MPI_SUCCESS;
2163 }
2164
2165 int PMPI_Get_count(MPI_Status * status, MPI_Datatype datatype, int *count)
2166 {
2167   if (status == nullptr || count == nullptr) {
2168     return MPI_ERR_ARG;
2169   } else if (not datatype->is_valid()) {
2170     return MPI_ERR_TYPE;
2171   } else {
2172     size_t size = datatype->size();
2173     if (size == 0) {
2174       *count = 0;
2175       return MPI_SUCCESS;
2176     } else if (status->count % size != 0) {
2177       return MPI_UNDEFINED;
2178     } else {
2179       *count = simgrid::smpi::Status::get_count(status, datatype);
2180       return MPI_SUCCESS;
2181     }
2182   }
2183 }
2184
2185 int PMPI_Type_contiguous(int count, MPI_Datatype old_type, MPI_Datatype* new_type) {
2186   if (old_type == MPI_DATATYPE_NULL) {
2187     return MPI_ERR_TYPE;
2188   } else if (count<0){
2189     return MPI_ERR_COUNT;
2190   } else {
2191     return simgrid::smpi::Datatype::create_contiguous(count, old_type, 0, new_type);
2192   }
2193 }
2194
2195 int PMPI_Type_commit(MPI_Datatype* datatype) {
2196   if (datatype == nullptr || *datatype == MPI_DATATYPE_NULL) {
2197     return MPI_ERR_TYPE;
2198   } else {
2199     (*datatype)->commit();
2200     return MPI_SUCCESS;
2201   }
2202 }
2203
2204 int PMPI_Type_vector(int count, int blocklen, int stride, MPI_Datatype old_type, MPI_Datatype* new_type) {
2205   if (old_type == MPI_DATATYPE_NULL) {
2206     return MPI_ERR_TYPE;
2207   } else if (count<0 || blocklen<0){
2208     return MPI_ERR_COUNT;
2209   } else {
2210     return simgrid::smpi::Datatype::create_vector(count, blocklen, stride, old_type, new_type);
2211   }
2212 }
2213
2214 int PMPI_Type_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type) {
2215   if (old_type == MPI_DATATYPE_NULL) {
2216     return MPI_ERR_TYPE;
2217   } else if (count<0 || blocklen<0){
2218     return MPI_ERR_COUNT;
2219   } else {
2220     return simgrid::smpi::Datatype::create_hvector(count, blocklen, stride, old_type, new_type);
2221   }
2222 }
2223
2224 int PMPI_Type_create_hvector(int count, int blocklen, MPI_Aint stride, MPI_Datatype old_type, MPI_Datatype* new_type) {
2225   return MPI_Type_hvector(count, blocklen, stride, old_type, new_type);
2226 }
2227
2228 int PMPI_Type_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type) {
2229   if (old_type == MPI_DATATYPE_NULL) {
2230     return MPI_ERR_TYPE;
2231   } else if (count<0){
2232     return MPI_ERR_COUNT;
2233   } else {
2234     return simgrid::smpi::Datatype::create_indexed(count, blocklens, indices, old_type, new_type);
2235   }
2236 }
2237
2238 int PMPI_Type_create_indexed(int count, int* blocklens, int* indices, MPI_Datatype old_type, MPI_Datatype* new_type) {
2239   if (old_type == MPI_DATATYPE_NULL) {
2240     return MPI_ERR_TYPE;
2241   } else if (count<0){
2242     return MPI_ERR_COUNT;
2243   } else {
2244     return simgrid::smpi::Datatype::create_indexed(count, blocklens, indices, old_type, new_type);
2245   }
2246 }
2247
2248 int PMPI_Type_create_indexed_block(int count, int blocklength, int* indices, MPI_Datatype old_type,
2249                                    MPI_Datatype* new_type)
2250 {
2251   if (old_type == MPI_DATATYPE_NULL) {
2252     return MPI_ERR_TYPE;
2253   } else if (count<0){
2254     return MPI_ERR_COUNT;
2255   } else {
2256     int* blocklens=static_cast<int*>(xbt_malloc(blocklength*count*sizeof(int)));
2257     for (int i    = 0; i < count; i++)
2258       blocklens[i]=blocklength;
2259     int retval    = simgrid::smpi::Datatype::create_indexed(count, blocklens, indices, old_type, new_type);
2260     xbt_free(blocklens);
2261     return retval;
2262   }
2263 }
2264
2265 int PMPI_Type_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type, MPI_Datatype* new_type)
2266 {
2267   if (old_type == MPI_DATATYPE_NULL) {
2268     return MPI_ERR_TYPE;
2269   } else if (count<0){
2270     return MPI_ERR_COUNT;
2271   } else {
2272     return simgrid::smpi::Datatype::create_hindexed(count, blocklens, indices, old_type, new_type);
2273   }
2274 }
2275
2276 int PMPI_Type_create_hindexed(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype old_type,
2277                               MPI_Datatype* new_type) {
2278   return PMPI_Type_hindexed(count, blocklens,indices,old_type,new_type);
2279 }
2280
2281 int PMPI_Type_create_hindexed_block(int count, int blocklength, MPI_Aint* indices, MPI_Datatype old_type,
2282                                     MPI_Datatype* new_type) {
2283   if (old_type == MPI_DATATYPE_NULL) {
2284     return MPI_ERR_TYPE;
2285   } else if (count<0){
2286     return MPI_ERR_COUNT;
2287   } else {
2288     int* blocklens=(int*)xbt_malloc(blocklength*count*sizeof(int));
2289     for (int i     = 0; i < count; i++)
2290       blocklens[i] = blocklength;
2291     int retval     = simgrid::smpi::Datatype::create_hindexed(count, blocklens, indices, old_type, new_type);
2292     xbt_free(blocklens);
2293     return retval;
2294   }
2295 }
2296
2297 int PMPI_Type_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types, MPI_Datatype* new_type) {
2298   if (count<0){
2299     return MPI_ERR_COUNT;
2300   } else {
2301     return simgrid::smpi::Datatype::create_struct(count, blocklens, indices, old_types, new_type);
2302   }
2303 }
2304
2305 int PMPI_Type_create_struct(int count, int* blocklens, MPI_Aint* indices, MPI_Datatype* old_types,
2306                             MPI_Datatype* new_type) {
2307   return PMPI_Type_struct(count, blocklens, indices, old_types, new_type);
2308 }
2309
2310 int PMPI_Error_class(int errorcode, int* errorclass) {
2311   // assume smpi uses only standard mpi error codes
2312   *errorclass=errorcode;
2313   return MPI_SUCCESS;
2314 }
2315
2316 int PMPI_Initialized(int* flag) {
2317    *flag=(smpi_process()!=nullptr && smpi_process()->initialized());
2318    return MPI_SUCCESS;
2319 }
2320
2321 /* The topo part of MPI_COMM_WORLD should always be nullptr. When other topologies will be implemented, not only should we
2322  * check if the topology is nullptr, but we should check if it is the good topology type (so we have to add a
2323  *  MPIR_Topo_Type field, and replace the MPI_Topology field by an union)*/
2324
2325 int PMPI_Cart_create(MPI_Comm comm_old, int ndims, int* dims, int* periodic, int reorder, MPI_Comm* comm_cart) {
2326   if (comm_old == MPI_COMM_NULL){
2327     return MPI_ERR_COMM;
2328   } else if (ndims < 0 || (ndims > 0 && (dims == nullptr || periodic == nullptr)) || comm_cart == nullptr) {
2329     return MPI_ERR_ARG;
2330   } else{
2331     simgrid::smpi::Topo_Cart* topo = new simgrid::smpi::Topo_Cart(comm_old, ndims, dims, periodic, reorder, comm_cart);
2332     if(*comm_cart==MPI_COMM_NULL)
2333       delete topo;
2334     return MPI_SUCCESS;
2335   }
2336 }
2337
2338 int PMPI_Cart_rank(MPI_Comm comm, int* coords, int* rank) {
2339   if(comm == MPI_COMM_NULL || comm->topo() == nullptr) {
2340     return MPI_ERR_TOPOLOGY;
2341   }
2342   if (coords == nullptr) {
2343     return MPI_ERR_ARG;
2344   }
2345   MPIR_Cart_Topology topo = static_cast<MPIR_Cart_Topology>(comm->topo());
2346   if (topo==nullptr) {
2347     return MPI_ERR_ARG;
2348   }
2349   return topo->rank(coords, rank);
2350 }
2351
2352 int PMPI_Cart_shift(MPI_Comm comm, int direction, int displ, int* source, int* dest) {
2353   if(comm == MPI_COMM_NULL || comm->topo() == nullptr) {
2354     return MPI_ERR_TOPOLOGY;
2355   }
2356   if (source == nullptr || dest == nullptr || direction < 0 ) {
2357     return MPI_ERR_ARG;
2358   }
2359   MPIR_Cart_Topology topo = static_cast<MPIR_Cart_Topology>(comm->topo());
2360   if (topo==nullptr) {
2361     return MPI_ERR_ARG;
2362   }
2363   return topo->shift(direction, displ, source, dest);
2364 }
2365
2366 int PMPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int* coords) {
2367   if(comm == MPI_COMM_NULL || comm->topo() == nullptr) {
2368     return MPI_ERR_TOPOLOGY;
2369   }
2370   if (rank < 0 || rank >= comm->size()) {
2371     return MPI_ERR_RANK;
2372   }
2373   if (maxdims <= 0) {
2374     return MPI_ERR_ARG;
2375   }
2376   if(coords == nullptr) {
2377     return MPI_ERR_ARG;
2378   }
2379   MPIR_Cart_Topology topo = static_cast<MPIR_Cart_Topology>(comm->topo());
2380   if (topo==nullptr) {
2381     return MPI_ERR_ARG;
2382   }
2383   return topo->coords(rank, maxdims, coords);
2384 }
2385
2386 int PMPI_Cart_get(MPI_Comm comm, int maxdims, int* dims, int* periods, int* coords) {
2387   if(comm == nullptr || comm->topo() == nullptr) {
2388     return MPI_ERR_TOPOLOGY;
2389   }
2390   if(maxdims <= 0 || dims == nullptr || periods == nullptr || coords == nullptr) {
2391     return MPI_ERR_ARG;
2392   }
2393   MPIR_Cart_Topology topo = static_cast<MPIR_Cart_Topology>(comm->topo());
2394   if (topo==nullptr) {
2395     return MPI_ERR_ARG;
2396   }
2397   return topo->get(maxdims, dims, periods, coords);
2398 }
2399
2400 int PMPI_Cartdim_get(MPI_Comm comm, int* ndims) {
2401   if (comm == MPI_COMM_NULL || comm->topo() == nullptr) {
2402     return MPI_ERR_TOPOLOGY;
2403   }
2404   if (ndims == nullptr) {
2405     return MPI_ERR_ARG;
2406   }
2407   MPIR_Cart_Topology topo = static_cast<MPIR_Cart_Topology>(comm->topo());
2408   if (topo==nullptr) {
2409     return MPI_ERR_ARG;
2410   }
2411   return topo->dim_get(ndims);
2412 }
2413
2414 int PMPI_Dims_create(int nnodes, int ndims, int* dims) {
2415   if(dims == nullptr) {
2416     return MPI_ERR_ARG;
2417   }
2418   if (ndims < 1 || nnodes < 1) {
2419     return MPI_ERR_DIMS;
2420   }
2421   return simgrid::smpi::Topo_Cart::Dims_create(nnodes, ndims, dims);
2422 }
2423
2424 int PMPI_Cart_sub(MPI_Comm comm, int* remain_dims, MPI_Comm* comm_new) {
2425   if(comm == MPI_COMM_NULL || comm->topo() == nullptr) {
2426     return MPI_ERR_TOPOLOGY;
2427   }
2428   if (comm_new == nullptr) {
2429     return MPI_ERR_ARG;
2430   }
2431   MPIR_Cart_Topology topo = static_cast<MPIR_Cart_Topology>(comm->topo());
2432   if (topo==nullptr) {
2433     return MPI_ERR_ARG;
2434   }
2435   MPIR_Cart_Topology cart = topo->sub(remain_dims, comm_new);
2436   if(*comm_new==MPI_COMM_NULL)
2437       delete cart;
2438   if(cart==nullptr)
2439     return  MPI_ERR_ARG;
2440   return MPI_SUCCESS;
2441 }
2442
2443 int PMPI_Type_create_resized(MPI_Datatype oldtype,MPI_Aint lb, MPI_Aint extent, MPI_Datatype *newtype){
2444   if (oldtype == MPI_DATATYPE_NULL) {
2445     return MPI_ERR_TYPE;
2446   }
2447   int blocks[3]         = {1, 1, 1};
2448   MPI_Aint disps[3]     = {lb, 0, lb + extent};
2449   MPI_Datatype types[3] = {MPI_LB, oldtype, MPI_UB};
2450
2451   *newtype = new simgrid::smpi::Type_Struct(oldtype->size(), lb, lb + extent, DT_FLAG_DERIVED, 3, blocks, disps, types);
2452
2453   (*newtype)->addflag(~DT_FLAG_COMMITED);
2454   return MPI_SUCCESS;
2455 }
2456
2457 int PMPI_Win_create( void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win){
2458   int retval = 0;
2459   smpi_bench_end();
2460   if (comm == MPI_COMM_NULL) {
2461     retval= MPI_ERR_COMM;
2462   }else if ((base == nullptr && size != 0) || disp_unit <= 0 || size < 0 ){
2463     retval= MPI_ERR_OTHER;
2464   }else{
2465     *win = new simgrid::smpi::Win( base, size, disp_unit, info, comm);
2466     retval = MPI_SUCCESS;
2467   }
2468   smpi_bench_begin();
2469   return retval;
2470 }
2471
2472 int PMPI_Win_allocate( MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, void *base, MPI_Win *win){
2473   int retval = 0;
2474   smpi_bench_end();
2475   if (comm == MPI_COMM_NULL) {
2476     retval= MPI_ERR_COMM;
2477   }else if (disp_unit <= 0 || size < 0 ){
2478     retval= MPI_ERR_OTHER;
2479   }else{
2480     void* ptr = xbt_malloc(size);
2481     if(ptr==nullptr)
2482       return MPI_ERR_NO_MEM;
2483     *static_cast<void**>(base) = ptr;
2484     *win = new simgrid::smpi::Win( ptr, size, disp_unit, info, comm,1);
2485     retval = MPI_SUCCESS;
2486   }
2487   smpi_bench_begin();
2488   return retval;
2489 }
2490
2491 int PMPI_Win_create_dynamic( MPI_Info info, MPI_Comm comm, MPI_Win *win){
2492   int retval = 0;
2493   smpi_bench_end();
2494   if (comm == MPI_COMM_NULL) {
2495     retval= MPI_ERR_COMM;
2496   }else{
2497     *win = new simgrid::smpi::Win(info, comm);
2498     retval = MPI_SUCCESS;
2499   }
2500   smpi_bench_begin();
2501   return retval;
2502 }
2503
2504 int PMPI_Win_attach(MPI_Win win, void *base, MPI_Aint size){
2505   int retval = 0;
2506   smpi_bench_end();
2507   if(win == MPI_WIN_NULL){
2508     retval = MPI_ERR_WIN;
2509   } else if ((base == nullptr && size != 0) || size < 0 ){
2510     retval= MPI_ERR_OTHER;
2511   }else{
2512     retval = win->attach(base, size);
2513   }
2514   smpi_bench_begin();
2515   return retval;
2516 }
2517
2518 int PMPI_Win_detach(MPI_Win win,  void *base){
2519   int retval = 0;
2520   smpi_bench_end();
2521   if(win == MPI_WIN_NULL){
2522     retval = MPI_ERR_WIN;
2523   } else if (base == nullptr){
2524     retval= MPI_ERR_OTHER;
2525   }else{
2526     retval = win->detach(base);
2527   }
2528   smpi_bench_begin();
2529   return retval;
2530 }
2531
2532
2533 int PMPI_Win_free( MPI_Win* win){
2534   int retval = 0;
2535   smpi_bench_end();
2536   if (win == nullptr || *win == MPI_WIN_NULL) {
2537     retval = MPI_ERR_WIN;
2538   }else{
2539     delete *win;
2540     retval=MPI_SUCCESS;
2541   }
2542   smpi_bench_begin();
2543   return retval;
2544 }
2545
2546 int PMPI_Win_set_name(MPI_Win  win, char * name)
2547 {
2548   if (win == MPI_WIN_NULL)  {
2549     return MPI_ERR_TYPE;
2550   } else if (name == nullptr)  {
2551     return MPI_ERR_ARG;
2552   } else {
2553     win->set_name(name);
2554     return MPI_SUCCESS;
2555   }
2556 }
2557
2558 int PMPI_Win_get_name(MPI_Win  win, char * name, int* len)
2559 {
2560   if (win == MPI_WIN_NULL)  {
2561     return MPI_ERR_WIN;
2562   } else if (name == nullptr)  {
2563     return MPI_ERR_ARG;
2564   } else {
2565     win->get_name(name, len);
2566     return MPI_SUCCESS;
2567   }
2568 }
2569
2570 int PMPI_Win_get_info(MPI_Win  win, MPI_Info* info)
2571 {
2572   if (win == MPI_WIN_NULL)  {
2573     return MPI_ERR_WIN;
2574   } else {
2575     *info = win->info();
2576     return MPI_SUCCESS;
2577   }
2578 }
2579
2580 int PMPI_Win_set_info(MPI_Win  win, MPI_Info info)
2581 {
2582   if (win == MPI_WIN_NULL)  {
2583     return MPI_ERR_TYPE;
2584   } else {
2585     win->set_info(info);
2586     return MPI_SUCCESS;
2587   }
2588 }
2589
2590 int PMPI_Win_get_group(MPI_Win  win, MPI_Group * group){
2591   if (win == MPI_WIN_NULL)  {
2592     return MPI_ERR_WIN;
2593   }else {
2594     win->get_group(group);
2595     (*group)->ref();
2596     return MPI_SUCCESS;
2597   }
2598 }
2599
2600 int PMPI_Win_fence( int assert,  MPI_Win win){
2601   int retval = 0;
2602   smpi_bench_end();
2603   if (win == MPI_WIN_NULL) {
2604     retval = MPI_ERR_WIN;
2605   } else {
2606   int rank = smpi_process()->index();
2607   TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2608   retval = win->fence(assert);
2609   TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2610   }
2611   smpi_bench_begin();
2612   return retval;
2613 }
2614
2615 int PMPI_Get( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2616               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win){
2617   int retval = 0;
2618   smpi_bench_end();
2619   if (win == MPI_WIN_NULL) {
2620     retval = MPI_ERR_WIN;
2621   } else if (target_rank == MPI_PROC_NULL) {
2622     retval = MPI_SUCCESS;
2623   } else if (target_rank <0){
2624     retval = MPI_ERR_RANK;
2625   } else if (win->dynamic()==0 && target_disp <0){
2626     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2627     retval = MPI_ERR_ARG;
2628   } else if ((origin_count < 0 || target_count < 0) ||
2629              (origin_addr==nullptr && origin_count > 0)){
2630     retval = MPI_ERR_COUNT;
2631   } else if ((not origin_datatype->is_valid()) || (not target_datatype->is_valid())) {
2632     retval = MPI_ERR_TYPE;
2633   } else {
2634     int rank = smpi_process()->index();
2635     MPI_Group group;
2636     win->get_group(&group);
2637     int src_traced = group->index(target_rank);
2638     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2639
2640     retval = win->get( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2641                            target_datatype);
2642
2643     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2644   }
2645   smpi_bench_begin();
2646   return retval;
2647 }
2648
2649 int PMPI_Rget( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2650               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win, MPI_Request* request){
2651   int retval = 0;
2652   smpi_bench_end();
2653   if (win == MPI_WIN_NULL) {
2654     retval = MPI_ERR_WIN;
2655   } else if (target_rank == MPI_PROC_NULL) {
2656     *request = MPI_REQUEST_NULL;
2657     retval = MPI_SUCCESS;
2658   } else if (target_rank <0){
2659     retval = MPI_ERR_RANK;
2660   } else if (win->dynamic()==0 && target_disp <0){
2661     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2662     retval = MPI_ERR_ARG;
2663   } else if ((origin_count < 0 || target_count < 0) ||
2664              (origin_addr==nullptr && origin_count > 0)){
2665     retval = MPI_ERR_COUNT;
2666   } else if ((not origin_datatype->is_valid()) || (not target_datatype->is_valid())) {
2667     retval = MPI_ERR_TYPE;
2668   } else if(request == nullptr){
2669     retval = MPI_ERR_REQUEST;
2670   } else {
2671     int rank = smpi_process()->index();
2672     MPI_Group group;
2673     win->get_group(&group);
2674     int src_traced = group->index(target_rank);
2675     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2676
2677     retval = win->get( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2678                            target_datatype, request);
2679
2680     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2681   }
2682   smpi_bench_begin();
2683   return retval;
2684 }
2685
2686 int PMPI_Put( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2687               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win){
2688   int retval = 0;
2689   smpi_bench_end();
2690   if (win == MPI_WIN_NULL) {
2691     retval = MPI_ERR_WIN;
2692   } else if (target_rank == MPI_PROC_NULL) {
2693     retval = MPI_SUCCESS;
2694   } else if (target_rank <0){
2695     retval = MPI_ERR_RANK;
2696   } else if (win->dynamic()==0 && target_disp <0){
2697     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2698     retval = MPI_ERR_ARG;
2699   } else if ((origin_count < 0 || target_count < 0) ||
2700             (origin_addr==nullptr && origin_count > 0)){
2701     retval = MPI_ERR_COUNT;
2702   } else if ((not origin_datatype->is_valid()) || (not target_datatype->is_valid())) {
2703     retval = MPI_ERR_TYPE;
2704   } else {
2705     int rank = smpi_process()->index();
2706     MPI_Group group;
2707     win->get_group(&group);
2708     int dst_traced = group->index(target_rank);
2709     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, nullptr);
2710     TRACE_smpi_send(rank, rank, dst_traced, SMPI_RMA_TAG, origin_count*origin_datatype->size());
2711
2712     retval = win->put( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2713                            target_datatype);
2714
2715     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
2716   }
2717   smpi_bench_begin();
2718   return retval;
2719 }
2720
2721 int PMPI_Rput( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2722               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win, MPI_Request* request){
2723   int retval = 0;
2724   smpi_bench_end();
2725   if (win == MPI_WIN_NULL) {
2726     retval = MPI_ERR_WIN;
2727   } else if (target_rank == MPI_PROC_NULL) {
2728     *request = MPI_REQUEST_NULL;
2729     retval = MPI_SUCCESS;
2730   } else if (target_rank <0){
2731     retval = MPI_ERR_RANK;
2732   } else if (win->dynamic()==0 && target_disp <0){
2733     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2734     retval = MPI_ERR_ARG;
2735   } else if ((origin_count < 0 || target_count < 0) ||
2736             (origin_addr==nullptr && origin_count > 0)){
2737     retval = MPI_ERR_COUNT;
2738   } else if ((not origin_datatype->is_valid()) || (not target_datatype->is_valid())) {
2739     retval = MPI_ERR_TYPE;
2740   } else if(request == nullptr){
2741     retval = MPI_ERR_REQUEST;
2742   } else {
2743     int rank = smpi_process()->index();
2744     MPI_Group group;
2745     win->get_group(&group);
2746     int dst_traced = group->index(target_rank);
2747     TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__, nullptr);
2748     TRACE_smpi_send(rank, rank, dst_traced, SMPI_RMA_TAG, origin_count*origin_datatype->size());
2749
2750     retval = win->put( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2751                            target_datatype, request);
2752
2753     TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__);
2754   }
2755   smpi_bench_begin();
2756   return retval;
2757 }
2758
2759 int PMPI_Accumulate( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2760               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win){
2761   int retval = 0;
2762   smpi_bench_end();
2763   if (win == MPI_WIN_NULL) {
2764     retval = MPI_ERR_WIN;
2765   } else if (target_rank == MPI_PROC_NULL) {
2766     retval = MPI_SUCCESS;
2767   } else if (target_rank <0){
2768     retval = MPI_ERR_RANK;
2769   } else if (win->dynamic()==0 && target_disp <0){
2770     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2771     retval = MPI_ERR_ARG;
2772   } else if ((origin_count < 0 || target_count < 0) ||
2773              (origin_addr==nullptr && origin_count > 0)){
2774     retval = MPI_ERR_COUNT;
2775   } else if ((not origin_datatype->is_valid()) || (not target_datatype->is_valid())) {
2776     retval = MPI_ERR_TYPE;
2777   } else if (op == MPI_OP_NULL) {
2778     retval = MPI_ERR_OP;
2779   } else {
2780     int rank = smpi_process()->index();
2781     MPI_Group group;
2782     win->get_group(&group);
2783     int src_traced = group->index(target_rank);
2784     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2785
2786     retval = win->accumulate( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2787                                   target_datatype, op);
2788
2789     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2790   }
2791   smpi_bench_begin();
2792   return retval;
2793 }
2794
2795 int PMPI_Raccumulate( void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank,
2796               MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request* request){
2797   int retval = 0;
2798   smpi_bench_end();
2799   if (win == MPI_WIN_NULL) {
2800     retval = MPI_ERR_WIN;
2801   } else if (target_rank == MPI_PROC_NULL) {
2802     *request = MPI_REQUEST_NULL;
2803     retval = MPI_SUCCESS;
2804   } else if (target_rank <0){
2805     retval = MPI_ERR_RANK;
2806   } else if (win->dynamic()==0 && target_disp <0){
2807     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2808     retval = MPI_ERR_ARG;
2809   } else if ((origin_count < 0 || target_count < 0) ||
2810              (origin_addr==nullptr && origin_count > 0)){
2811     retval = MPI_ERR_COUNT;
2812   } else if ((not origin_datatype->is_valid()) || (not target_datatype->is_valid())) {
2813     retval = MPI_ERR_TYPE;
2814   } else if (op == MPI_OP_NULL) {
2815     retval = MPI_ERR_OP;
2816   } else if(request == nullptr){
2817     retval = MPI_ERR_REQUEST;
2818   } else {
2819     int rank = smpi_process()->index();
2820     MPI_Group group;
2821     win->get_group(&group);
2822     int src_traced = group->index(target_rank);
2823     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2824
2825     retval = win->accumulate( origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count,
2826                                   target_datatype, op, request);
2827
2828     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2829   }
2830   smpi_bench_begin();
2831   return retval;
2832 }
2833
2834 int PMPI_Get_accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, void *result_addr,
2835 int result_count, MPI_Datatype result_datatype, int target_rank, MPI_Aint target_disp, int target_count,
2836 MPI_Datatype target_datatype, MPI_Op op, MPI_Win win){
2837   int retval = 0;
2838   smpi_bench_end();
2839   if (win == MPI_WIN_NULL) {
2840     retval = MPI_ERR_WIN;
2841   } else if (target_rank == MPI_PROC_NULL) {
2842     retval = MPI_SUCCESS;
2843   } else if (target_rank <0){
2844     retval = MPI_ERR_RANK;
2845   } else if (win->dynamic()==0 && target_disp <0){
2846     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2847     retval = MPI_ERR_ARG;
2848   } else if ((origin_count < 0 || target_count < 0 || result_count <0) ||
2849              (origin_addr==nullptr && origin_count > 0 && op != MPI_NO_OP) ||
2850              (result_addr==nullptr && result_count > 0)){
2851     retval = MPI_ERR_COUNT;
2852   } else if ((origin_datatype != MPI_DATATYPE_NULL && not origin_datatype->is_valid()) ||
2853              (not target_datatype->is_valid()) || (not result_datatype->is_valid())) {
2854     retval = MPI_ERR_TYPE;
2855   } else if (op == MPI_OP_NULL) {
2856     retval = MPI_ERR_OP;
2857   } else {
2858     int rank = smpi_process()->index();
2859     MPI_Group group;
2860     win->get_group(&group);
2861     int src_traced = group->index(target_rank);
2862     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2863
2864     retval = win->get_accumulate( origin_addr, origin_count, origin_datatype, result_addr,
2865                                   result_count, result_datatype, target_rank, target_disp,
2866                                   target_count, target_datatype, op);
2867
2868     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2869   }
2870   smpi_bench_begin();
2871   return retval;
2872 }
2873
2874
2875 int PMPI_Rget_accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, void *result_addr,
2876 int result_count, MPI_Datatype result_datatype, int target_rank, MPI_Aint target_disp, int target_count,
2877 MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request* request){
2878   int retval = 0;
2879   smpi_bench_end();
2880   if (win == MPI_WIN_NULL) {
2881     retval = MPI_ERR_WIN;
2882   } else if (target_rank == MPI_PROC_NULL) {
2883     *request = MPI_REQUEST_NULL;
2884     retval = MPI_SUCCESS;
2885   } else if (target_rank <0){
2886     retval = MPI_ERR_RANK;
2887   } else if (win->dynamic()==0 && target_disp <0){
2888     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2889     retval = MPI_ERR_ARG;
2890   } else if ((origin_count < 0 || target_count < 0 || result_count <0) ||
2891              (origin_addr==nullptr && origin_count > 0 && op != MPI_NO_OP) ||
2892              (result_addr==nullptr && result_count > 0)){
2893     retval = MPI_ERR_COUNT;
2894   } else if ((origin_datatype != MPI_DATATYPE_NULL && not origin_datatype->is_valid()) ||
2895              (not target_datatype->is_valid()) || (not result_datatype->is_valid())) {
2896     retval = MPI_ERR_TYPE;
2897   } else if (op == MPI_OP_NULL) {
2898     retval = MPI_ERR_OP;
2899   } else if(request == nullptr){
2900     retval = MPI_ERR_REQUEST;
2901   } else {
2902     int rank = smpi_process()->index();
2903     MPI_Group group;
2904     win->get_group(&group);
2905     int src_traced = group->index(target_rank);
2906     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2907
2908     retval = win->get_accumulate( origin_addr, origin_count, origin_datatype, result_addr,
2909                                   result_count, result_datatype, target_rank, target_disp,
2910                                   target_count, target_datatype, op, request);
2911
2912     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2913   }
2914   smpi_bench_begin();
2915   return retval;
2916 }
2917
2918 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){
2919   return PMPI_Get_accumulate(origin_addr, origin_addr==nullptr?0:1, dtype, result_addr, 1, dtype, target_rank, target_disp, 1, dtype, op, win);
2920 }
2921
2922 int PMPI_Compare_and_swap(void *origin_addr, void *compare_addr,
2923         void *result_addr, MPI_Datatype datatype, int target_rank,
2924         MPI_Aint target_disp, MPI_Win win){
2925   int retval = 0;
2926   smpi_bench_end();
2927   if (win == MPI_WIN_NULL) {
2928     retval = MPI_ERR_WIN;
2929   } else if (target_rank == MPI_PROC_NULL) {
2930     retval = MPI_SUCCESS;
2931   } else if (target_rank <0){
2932     retval = MPI_ERR_RANK;
2933   } else if (win->dynamic()==0 && target_disp <0){
2934     //in case of dynamic window, target_disp can be mistakenly seen as negative, as it is an address
2935     retval = MPI_ERR_ARG;
2936   } else if (origin_addr==nullptr || result_addr==nullptr || compare_addr==nullptr){
2937     retval = MPI_ERR_COUNT;
2938   } else if (not datatype->is_valid()) {
2939     retval = MPI_ERR_TYPE;
2940   } else {
2941     int rank = smpi_process()->index();
2942     MPI_Group group;
2943     win->get_group(&group);
2944     int src_traced = group->index(target_rank);
2945     TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__, nullptr);
2946
2947     retval = win->compare_and_swap( origin_addr, compare_addr, result_addr, datatype,
2948                                   target_rank, target_disp);
2949
2950     TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__);
2951   }
2952   smpi_bench_begin();
2953   return retval;
2954 }
2955
2956 int PMPI_Win_post(MPI_Group group, int assert, MPI_Win win){
2957   int retval = 0;
2958   smpi_bench_end();
2959   if (win == MPI_WIN_NULL) {
2960     retval = MPI_ERR_WIN;
2961   } else if (group==MPI_GROUP_NULL){
2962     retval = MPI_ERR_GROUP;
2963   } else {
2964     int rank = smpi_process()->index();
2965     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2966     retval = win->post(group,assert);
2967     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2968   }
2969   smpi_bench_begin();
2970   return retval;
2971 }
2972
2973 int PMPI_Win_start(MPI_Group group, int assert, MPI_Win win){
2974   int retval = 0;
2975   smpi_bench_end();
2976   if (win == MPI_WIN_NULL) {
2977     retval = MPI_ERR_WIN;
2978   } else if (group==MPI_GROUP_NULL){
2979     retval = MPI_ERR_GROUP;
2980   } else {
2981     int rank = smpi_process()->index();
2982     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2983     retval = win->start(group,assert);
2984     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
2985   }
2986   smpi_bench_begin();
2987   return retval;
2988 }
2989
2990 int PMPI_Win_complete(MPI_Win win){
2991   int retval = 0;
2992   smpi_bench_end();
2993   if (win == MPI_WIN_NULL) {
2994     retval = MPI_ERR_WIN;
2995   } else {
2996     int rank = smpi_process()->index();
2997     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
2998
2999     retval = win->complete();
3000
3001     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
3002   }
3003   smpi_bench_begin();
3004   return retval;
3005 }
3006
3007 int PMPI_Win_wait(MPI_Win win){
3008   int retval = 0;
3009   smpi_bench_end();
3010   if (win == MPI_WIN_NULL) {
3011     retval = MPI_ERR_WIN;
3012   } else {
3013     int rank = smpi_process()->index();
3014     TRACE_smpi_collective_in(rank, -1, __FUNCTION__, nullptr);
3015
3016     retval = win->wait();
3017
3018     TRACE_smpi_collective_out(rank, -1, __FUNCTION__);
3019   }
3020   smpi_bench_begin();
3021   return retval;
3022 }
3023
3024 int PMPI_Win_lock(int lock_type, int rank, int assert, MPI_Win win){
3025   int retval = 0;
3026   smpi_bench_end();
3027   if (win == MPI_WIN_NULL) {
3028     retval = MPI_ERR_WIN;
3029   } else if (lock_type != MPI_LOCK_EXCLUSIVE &&
3030              lock_type != MPI_LOCK_SHARED) {
3031     retval = MPI_ERR_LOCKTYPE;
3032   } else if (rank == MPI_PROC_NULL){
3033     retval = MPI_SUCCESS;
3034   } else {
3035     int myrank = smpi_process()->index();
3036     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3037     retval = win->lock(lock_type,rank,assert);
3038     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3039   }
3040   smpi_bench_begin();
3041   return retval;
3042 }
3043
3044 int PMPI_Win_unlock(int rank, MPI_Win win){
3045   int retval = 0;
3046   smpi_bench_end();
3047   if (win == MPI_WIN_NULL) {
3048     retval = MPI_ERR_WIN;
3049   } else if (rank == MPI_PROC_NULL){
3050     retval = MPI_SUCCESS;
3051   } else {
3052     int myrank = smpi_process()->index();
3053     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3054     retval = win->unlock(rank);
3055     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3056   }
3057   smpi_bench_begin();
3058   return retval;
3059 }
3060
3061 int PMPI_Win_lock_all(int assert, MPI_Win win){
3062   int retval = 0;
3063   smpi_bench_end();
3064   if (win == MPI_WIN_NULL) {
3065     retval = MPI_ERR_WIN;
3066   } else {
3067     int myrank = smpi_process()->index();
3068     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3069     retval = win->lock_all(assert);
3070     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3071   }
3072   smpi_bench_begin();
3073   return retval;
3074 }
3075
3076 int PMPI_Win_unlock_all(MPI_Win win){
3077   int retval = 0;
3078   smpi_bench_end();
3079   if (win == MPI_WIN_NULL) {
3080     retval = MPI_ERR_WIN;
3081   } else {
3082     int myrank = smpi_process()->index();
3083     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3084     retval = win->unlock_all();
3085     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3086   }
3087   smpi_bench_begin();
3088   return retval;
3089 }
3090
3091 int PMPI_Win_flush(int rank, MPI_Win win){
3092   int retval = 0;
3093   smpi_bench_end();
3094   if (win == MPI_WIN_NULL) {
3095     retval = MPI_ERR_WIN;
3096   } else if (rank == MPI_PROC_NULL){
3097     retval = MPI_SUCCESS;
3098   } else {
3099     int myrank = smpi_process()->index();
3100     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3101     retval = win->flush(rank);
3102     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3103   }
3104   smpi_bench_begin();
3105   return retval;
3106 }
3107
3108 int PMPI_Win_flush_local(int rank, MPI_Win win){
3109   int retval = 0;
3110   smpi_bench_end();
3111   if (win == MPI_WIN_NULL) {
3112     retval = MPI_ERR_WIN;
3113   } else if (rank == MPI_PROC_NULL){
3114     retval = MPI_SUCCESS;
3115   } else {
3116     int myrank = smpi_process()->index();
3117     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3118     retval = win->flush_local(rank);
3119     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3120   }
3121   smpi_bench_begin();
3122   return retval;
3123 }
3124
3125 int PMPI_Win_flush_all(MPI_Win win){
3126   int retval = 0;
3127   smpi_bench_end();
3128   if (win == MPI_WIN_NULL) {
3129     retval = MPI_ERR_WIN;
3130   } else {
3131     int myrank = smpi_process()->index();
3132     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3133     retval = win->flush_all();
3134     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3135   }
3136   smpi_bench_begin();
3137   return retval;
3138 }
3139
3140 int PMPI_Win_flush_local_all(MPI_Win win){
3141   int retval = 0;
3142   smpi_bench_end();
3143   if (win == MPI_WIN_NULL) {
3144     retval = MPI_ERR_WIN;
3145   } else {
3146     int myrank = smpi_process()->index();
3147     TRACE_smpi_collective_in(myrank, -1, __FUNCTION__, nullptr);
3148     retval = win->flush_local_all();
3149     TRACE_smpi_collective_out(myrank, -1, __FUNCTION__);
3150   }
3151   smpi_bench_begin();
3152   return retval;
3153 }
3154
3155 int PMPI_Alloc_mem(MPI_Aint size, MPI_Info info, void *baseptr){
3156   void *ptr = xbt_malloc(size);
3157   if(ptr==nullptr)
3158     return MPI_ERR_NO_MEM;
3159   else {
3160     *static_cast<void**>(baseptr) = ptr;
3161     return MPI_SUCCESS;
3162   }
3163 }
3164
3165 int PMPI_Free_mem(void *baseptr){
3166   xbt_free(baseptr);
3167   return MPI_SUCCESS;
3168 }
3169
3170 int PMPI_Type_set_name(MPI_Datatype  datatype, char * name)
3171 {
3172   if (datatype == MPI_DATATYPE_NULL)  {
3173     return MPI_ERR_TYPE;
3174   } else if (name == nullptr)  {
3175     return MPI_ERR_ARG;
3176   } else {
3177     datatype->set_name(name);
3178     return MPI_SUCCESS;
3179   }
3180 }
3181
3182 int PMPI_Type_get_name(MPI_Datatype  datatype, char * name, int* len)
3183 {
3184   if (datatype == MPI_DATATYPE_NULL)  {
3185     return MPI_ERR_TYPE;
3186   } else if (name == nullptr)  {
3187     return MPI_ERR_ARG;
3188   } else {
3189     datatype->get_name(name, len);
3190     return MPI_SUCCESS;
3191   }
3192 }
3193
3194 MPI_Datatype PMPI_Type_f2c(MPI_Fint datatype){
3195   return static_cast<MPI_Datatype>(simgrid::smpi::F2C::f2c(datatype));
3196 }
3197
3198 MPI_Fint PMPI_Type_c2f(MPI_Datatype datatype){
3199   return datatype->c2f();
3200 }
3201
3202 MPI_Group PMPI_Group_f2c(MPI_Fint group){
3203   return simgrid::smpi::Group::f2c(group);
3204 }
3205
3206 MPI_Fint PMPI_Group_c2f(MPI_Group group){
3207   return group->c2f();
3208 }
3209
3210 MPI_Request PMPI_Request_f2c(MPI_Fint request){
3211   return static_cast<MPI_Request>(simgrid::smpi::Request::f2c(request));
3212 }
3213
3214 MPI_Fint PMPI_Request_c2f(MPI_Request request) {
3215   return request->c2f();
3216 }
3217
3218 MPI_Win PMPI_Win_f2c(MPI_Fint win){
3219   return static_cast<MPI_Win>(simgrid::smpi::Win::f2c(win));
3220 }
3221
3222 MPI_Fint PMPI_Win_c2f(MPI_Win win){
3223   return win->c2f();
3224 }
3225
3226 MPI_Op PMPI_Op_f2c(MPI_Fint op){
3227   return static_cast<MPI_Op>(simgrid::smpi::Op::f2c(op));
3228 }
3229
3230 MPI_Fint PMPI_Op_c2f(MPI_Op op){
3231   return op->c2f();
3232 }
3233
3234 MPI_Comm PMPI_Comm_f2c(MPI_Fint comm){
3235   return static_cast<MPI_Comm>(simgrid::smpi::Comm::f2c(comm));
3236 }
3237
3238 MPI_Fint PMPI_Comm_c2f(MPI_Comm comm){
3239   return comm->c2f();
3240 }
3241
3242 MPI_Info PMPI_Info_f2c(MPI_Fint info){
3243   return static_cast<MPI_Info>(simgrid::smpi::Info::f2c(info));
3244 }
3245
3246 MPI_Fint PMPI_Info_c2f(MPI_Info info){
3247   return info->c2f();
3248 }
3249
3250 int PMPI_Keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state) {
3251   smpi_copy_fn _copy_fn={copy_fn,nullptr,nullptr};
3252   smpi_delete_fn _delete_fn={delete_fn,nullptr,nullptr};
3253   return simgrid::smpi::Keyval::keyval_create<simgrid::smpi::Comm>(_copy_fn, _delete_fn, keyval, extra_state);
3254 }
3255
3256 int PMPI_Keyval_free(int* keyval) {
3257   return simgrid::smpi::Keyval::keyval_free<simgrid::smpi::Comm>(keyval);
3258 }
3259
3260 int PMPI_Attr_delete(MPI_Comm comm, int keyval) {
3261   if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
3262        ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE)
3263     return MPI_ERR_ARG;
3264   else if (comm==MPI_COMM_NULL)
3265     return MPI_ERR_COMM;
3266   else
3267     return comm->attr_delete<simgrid::smpi::Comm>(keyval);
3268 }
3269
3270 int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
3271   static int one = 1;
3272   static int zero = 0;
3273   static int tag_ub = INT_MAX;
3274   static int last_used_code = MPI_ERR_LASTCODE;
3275
3276   if (comm==MPI_COMM_NULL){
3277     *flag = 0;
3278     return MPI_ERR_COMM;
3279   }
3280
3281   switch (keyval) {
3282   case MPI_HOST:
3283   case MPI_IO:
3284   case MPI_APPNUM:
3285     *flag = 1;
3286     *static_cast<int**>(attr_value) = &zero;
3287     return MPI_SUCCESS;
3288   case MPI_UNIVERSE_SIZE:
3289     *flag = 1;
3290     *static_cast<int**>(attr_value) = &smpi_universe_size;
3291     return MPI_SUCCESS;
3292   case MPI_LASTUSEDCODE:
3293     *flag = 1;
3294     *static_cast<int**>(attr_value) = &last_used_code;
3295     return MPI_SUCCESS;
3296   case MPI_TAG_UB:
3297     *flag=1;
3298     *static_cast<int**>(attr_value) = &tag_ub;
3299     return MPI_SUCCESS;
3300   case MPI_WTIME_IS_GLOBAL:
3301     *flag = 1;
3302     *static_cast<int**>(attr_value) = &one;
3303     return MPI_SUCCESS;
3304   default:
3305     return comm->attr_get<simgrid::smpi::Comm>(keyval, attr_value, flag);
3306   }
3307 }
3308
3309 int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
3310   if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
3311        ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE)
3312     return MPI_ERR_ARG;
3313   else if (comm==MPI_COMM_NULL)
3314     return MPI_ERR_COMM;
3315   else
3316   return comm->attr_put<simgrid::smpi::Comm>(keyval, attr_value);
3317 }
3318
3319 int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
3320 {
3321   return PMPI_Attr_get(comm, comm_keyval, attribute_val,flag);
3322 }
3323
3324 int PMPI_Comm_set_attr (MPI_Comm comm, int comm_keyval, void *attribute_val)
3325 {
3326   return PMPI_Attr_put(comm, comm_keyval, attribute_val);
3327 }
3328
3329 int PMPI_Comm_delete_attr (MPI_Comm comm, int comm_keyval)
3330 {
3331   return PMPI_Attr_delete(comm, comm_keyval);
3332 }
3333
3334 int PMPI_Comm_create_keyval(MPI_Comm_copy_attr_function* copy_fn, MPI_Comm_delete_attr_function* delete_fn, int* keyval,
3335                             void* extra_state)
3336 {
3337   return PMPI_Keyval_create(copy_fn, delete_fn, keyval, extra_state);
3338 }
3339
3340 int PMPI_Comm_free_keyval(int* keyval) {
3341   return PMPI_Keyval_free(keyval);
3342 }
3343
3344 int PMPI_Type_get_attr (MPI_Datatype type, int type_keyval, void *attribute_val, int* flag)
3345 {
3346   if (type==MPI_DATATYPE_NULL)
3347     return MPI_ERR_TYPE;
3348   else
3349     return type->attr_get<simgrid::smpi::Datatype>(type_keyval, attribute_val, flag);
3350 }
3351
3352 int PMPI_Type_set_attr (MPI_Datatype type, int type_keyval, void *attribute_val)
3353 {
3354   if (type==MPI_DATATYPE_NULL)
3355     return MPI_ERR_TYPE;
3356   else
3357     return type->attr_put<simgrid::smpi::Datatype>(type_keyval, attribute_val);
3358 }
3359
3360 int PMPI_Type_delete_attr (MPI_Datatype type, int type_keyval)
3361 {
3362   if (type==MPI_DATATYPE_NULL)
3363     return MPI_ERR_TYPE;
3364   else
3365     return type->attr_delete<simgrid::smpi::Datatype>(type_keyval);
3366 }
3367
3368 int PMPI_Type_create_keyval(MPI_Type_copy_attr_function* copy_fn, MPI_Type_delete_attr_function* delete_fn, int* keyval,
3369                             void* extra_state)
3370 {
3371   smpi_copy_fn _copy_fn={nullptr,copy_fn,nullptr};
3372   smpi_delete_fn _delete_fn={nullptr,delete_fn,nullptr};
3373   return simgrid::smpi::Keyval::keyval_create<simgrid::smpi::Datatype>(_copy_fn, _delete_fn, keyval, extra_state);
3374 }
3375
3376 int PMPI_Type_free_keyval(int* keyval) {
3377   return simgrid::smpi::Keyval::keyval_free<simgrid::smpi::Datatype>(keyval);
3378 }
3379
3380 int PMPI_Win_get_attr (MPI_Win win, int keyval, void *attribute_val, int* flag)
3381 {
3382   static MPI_Aint size;
3383   static int disp_unit;
3384   if (win==MPI_WIN_NULL)
3385     return MPI_ERR_TYPE;
3386   else{
3387   switch (keyval) {
3388     case MPI_WIN_BASE :
3389       *static_cast<void**>(attribute_val)  = win->base();
3390       *flag = 1;
3391       return MPI_SUCCESS;
3392     case MPI_WIN_SIZE :
3393       size = win->size();
3394       *static_cast<MPI_Aint**>(attribute_val)  = &size;
3395       *flag = 1;
3396       return MPI_SUCCESS;
3397     case MPI_WIN_DISP_UNIT :
3398       disp_unit=win->disp_unit();
3399       *static_cast<int**>(attribute_val)  = &disp_unit;
3400       *flag = 1;
3401       return MPI_SUCCESS;
3402     default:
3403       return win->attr_get<simgrid::smpi::Win>(keyval, attribute_val, flag);
3404   }
3405 }
3406
3407 }
3408
3409 int PMPI_Win_set_attr (MPI_Win win, int type_keyval, void *attribute_val)
3410 {
3411   if (win==MPI_WIN_NULL)
3412     return MPI_ERR_TYPE;
3413   else
3414     return win->attr_put<simgrid::smpi::Win>(type_keyval, attribute_val);
3415 }
3416
3417 int PMPI_Win_delete_attr (MPI_Win win, int type_keyval)
3418 {
3419   if (win==MPI_WIN_NULL)
3420     return MPI_ERR_TYPE;
3421   else
3422     return win->attr_delete<simgrid::smpi::Win>(type_keyval);
3423 }
3424
3425 int PMPI_Win_create_keyval(MPI_Win_copy_attr_function* copy_fn, MPI_Win_delete_attr_function* delete_fn, int* keyval,
3426                             void* extra_state)
3427 {
3428   smpi_copy_fn _copy_fn={nullptr, nullptr, copy_fn};
3429   smpi_delete_fn _delete_fn={nullptr, nullptr, delete_fn};
3430   return simgrid::smpi::Keyval::keyval_create<simgrid::smpi::Win>(_copy_fn, _delete_fn, keyval, extra_state);
3431 }
3432
3433 int PMPI_Win_free_keyval(int* keyval) {
3434   return simgrid::smpi::Keyval::keyval_free<simgrid::smpi::Win>(keyval);
3435 }
3436
3437 int PMPI_Info_create( MPI_Info *info){
3438   if (info == nullptr)
3439     return MPI_ERR_ARG;
3440   *info = new simgrid::smpi::Info();
3441   return MPI_SUCCESS;
3442 }
3443
3444 int PMPI_Info_set( MPI_Info info, char *key, char *value){
3445   if (info == nullptr || key == nullptr || value == nullptr)
3446     return MPI_ERR_ARG;
3447   info->set(key, value);
3448   return MPI_SUCCESS;
3449 }
3450
3451 int PMPI_Info_free( MPI_Info *info){
3452   if (info == nullptr || *info==nullptr)
3453     return MPI_ERR_ARG;
3454   simgrid::smpi::Info::unref(*info);
3455   *info=MPI_INFO_NULL;
3456   return MPI_SUCCESS;
3457 }
3458
3459 int PMPI_Info_get(MPI_Info info,char *key,int valuelen, char *value, int *flag){
3460   *flag=false;
3461   if (info == nullptr || key == nullptr || valuelen <0)
3462     return MPI_ERR_ARG;
3463   if (value == nullptr)
3464     return MPI_ERR_INFO_VALUE;
3465   return info->get(key, valuelen, value, flag);
3466 }
3467
3468 int PMPI_Info_dup(MPI_Info info, MPI_Info *newinfo){
3469   if (info == nullptr || newinfo==nullptr)
3470     return MPI_ERR_ARG;
3471   *newinfo = new simgrid::smpi::Info(info);
3472   return MPI_SUCCESS;
3473 }
3474
3475 int PMPI_Info_delete(MPI_Info info, char *key){
3476   if (info == nullptr || key==nullptr)
3477     return MPI_ERR_ARG;
3478   return info->remove(key);
3479 }
3480
3481 int PMPI_Info_get_nkeys( MPI_Info info, int *nkeys){
3482   if (info == nullptr || nkeys==nullptr)
3483     return MPI_ERR_ARG;
3484   return info->get_nkeys(nkeys);
3485 }
3486
3487 int PMPI_Info_get_nthkey( MPI_Info info, int n, char *key){
3488   if (info == nullptr || key==nullptr || n<0 || n> MPI_MAX_INFO_KEY)
3489     return MPI_ERR_ARG;
3490   return info->get_nthkey(n, key);
3491 }
3492
3493 int PMPI_Info_get_valuelen( MPI_Info info, char *key, int *valuelen, int *flag){
3494   *flag=false;
3495   if (info == nullptr || key == nullptr || valuelen==nullptr)
3496     return MPI_ERR_ARG;
3497   return info->get_valuelen(key, valuelen, flag);
3498 }
3499
3500 int PMPI_Unpack(void* inbuf, int incount, int* position, void* outbuf, int outcount, MPI_Datatype type, MPI_Comm comm) {
3501   if(incount<0 || outcount < 0 || inbuf==nullptr || outbuf==nullptr)
3502     return MPI_ERR_ARG;
3503   if (not type->is_valid())
3504     return MPI_ERR_TYPE;
3505   if(comm==MPI_COMM_NULL)
3506     return MPI_ERR_COMM;
3507   return type->unpack(inbuf, incount, position, outbuf,outcount, comm);
3508 }
3509
3510 int PMPI_Pack(void* inbuf, int incount, MPI_Datatype type, void* outbuf, int outcount, int* position, MPI_Comm comm) {
3511   if(incount<0 || outcount < 0|| inbuf==nullptr || outbuf==nullptr)
3512     return MPI_ERR_ARG;
3513   if (not type->is_valid())
3514     return MPI_ERR_TYPE;
3515   if(comm==MPI_COMM_NULL)
3516     return MPI_ERR_COMM;
3517   return type->pack(inbuf, incount, outbuf,outcount,position, comm);
3518 }
3519
3520 int PMPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, int* size) {
3521   if(incount<0)
3522     return MPI_ERR_ARG;
3523   if (not datatype->is_valid())
3524     return MPI_ERR_TYPE;
3525   if(comm==MPI_COMM_NULL)
3526     return MPI_ERR_COMM;
3527
3528   *size=incount*datatype->size();
3529
3530   return MPI_SUCCESS;
3531 }
3532
3533 } // extern "C"