Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / src / smpi / bindings / smpi_pmpi_comm.cpp
1 /* Copyright (c) 2007-2023. 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 <climits>
7
8 #include "private.hpp"
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"
14
15 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smpi_pmpi);
16
17 /* PMPI User level calls */
18
19 int PMPI_Comm_rank(MPI_Comm comm, int *rank)
20 {
21   CHECK_COMM(1)
22   CHECK_NULL(2, MPI_ERR_ARG, rank)
23   *rank = comm->rank();
24   return MPI_SUCCESS;
25 }
26
27 int PMPI_Comm_size(MPI_Comm comm, int *size)
28 {
29   CHECK_COMM(1)
30   CHECK_NULL(2, MPI_ERR_ARG, size)
31   *size = comm->size();
32   return MPI_SUCCESS;
33 }
34
35 int PMPI_Comm_get_name (MPI_Comm comm, char* name, int* len)
36 {
37   CHECK_COMM(1)
38   CHECK_NULL(2, MPI_ERR_ARG, name)
39   CHECK_NULL(3, MPI_ERR_ARG, len)
40   comm->get_name(name, len);
41   return MPI_SUCCESS;
42 }
43
44 int PMPI_Comm_set_name (MPI_Comm comm, const char* name)
45 {
46   CHECK_COMM(1)
47   CHECK_NULL(2, MPI_ERR_ARG, name)
48   comm->set_name(name);
49   return MPI_SUCCESS;
50 }
51
52 int PMPI_Comm_group(MPI_Comm comm, MPI_Group * group)
53 {
54   CHECK_COMM(1)
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)
58     (*group)->ref();
59   return MPI_SUCCESS;
60 }
61
62 int PMPI_Comm_compare(MPI_Comm comm1, MPI_Comm comm2, int *result)
63 {
64   CHECK_COMM2(1, comm1)
65   CHECK_COMM2(2, comm2)
66   CHECK_NULL(3, MPI_ERR_ARG, result)
67   if (comm1 == comm2) {       /* Same communicators means same groups */
68     *result = MPI_IDENT;
69   } else {
70     *result = comm1->group()->compare(comm2->group());
71     if (*result == MPI_IDENT) {
72       *result = MPI_CONGRUENT;
73     }
74   }
75   return MPI_SUCCESS;
76 }
77
78 int PMPI_Comm_dup(MPI_Comm comm, MPI_Comm * newcomm)
79 {
80   CHECK_COMM(1)
81   CHECK_NULL(2, MPI_ERR_ARG, newcomm)
82   return comm->dup(newcomm);
83 }
84
85 int PMPI_Comm_dup_with_info(MPI_Comm comm, MPI_Info info, MPI_Comm * newcomm)
86 {
87   CHECK_COMM(1)
88   CHECK_NULL(2, MPI_ERR_ARG, newcomm)
89   comm->dup_with_info(info, newcomm);
90   return MPI_SUCCESS;
91 }
92
93 int PMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm * newcomm)
94 {
95   CHECK_COMM(1)
96   CHECK_GROUP(2, group)
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;
100     return MPI_SUCCESS;
101   }else{
102     group->ref();
103     *newcomm = new simgrid::smpi::Comm(group, nullptr);
104     return MPI_SUCCESS;
105   }
106 }
107
108 int PMPI_Comm_free(MPI_Comm * comm)
109 {
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;
115   return MPI_SUCCESS;
116 }
117
118 int PMPI_Comm_disconnect(MPI_Comm * comm)
119 {
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;
125   return MPI_SUCCESS;
126 }
127
128 int PMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* comm_out)
129 {
130   CHECK_NULL(4, MPI_ERR_ARG, comm_out)
131   CHECK_COMM2(1, comm)
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);
137   return MPI_SUCCESS;
138 }
139
140 int PMPI_Comm_split_type(MPI_Comm comm, int split_type, int key, MPI_Info info, MPI_Comm *newcomm)
141 {
142   CHECK_COMM(1)
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);
147   return MPI_SUCCESS;
148 }
149
150 int PMPI_Comm_create_group(MPI_Comm comm, MPI_Group group, int, MPI_Comm* comm_out)
151 {
152   CHECK_COMM(1)
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);
157   return retval;
158 }
159
160 MPI_Comm PMPI_Comm_f2c(MPI_Fint comm){
161   if(comm==-1)
162     return MPI_COMM_NULL;
163   return simgrid::smpi::Comm::f2c(comm);
164 }
165
166 MPI_Fint PMPI_Comm_c2f(MPI_Comm comm){
167   if(comm==MPI_COMM_NULL)
168     return -1;
169   return comm->c2f();
170 }
171
172 int PMPI_Comm_get_attr (MPI_Comm comm, int comm_keyval, void *attribute_val, int *flag)
173 {
174   return PMPI_Attr_get(comm, comm_keyval, attribute_val,flag);
175 }
176
177 int PMPI_Comm_set_attr (MPI_Comm comm, int comm_keyval, void *attribute_val)
178 {
179   return PMPI_Attr_put(comm, comm_keyval, attribute_val);
180 }
181
182 int PMPI_Comm_get_info(MPI_Comm comm, MPI_Info* info)
183 {
184   CHECK_COMM(1)
185   CHECK_NULL(2, MPI_ERR_ARG, info)
186   *info = new simgrid::smpi::Info(comm->info());
187   return MPI_SUCCESS;
188 }
189
190 int PMPI_Comm_set_info(MPI_Comm  comm, MPI_Info info)
191 {
192   CHECK_COMM(1)
193   comm->set_info(info);
194   return MPI_SUCCESS;
195 }
196
197 int PMPI_Comm_delete_attr (MPI_Comm comm, int comm_keyval)
198 {
199   return PMPI_Attr_delete(comm, comm_keyval);
200 }
201
202 int PMPI_Comm_create_keyval(MPI_Comm_copy_attr_function* copy_fn, MPI_Comm_delete_attr_function* delete_fn, int* keyval,
203                             void* extra_state)
204 {
205   return PMPI_Keyval_create(copy_fn, delete_fn, keyval, extra_state);
206 }
207
208 int PMPI_Comm_free_keyval(int* keyval) {
209   return PMPI_Keyval_free(keyval);
210 }
211
212 int PMPI_Comm_test_inter(MPI_Comm comm, int* flag){
213   CHECK_COMM(1)
214
215   if(flag == nullptr)
216     return MPI_ERR_ARG;
217   *flag=false;
218   return MPI_SUCCESS;
219 }
220
221 int PMPI_Attr_delete(MPI_Comm comm, int keyval) {
222   CHECK_COMM(1)
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)
226     return MPI_ERR_ARG;
227   else
228     return comm->attr_delete<simgrid::smpi::Comm>(keyval);
229 }
230
231 int PMPI_Attr_get(MPI_Comm comm, int keyval, void* attr_value, int* flag) {
232   static int one = 1;
233   static int zero = 0;
234   static int tag_ub = INT_MAX;
235   static int last_used_code = MPI_ERR_LASTCODE;
236   static int universe_size;
237
238   CHECK_NULL(4, MPI_ERR_ARG, flag)
239   *flag = 0;
240   CHECK_COMM(1)
241   CHECK_VAL(2, MPI_KEYVAL_INVALID, MPI_ERR_KEYVAL, keyval)
242
243   switch (keyval) {
244   case MPI_HOST:
245   case MPI_IO:
246   case MPI_APPNUM:
247     *flag = 1;
248     *static_cast<int**>(attr_value) = &zero;
249     return MPI_SUCCESS;
250   case MPI_UNIVERSE_SIZE:
251     *flag = 1;
252     universe_size                   = simgrid::s4u::Engine::get_instance()->get_host_count();
253     *static_cast<int**>(attr_value) = &universe_size;
254     return MPI_SUCCESS;
255   case MPI_LASTUSEDCODE:
256     *flag = 1;
257     *static_cast<int**>(attr_value) = &last_used_code;
258     return MPI_SUCCESS;
259   case MPI_TAG_UB:
260     *flag=1;
261     *static_cast<int**>(attr_value) = &tag_ub;
262     return MPI_SUCCESS;
263   case MPI_WTIME_IS_GLOBAL:
264     *flag = 1;
265     *static_cast<int**>(attr_value) = &one;
266     return MPI_SUCCESS;
267   default:
268     return comm->attr_get<simgrid::smpi::Comm>(keyval, attr_value, flag);
269   }
270 }
271
272 int PMPI_Attr_put(MPI_Comm comm, int keyval, void* attr_value) {
273   CHECK_COMM(1)
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)
277     return MPI_ERR_ARG;
278   else
279     return comm->attr_put<simgrid::smpi::Comm>(keyval, attr_value);
280 }
281
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;
287   return MPI_SUCCESS;
288 }
289
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();
294   return MPI_SUCCESS;
295 }
296
297 int PMPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler* errhandler){
298   CHECK_COMM(1)
299   CHECK_NULL(1, MPI_ERR_ARG, errhandler)
300   *errhandler=comm->errhandler();
301   return MPI_SUCCESS;
302 }
303
304 int PMPI_Errhandler_set(MPI_Comm comm, MPI_Errhandler errhandler){
305   CHECK_COMM(1)
306   CHECK_NULL(1, MPI_ERR_ARG, errhandler)
307   comm->set_errhandler(errhandler);
308   return MPI_SUCCESS;
309 }
310
311 int PMPI_Comm_call_errhandler(MPI_Comm comm,int errorcode){
312   CHECK_COMM(1)
313   MPI_Errhandler err = comm->errhandler();
314   err->call(comm, errorcode);
315   simgrid::smpi::Errhandler::unref(err);
316   return MPI_SUCCESS;
317 }
318
319 MPI_Errhandler PMPI_Errhandler_f2c(MPI_Fint errhan){
320   if(errhan==-1)
321     return MPI_ERRHANDLER_NULL;
322   return simgrid::smpi::Errhandler::f2c(errhan);
323 }
324
325 MPI_Fint PMPI_Errhandler_c2f(MPI_Errhandler errhan){
326   if(errhan==MPI_ERRHANDLER_NULL)
327     return -1;
328   return errhan->c2f();
329 }
330
331 int PMPI_Comm_create_errhandler( MPI_Comm_errhandler_fn *function, MPI_Errhandler *errhandler){
332   return MPI_Errhandler_create(function, errhandler);
333 }
334 int PMPI_Comm_get_errhandler(MPI_Comm comm, MPI_Errhandler* errhandler){
335   return PMPI_Errhandler_get(comm, errhandler);
336 }
337 int PMPI_Comm_set_errhandler(MPI_Comm comm, MPI_Errhandler errhandler){
338   return PMPI_Errhandler_set(comm, errhandler);
339 }