Logo AND Algorithmique Numérique Distribuée

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