Logo AND Algorithmique Numérique Distribuée

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