Logo AND Algorithmique Numérique Distribuée

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