Logo AND Algorithmique Numérique Distribuée

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