Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge pull request #314 from simgrid/smpi-args-cleanup
[simgrid.git] / src / smpi / bindings / smpi_pmpi.cpp
1 /* Copyright (c) 2007-2018. 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 "private.hpp"
7 #include "simgrid/s4u/Engine.hpp"
8 #include "simgrid/s4u/Host.hpp"
9 #include "smpi_comm.hpp"
10 #include "smpi_datatype_derived.hpp"
11 #include "smpi_status.hpp"
12 #include "src/simix/ActorImpl.hpp"
13 #include "src/smpi/include/smpi_actor.hpp"
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_pmpi, smpi, "Logging specific to SMPI (pmpi)");
16
17 //this function need to be here because of the calls to smpi_bench
18 void TRACE_smpi_set_category(const char *category)
19 {
20   //need to end bench otherwise categories for execution tasks are wrong
21   smpi_bench_end();
22   if (category != nullptr)
23     TRACE_internal_smpi_set_category(category);
24   //begin bench after changing process's category
25   smpi_bench_begin();
26 }
27
28 /* PMPI User level calls */
29
30 int PMPI_Init(int *argc, char ***argv)
31 {
32   xbt_assert(simgrid::s4u::Engine::is_initialized(),
33              "Your MPI program was not properly initialized. The easiest is to use smpirun to start it.");
34
35   // Init is called only once per SMPI process
36   if (not smpi_process()->initializing()){
37     simgrid::smpi::ActorExt::init();
38   }
39   if (not smpi_process()->initialized()){
40     int rank_traced = simgrid::s4u::this_actor::get_pid();
41     TRACE_smpi_init(rank_traced);
42     TRACE_smpi_comm_in(rank_traced, __func__, new simgrid::instr::NoOpTIData("init"));
43     TRACE_smpi_comm_out(rank_traced);
44     TRACE_smpi_computing_init(rank_traced);
45     TRACE_smpi_sleeping_init(rank_traced);
46     smpi_bench_begin();
47     smpi_process()->mark_as_initialized();
48   }
49
50   smpi_mpi_init();
51
52   return MPI_SUCCESS;
53 }
54
55 int PMPI_Finalize()
56 {
57   smpi_bench_end();
58   int rank_traced = simgrid::s4u::this_actor::get_pid();
59   TRACE_smpi_comm_in(rank_traced, __func__, new simgrid::instr::NoOpTIData("finalize"));
60
61   smpi_process()->finalize();
62
63   TRACE_smpi_comm_out(rank_traced);
64   TRACE_smpi_finalize(rank_traced);
65   return MPI_SUCCESS;
66 }
67
68 int PMPI_Finalized(int* flag)
69 {
70   *flag=smpi_process()!=nullptr ? smpi_process()->finalized() : 0;
71   return MPI_SUCCESS;
72 }
73
74 int PMPI_Get_version (int *version,int *subversion){
75   *version = MPI_VERSION;
76   *subversion= MPI_SUBVERSION;
77   return MPI_SUCCESS;
78 }
79
80 int PMPI_Get_library_version (char *version,int *len){
81   smpi_bench_end();
82   snprintf(version, MPI_MAX_LIBRARY_VERSION_STRING, "SMPI Version %d.%d. Copyright The Simgrid Team 2007-2018",
83            SIMGRID_VERSION_MAJOR, SIMGRID_VERSION_MINOR);
84   *len = strlen(version) > MPI_MAX_LIBRARY_VERSION_STRING ? MPI_MAX_LIBRARY_VERSION_STRING : strlen(version);
85   smpi_bench_begin();
86   return MPI_SUCCESS;
87 }
88
89 int PMPI_Init_thread(int* argc, char*** argv, int /*required*/, int* provided)
90 {
91   if (provided != nullptr) {
92     *provided = MPI_THREAD_SINGLE;
93   }
94   return MPI_Init(argc, argv);
95 }
96
97 int PMPI_Query_thread(int *provided)
98 {
99   if (provided == nullptr) {
100     return MPI_ERR_ARG;
101   } else {
102     *provided = MPI_THREAD_SINGLE;
103     return MPI_SUCCESS;
104   }
105 }
106
107 int PMPI_Is_thread_main(int *flag)
108 {
109   // FIXME: The MPI standard seems to say that fatal errors need to be triggered
110   // if MPI has been finalized or not yet been initialized
111   if (flag == nullptr) {
112     return MPI_ERR_ARG;
113   } else {
114     *flag = simgrid::s4u::this_actor::get_pid() ==
115             1; // FIXME: I don't think this is correct: This just returns true if the process ID is 1,
116                // regardless of whether this process called MPI_Thread_Init() or not.
117     return MPI_SUCCESS;
118   }
119 }
120
121 int PMPI_Abort(MPI_Comm /*comm*/, int /*errorcode*/)
122 {
123   smpi_bench_end();
124   // FIXME: should kill all processes in comm instead
125   smx_actor_t process = SIMIX_process_self();
126   simgrid::simix::simcall([process] { SIMIX_process_kill(process, process); });
127   return MPI_SUCCESS;
128 }
129
130 double PMPI_Wtime()
131 {
132   return smpi_mpi_wtime();
133 }
134
135 extern double sg_maxmin_precision;
136 double PMPI_Wtick()
137 {
138   return sg_maxmin_precision;
139 }
140
141 int PMPI_Address(void *location, MPI_Aint * address)
142 {
143   if (address==nullptr) {
144     return MPI_ERR_ARG;
145   } else {
146     *address = reinterpret_cast<MPI_Aint>(location);
147     return MPI_SUCCESS;
148   }
149 }
150
151 int PMPI_Get_address(void *location, MPI_Aint * address)
152 {
153   return PMPI_Address(location, address);
154 }
155
156 int PMPI_Get_processor_name(char *name, int *resultlen)
157 {
158   strncpy(name, sg_host_self()->get_cname(),
159           strlen(sg_host_self()->get_cname()) < MPI_MAX_PROCESSOR_NAME - 1 ? strlen(sg_host_self()->get_cname()) + 1
160                                                                            : MPI_MAX_PROCESSOR_NAME - 1);
161   *resultlen = strlen(name) > MPI_MAX_PROCESSOR_NAME ? MPI_MAX_PROCESSOR_NAME : strlen(name);
162
163   return MPI_SUCCESS;
164 }
165
166 int PMPI_Get_count(MPI_Status * status, MPI_Datatype datatype, int *count)
167 {
168   if (status == nullptr || count == nullptr) {
169     return MPI_ERR_ARG;
170   } else if (not datatype->is_valid()) {
171     return MPI_ERR_TYPE;
172   } else {
173     size_t size = datatype->size();
174     if (size == 0) {
175       *count = 0;
176       return MPI_SUCCESS;
177     } else if (status->count % size != 0) {
178       return MPI_UNDEFINED;
179     } else {
180       *count = simgrid::smpi::Status::get_count(status, datatype);
181       return MPI_SUCCESS;
182     }
183   }
184 }
185
186 int PMPI_Initialized(int* flag) {
187    *flag=(smpi_process()!=nullptr && smpi_process()->initialized());
188    return MPI_SUCCESS;
189 }
190
191 int PMPI_Alloc_mem(MPI_Aint size, MPI_Info /*info*/, void* baseptr)
192 {
193   void *ptr = xbt_malloc(size);
194   if(ptr==nullptr)
195     return MPI_ERR_NO_MEM;
196   else {
197     *static_cast<void**>(baseptr) = ptr;
198     return MPI_SUCCESS;
199   }
200 }
201
202 int PMPI_Free_mem(void *baseptr){
203   xbt_free(baseptr);
204   return MPI_SUCCESS;
205 }
206
207 int PMPI_Error_class(int errorcode, int* errorclass) {
208   // assume smpi uses only standard mpi error codes
209   *errorclass=errorcode;
210   return MPI_SUCCESS;
211 }
212
213 int PMPI_Error_string(int errorcode, char* string, int* resultlen){
214   if (errorcode<0 || string ==nullptr){
215     return MPI_ERR_ARG;
216   } else {
217     static const char *smpi_error_string[] = {
218       FOREACH_ERROR(GENERATE_STRING)
219     };
220     *resultlen = strlen(smpi_error_string[errorcode]);
221     strncpy(string, smpi_error_string[errorcode], *resultlen);
222     return MPI_SUCCESS;  
223   }
224 }
225
226 int PMPI_Keyval_create(MPI_Copy_function* copy_fn, MPI_Delete_function* delete_fn, int* keyval, void* extra_state) {
227   smpi_copy_fn _copy_fn={copy_fn,nullptr,nullptr,nullptr,nullptr,nullptr};
228   smpi_delete_fn _delete_fn={delete_fn,nullptr,nullptr,nullptr,nullptr,nullptr};
229   return simgrid::smpi::Keyval::keyval_create<simgrid::smpi::Comm>(_copy_fn, _delete_fn, keyval, extra_state);
230 }
231
232 int PMPI_Keyval_free(int* keyval) {
233   return simgrid::smpi::Keyval::keyval_free<simgrid::smpi::Comm>(keyval);
234 }