1 /* Copyright (c) 2007-2023. The SimGrid Team. All rights reserved. */
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. */
9 #include "simgrid/s4u/Engine.hpp"
10 #include "smpi_comm.hpp"
11 #include "smpi_errhandler.hpp"
12 #include "smpi_info.hpp"
13 #include "src/smpi/include/smpi_actor.hpp"
15 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smpi_pmpi);
17 /* PMPI User level calls */
19 int PMPI_Comm_rank(MPI_Comm comm, int *rank)
22 CHECK_NULL(2, MPI_ERR_ARG, rank)
27 int PMPI_Comm_size(MPI_Comm comm, int *size)
30 CHECK_NULL(2, MPI_ERR_ARG, size)
35 int PMPI_Comm_get_name (MPI_Comm comm, char* name, int* len)
38 CHECK_NULL(2, MPI_ERR_ARG, name)
39 CHECK_NULL(3, MPI_ERR_ARG, len)
40 comm->get_name(name, len);
44 int PMPI_Comm_set_name (MPI_Comm comm, const char* name)
47 CHECK_NULL(2, MPI_ERR_ARG, name)
52 int PMPI_Comm_group(MPI_Comm comm, MPI_Group * group)
55 CHECK_NULL(2, MPI_ERR_ARG, group)
56 *group = comm->group();
57 if (*group != MPI_COMM_WORLD->group() && *group != MPI_GROUP_NULL && *group != MPI_GROUP_EMPTY)
62 int PMPI_Comm_compare(MPI_Comm comm1, MPI_Comm comm2, int *result)
66 CHECK_NULL(3, MPI_ERR_ARG, result)
67 if (comm1 == comm2) { /* Same communicators means same groups */
70 *result = comm1->group()->compare(comm2->group());
71 if (*result == MPI_IDENT) {
72 *result = MPI_CONGRUENT;
78 int PMPI_Comm_dup(MPI_Comm comm, MPI_Comm * newcomm)
81 CHECK_NULL(2, MPI_ERR_ARG, newcomm)
82 return comm->dup(newcomm);
85 int PMPI_Comm_dup_with_info(MPI_Comm comm, MPI_Info info, MPI_Comm * newcomm)
88 CHECK_NULL(2, MPI_ERR_ARG, newcomm)
89 comm->dup_with_info(info, newcomm);
93 int PMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm * newcomm)
97 CHECK_NULL(3, MPI_ERR_ARG, newcomm)
98 if (group->rank(simgrid::s4u::this_actor::get_pid()) == MPI_UNDEFINED) {
99 *newcomm= MPI_COMM_NULL;
103 *newcomm = new simgrid::smpi::Comm(group, nullptr);
108 int PMPI_Comm_free(MPI_Comm * comm)
110 CHECK_NULL(1, MPI_ERR_ARG, comm)
111 CHECK_COMM2(1, *comm)
112 CHECK_MPI_NULL(1, MPI_COMM_WORLD, MPI_ERR_COMM, *comm)
113 simgrid::smpi::Comm::destroy(*comm);
114 *comm = MPI_COMM_NULL;
118 int PMPI_Comm_disconnect(MPI_Comm * comm)
120 /* TODO: wait until all communication in comm are done */
121 CHECK_NULL(1, MPI_ERR_ARG, comm)
122 CHECK_COMM2(1, *comm)
123 simgrid::smpi::Comm::destroy(*comm);
124 *comm = MPI_COMM_NULL;
128 int PMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* comm_out)
130 CHECK_NULL(4, MPI_ERR_ARG, comm_out)
132 CHECK_COLLECTIVE(comm, __func__)
133 if( color != MPI_UNDEFINED)//we use a negative value for MPI_UNDEFINED
134 CHECK_NEGATIVE(3, MPI_ERR_ARG, color)
135 const SmpiBenchGuard suspend_bench;
136 *comm_out = comm->split(color, key);
140 int PMPI_Comm_split_type(MPI_Comm comm, int split_type, int key, MPI_Info info, MPI_Comm *newcomm)
143 CHECK_NULL(5, MPI_ERR_ARG, newcomm)
144 CHECK_COLLECTIVE(comm, __func__)
145 const SmpiBenchGuard suspend_bench;
146 *newcomm = comm->split_type(split_type, key, info);
150 int PMPI_Comm_create_group(MPI_Comm comm, MPI_Group group, int, MPI_Comm* comm_out)
153 CHECK_GROUP(2, group)
154 CHECK_NULL(5, MPI_ERR_ARG, comm_out)
155 const SmpiBenchGuard suspend_bench;
156 int retval = MPI_Comm_create(comm, group, comm_out);
160 MPI_Comm PMPI_Comm_f2c(MPI_Fint comm){
162 return MPI_COMM_NULL;
163 return simgrid::smpi::Comm::f2c(comm);
166 MPI_Fint PMPI_Comm_c2f(MPI_Comm comm){
167 if(comm==MPI_COMM_NULL)
172 int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
174 return PMPI_Attr_get(comm, comm_keyval, attribute_val,flag);
177 int PMPI_Comm_set_attr (MPI_Comm comm, int comm_keyval, void *attribute_val)
179 return PMPI_Attr_put(comm, comm_keyval, attribute_val);
182 int PMPI_Comm_get_info(MPI_Comm comm, MPI_Info* info)
185 CHECK_NULL(2, MPI_ERR_ARG, info)
186 *info = new simgrid::smpi::Info(comm->info());
190 int PMPI_Comm_set_info(MPI_Comm comm, MPI_Info info)
193 comm->set_info(info);
197 int PMPI_Comm_delete_attr (MPI_Comm comm, int comm_keyval)
199 return PMPI_Attr_delete(comm, comm_keyval);
202 int PMPI_Comm_create_keyval(MPI_Comm_copy_attr_function* copy_fn, MPI_Comm_delete_attr_function* delete_fn, int* keyval,
205 return PMPI_Keyval_create(copy_fn, delete_fn, keyval, extra_state);
208 int PMPI_Comm_free_keyval(int* keyval) {
209 return PMPI_Keyval_free(keyval);
212 int PMPI_Comm_test_inter(MPI_Comm comm, int* flag){
221 int PMPI_Attr_delete(MPI_Comm comm, int keyval) {
223 CHECK_VAL(2, MPI_KEYVAL_INVALID, MPI_ERR_KEYVAL, keyval)
224 if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
225 ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE)
228 return comm->attr_delete<simgrid::smpi::Comm>(keyval);
231 int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
234 static int tag_ub = INT_MAX;
235 static int last_used_code = MPI_ERR_LASTCODE;
236 static int universe_size;
238 CHECK_NULL(4, MPI_ERR_ARG, flag)
241 CHECK_VAL(2, MPI_KEYVAL_INVALID, MPI_ERR_KEYVAL, keyval)
248 *static_cast<int**>(attr_value) = &zero;
250 case MPI_UNIVERSE_SIZE:
252 universe_size = simgrid::s4u::Engine::get_instance()->get_host_count();
253 *static_cast<int**>(attr_value) = &universe_size;
255 case MPI_LASTUSEDCODE:
257 *static_cast<int**>(attr_value) = &last_used_code;
261 *static_cast<int**>(attr_value) = &tag_ub;
263 case MPI_WTIME_IS_GLOBAL:
265 *static_cast<int**>(attr_value) = &one;
268 return comm->attr_get<simgrid::smpi::Comm>(keyval, attr_value, flag);
272 int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
274 CHECK_VAL(2, MPI_KEYVAL_INVALID, MPI_ERR_KEYVAL, keyval)
275 if(keyval == MPI_TAG_UB||keyval == MPI_HOST||keyval == MPI_IO ||keyval == MPI_WTIME_IS_GLOBAL||keyval == MPI_APPNUM
276 ||keyval == MPI_UNIVERSE_SIZE||keyval == MPI_LASTUSEDCODE)
279 return comm->attr_put<simgrid::smpi::Comm>(keyval, attr_value);
282 int PMPI_Errhandler_free(MPI_Errhandler* errhandler){
283 CHECK_NULL(1, MPI_ERR_ARG, errhandler)
284 CHECK_MPI_NULL(1, MPI_ERRHANDLER_NULL, MPI_ERR_ARG, *errhandler)
285 simgrid::smpi::Errhandler::unref(*errhandler);
286 *errhandler = MPI_ERRHANDLER_NULL;
290 int PMPI_Errhandler_create(MPI_Handler_function* function, MPI_Errhandler* errhandler){
291 CHECK_NULL(2, MPI_ERR_ARG, errhandler)
292 *errhandler=new simgrid::smpi::Errhandler(function);
293 (*errhandler)->add_f();
297 int PMPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler* errhandler){
299 CHECK_NULL(1, MPI_ERR_ARG, errhandler)
300 *errhandler=comm->errhandler();
304 int PMPI_Errhandler_set(MPI_Comm comm, MPI_Errhandler errhandler){
306 CHECK_NULL(1, MPI_ERR_ARG, errhandler)
307 comm->set_errhandler(errhandler);
311 int PMPI_Comm_call_errhandler(MPI_Comm comm,int errorcode){
313 MPI_Errhandler err = comm->errhandler();
314 err->call(comm, errorcode);
315 simgrid::smpi::Errhandler::unref(err);
319 MPI_Errhandler PMPI_Errhandler_f2c(MPI_Fint errhan){
321 return MPI_ERRHANDLER_NULL;
322 return simgrid::smpi::Errhandler::f2c(errhan);
325 MPI_Fint PMPI_Errhandler_c2f(MPI_Errhandler errhan){
326 if(errhan==MPI_ERRHANDLER_NULL)
328 return errhan->c2f();
331 int PMPI_Comm_create_errhandler( MPI_Comm_errhandler_fn *function, MPI_Errhandler *errhandler){
332 return MPI_Errhandler_create(function, errhandler);
334 int PMPI_Comm_get_errhandler(MPI_Comm comm, MPI_Errhandler* errhandler){
335 return PMPI_Errhandler_get(comm, errhandler);
337 int PMPI_Comm_set_errhandler(MPI_Comm comm, MPI_Errhandler errhandler){
338 return PMPI_Errhandler_set(comm, errhandler);