+#include "smpi_coll_private.h"
+#include "smpi_mpi_dt_private.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_mpi, smpi,
+ "Logging specific to SMPI (mpi)");
+
+/* MPI User level calls */
+
+int MPI_Init(int* argc, char*** argv) {
+ smpi_process_init(argc, argv);
+#ifdef HAVE_TRACING
+ TRACE_smpi_init(smpi_process_index());
+#endif
+ smpi_bench_begin(-1, NULL);
+ return MPI_SUCCESS;
+}
+
+int MPI_Finalize(void) {
+ smpi_bench_end(-1, NULL);
+#ifdef HAVE_TRACING
+ TRACE_smpi_finalize(smpi_process_index());
+#endif
+ smpi_process_destroy();
+ return MPI_SUCCESS;
+}
+
+int MPI_Init_thread(int* argc, char*** argv, int required, int* provided) {
+ if(provided != NULL) {
+ *provided = MPI_THREAD_MULTIPLE;
+ }
+ return MPI_Init(argc, argv);
+}
+
+int MPI_Query_thread(int* provided) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(provided == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *provided = MPI_THREAD_MULTIPLE;
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Is_thread_main(int* flag) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(flag == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *flag = smpi_process_index() == 0;
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Abort(MPI_Comm comm, int errorcode) {
+ smpi_bench_end(-1, NULL);
+ smpi_process_destroy();
+ // FIXME: should kill all processes in comm instead
+ SIMIX_process_kill(SIMIX_process_self());
+ return MPI_SUCCESS;
+}
+
+double MPI_Wtime(void) {
+ double time;
+
+ smpi_bench_end(-1, NULL);
+ time = SIMIX_get_clock();
+ smpi_bench_begin(-1, NULL);
+ return time;
+}
+
+int MPI_Address(void *location, MPI_Aint *address) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(!address) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *address = (MPI_Aint)location;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Type_free(MPI_Datatype* datatype) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(!datatype) {
+ retval = MPI_ERR_ARG;
+ } else {
+ // FIXME: always fail for now
+ retval = MPI_ERR_TYPE;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Type_size(MPI_Datatype datatype, int* size) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(datatype == MPI_DATATYPE_NULL) {
+ retval = MPI_ERR_TYPE;
+ } else if(size == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *size = (int)smpi_datatype_size(datatype);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint* lb, MPI_Aint* extent) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(datatype == MPI_DATATYPE_NULL) {
+ retval = MPI_ERR_TYPE;
+ } else if(lb == NULL || extent == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ retval = smpi_datatype_extent(datatype, lb, extent);
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Type_extent(MPI_Datatype datatype, MPI_Aint* extent) {
+ int retval;
+ MPI_Aint dummy;
+
+ smpi_bench_end(-1, NULL);
+ if(datatype == MPI_DATATYPE_NULL) {
+ retval = MPI_ERR_TYPE;
+ } else if(extent == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ retval = smpi_datatype_extent(datatype, &dummy, extent);
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Type_lb(MPI_Datatype datatype, MPI_Aint* disp) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(datatype == MPI_DATATYPE_NULL) {
+ retval = MPI_ERR_TYPE;
+ } else if(disp == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *disp = smpi_datatype_lb(datatype);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Type_ub(MPI_Datatype datatype, MPI_Aint* disp) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(datatype == MPI_DATATYPE_NULL) {
+ retval = MPI_ERR_TYPE;
+ } else if(disp == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *disp = smpi_datatype_ub(datatype);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Op_create(MPI_User_function* function, int commute, MPI_Op* op) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(function == NULL || op == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *op = smpi_op_new(function, commute);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Op_free(MPI_Op* op) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(op == NULL) {
+ retval = MPI_ERR_ARG;
+ } else if(*op == MPI_OP_NULL) {
+ retval = MPI_ERR_OP;
+ } else {
+ smpi_op_destroy(*op);
+ *op = MPI_OP_NULL;
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_free(MPI_Group *group) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(group == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ smpi_group_destroy(*group);
+ *group = MPI_GROUP_NULL;
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_size(MPI_Group group, int* size) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(group == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(size == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *size = smpi_group_size(group);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_rank(MPI_Group group, int* rank) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(group == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(rank == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *rank = smpi_group_rank(group, smpi_process_index());
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_translate_ranks (MPI_Group group1, int n, int* ranks1, MPI_Group group2, int* ranks2) {
+ int retval, i, index;
+
+ smpi_bench_end(-1, NULL);
+ if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else {
+ for(i = 0; i < n; i++) {
+ index = smpi_group_index(group1, ranks1[i]);
+ ranks2[i] = smpi_group_rank(group2, index);
+ }
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_compare(MPI_Group group1, MPI_Group group2, int* result) {
+ int retval;
+
+ smpi_bench_end(-1, NULL);
+ if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(result == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ *result = smpi_group_compare(group1, group2);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group* newgroup) {
+ int retval, i, proc1, proc2, size, size2;
+
+ smpi_bench_end(-1, NULL);
+ if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(newgroup == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ size = smpi_group_size(group1);
+ size2 = smpi_group_size(group2);
+ for(i = 0; i < size2; i++) {
+ proc2 = smpi_group_index(group2, i);
+ proc1 = smpi_group_rank(group1, proc2);
+ if(proc1 == MPI_UNDEFINED) {
+ size++;
+ }
+ }
+ if(size == 0) {
+ *newgroup = MPI_GROUP_EMPTY;
+ } else {
+ *newgroup = smpi_group_new(size);
+ size2 = smpi_group_size(group1);
+ for(i = 0; i < size2; i++) {
+ proc1 = smpi_group_index(group1, i);
+ smpi_group_set_mapping(*newgroup, proc1, i);
+ }
+ for(i = size2; i < size; i++) {
+ proc2 = smpi_group_index(group2, i - size2);
+ smpi_group_set_mapping(*newgroup, proc2, i);
+ }
+ }
+ smpi_group_use(*newgroup);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group* newgroup) {
+ int retval, i, proc1, proc2, size, size2;
+
+ smpi_bench_end(-1, NULL);
+ if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(newgroup == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ size = smpi_group_size(group1);
+ size2 = smpi_group_size(group2);
+ for(i = 0; i < size2; i++) {
+ proc2 = smpi_group_index(group2, i);
+ proc1 = smpi_group_rank(group1, proc2);
+ if(proc1 == MPI_UNDEFINED) {
+ size--;
+ }
+ }
+ if(size == 0) {
+ *newgroup = MPI_GROUP_EMPTY;
+ } else {
+ *newgroup = smpi_group_new(size);
+ size2 = smpi_group_size(group1);
+ for(i = 0; i < size2; i++) {
+ proc1 = smpi_group_index(group1, i);
+ proc2 = smpi_group_rank(group2, proc1);
+ if(proc2 != MPI_UNDEFINED) {
+ smpi_group_set_mapping(*newgroup, proc1, i);
+ }
+ }
+ }
+ smpi_group_use(*newgroup);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group* newgroup) {
+ int retval, i, proc1, proc2, size, size2;
+
+ smpi_bench_end(-1, NULL);
+ if(group1 == MPI_GROUP_NULL || group2 == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(newgroup == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ size = size2 = smpi_group_size(group1);
+ for(i = 0; i < size2; i++) {
+ proc1 = smpi_group_index(group1, i);
+ proc2 = smpi_group_rank(group2, proc1);
+ if(proc2 != MPI_UNDEFINED) {
+ size--;
+ }
+ }
+ if(size == 0) {
+ *newgroup = MPI_GROUP_EMPTY;
+ } else {
+ *newgroup = smpi_group_new(size);
+ for(i = 0; i < size2; i++) {
+ proc1 = smpi_group_index(group1, i);
+ proc2 = smpi_group_rank(group2, proc1);
+ if(proc2 == MPI_UNDEFINED) {
+ smpi_group_set_mapping(*newgroup, proc1, i);
+ }
+ }
+ }
+ smpi_group_use(*newgroup);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_incl(MPI_Group group, int n, int* ranks, MPI_Group* newgroup) {
+ int retval, i, index;
+
+ smpi_bench_end(-1, NULL);
+ if(group == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(newgroup == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ if(n == 0) {
+ *newgroup = MPI_GROUP_EMPTY;
+ } else if(n == smpi_group_size(group)) {
+ *newgroup = group;
+ } else {
+ *newgroup = smpi_group_new(n);
+ for(i = 0; i < n; i++) {
+ index = smpi_group_index(group, ranks[i]);
+ smpi_group_set_mapping(*newgroup, index, i);
+ }
+ }
+ smpi_group_use(*newgroup);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}
+
+int MPI_Group_excl(MPI_Group group, int n, int* ranks, MPI_Group* newgroup) {
+ int retval, i, size, rank, index;
+
+ smpi_bench_end(-1, NULL);
+ if(group == MPI_GROUP_NULL) {
+ retval = MPI_ERR_GROUP;
+ } else if(newgroup == NULL) {
+ retval = MPI_ERR_ARG;
+ } else {
+ if(n == 0) {
+ *newgroup = group;
+ } else if(n == smpi_group_size(group)) {
+ *newgroup = MPI_GROUP_EMPTY;
+ } else {
+ size = smpi_group_size(group) - n;
+ *newgroup = smpi_group_new(size);
+ rank = 0;
+ while(rank < size) {
+ for(i = 0; i < n; i++) {
+ if(ranks[i] == rank) {
+ break;
+ }
+ }
+ if(i >= n) {
+ index = smpi_group_index(group, rank);
+ smpi_group_set_mapping(*newgroup, index, rank);
+ rank++;
+ }
+ }
+ }
+ smpi_group_use(*newgroup);
+ retval = MPI_SUCCESS;
+ }
+ smpi_bench_begin(-1, NULL);
+ return retval;
+}