Logo AND Algorithmique Numérique Distribuée

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