Logo AND Algorithmique Numérique Distribuée

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