Logo AND Algorithmique Numérique Distribuée

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