1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2008 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2005 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2008-2012 Cisco Systems, Inc. All rights reserved.
14 * Copyright (c) 2015-2016 Los Alamos National Security, LLC. All rights
15 * reserved.
16 * Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
17 * $COPYRIGHT$
18 *
19 * Additional copyrights may follow
20 *
21 * $HEADER$
22 */
23 /**
24 * @file
25 *
26 * Top-level interface for \em all MCA components.
27 *
28 * Historical notes:
29 *
30 * Open MPI originally used a v1.0.0 of the MCA component structs, but
31 * did not have a version number in the struct name. If I recall
32 * correctly, this is because we simply didn't think through (or never
33 * envisioned) changing the MCA base component struct itself. Oops.
34 *
35 * We made some changes in the base struct in Open MPI v1.3, and
36 * decided the following at the same time:
37 *
38 * - Bump the MCA version number to 2.0.0 and add some "reserved"
39 * space at the end of the struct.
40 * - The major MCA version number is essentially tied to the space
41 * that the struct occupies; if we make future changes in the struct
42 * by just using some of the reserved space, it may be possible to
43 * just increment the minor version number (depending on the scope of
44 * the change). If we need to add more space to the struct, we'll
45 * increment the major version number.
46 * - The MCA base component struct now has a version number in it
47 * (starting with Open MPI v1.3, it is 2.0.0).
48 * - As was an unstated assumption in prior versions of Open MPI, the
49 * unversioned versions of struct names (both in the MCA base and in
50 * individual framework bases) are intended for components who want
51 * to be forward source-compatible. That is, the unversioned struct
52 * name always represents the most recent interface version. If you
53 * need to use an older version, you can explicitly use that older
54 * struct version name. Please note, however, the Open MPI
55 * developers may not generally provide older versions of framework
56 * interface structs unless they know if someone outside of the Open
57 * MPI community needs it.
58 *
59 * ***IF YOU NEED BACKWARDS SOURCE OR BINARY COMPATIBILITY, you must
60 * let us know!***
61 *
62 * - We are currently only aware of one external developer making Open
63 * MPI components for the v1.2 series. He already knows that there
64 * are major changes coming in the v1.3 series, and does not expect to
65 * be able to use his v1.2 DSO binaries in v1.3. As such, we are
66 * breaking backwards binary compatibility in v1.3: there is no
67 * possibility of loading an MCA v1.0 binary component in Open MPI
68 * v1.3 or beyond (source compatibility is much easier -- the binary
69 * "refuse to load MCA components <v2.0.0" policy is enforced in
70 * mca_base_component_find.c).
71 *
72 * ***IF YOU NEED BACKWARDS BINARY COMPATIBILITY, please let us
73 * know!***
74 *
75 * - Note that we decided that framework version numbers are *not*
76 * related to the MCA version number. It is permissible to bump the
77 * MCA version number and leave all the framework version numbers
78 * they same. Specifically: a component is uniquely identified by
79 * its (MCA version, framework version, component version) tuple.
80 * So a component that is simply compiled with two different MCA
81 * base versions is still considered "different" because the tuple
82 * first member is different.
83 * - Per the discussion above, we decided to have MCA v2.0 no longer
84 * load <v2.0.0 components, and therefore avoided the "how to upcast
85 * a component in memory" issue. After v2.0.0, it is slightly
86 * easier because the MCA component structs have "reserved" space at
87 * the end that may account for future version data fields.
88 */
89
90 #ifndef OPAL_MCA_H
91 #define OPAL_MCA_H
92
93 #include "opal_config.h"
94
95
96 /**
97 * Common type for all MCA modules.
98 *
99 * An instance of this type is always the first element in MCA
100 * modules, allowing the module to be associated with a
101 * particular version of a specific framework, and to publish its own
102 * name and version.
103 */
104 struct mca_base_module_2_0_0_t {
105 int dummy_value;
106 };
107 /** Unversioned convenience typedef; use this name in
108 frameworks/components to stay forward source-compatible */
109 typedef struct mca_base_module_2_0_0_t mca_base_module_t;
110 /** Versioned convenience typedef */
111 typedef struct mca_base_module_2_0_0_t mca_base_module_2_0_0_t;
112
113
114 /**
115 * MCA component open function.
116 *
117 * @retval OPAL_SUCCESS This component can be used in the process.
118 *
119 * @retval OPAL_ERR_NOT_AVAILABLE Silently ignore this component for
120 * the duration of the process (it may even be unloaded from the
121 * process).
122 *
123 * @retval anything_else The MCA base will print an error message
124 * ignore this component for the duration of the process (it may even
125 * be unloaded from the process).
126 *
127 * All MCA components can have an "open" function that is invoked once
128 * per process, when the component is located and loaded.
129 *
130 * This function should avoid registering MCA parameters (use the
131 * component "register" function for that; i.e.,
132 * mca_base_register_component_params_2_0_0_fn_t for that). Legacy
133 * components still register MCA params in their component "open"
134 * function, but their authors should update them to use the component
135 * "register" function.
136 *
137 * This function can also be used to allocate any resources necessary
138 * for the component (e.g., heap memory).
139 *
140 * This function should return OPAL_SUCCESS if it wishes to remain
141 * loaded in the process. Any other return value will cause the MCA
142 * base to unload the component. Although most components do not use
143 * this mechanism to force themselves to be unloaded (because if they
144 * are immediately unloaded, ompi_info will not display them), the
145 * mechanism is available should the need arise.
146 *
147 * If the component a) has no MCA parameters to register, b) no
148 * resources to allocate, and c) can always be used in a process
149 * (albiet perhaps not selected), it may provide NULL for this
150 * function. In this cause, the MCA will act as if it called the open
151 * function and it returned OPAL_SUCCESS.
152 */
153 typedef int (*mca_base_open_component_1_0_0_fn_t)(void);
154
155 /**
156 * MCA component close function.
157 *
158 * @retval OPAL_SUCCESS The component successfully shut down.
159 *
160 * @retval any_other_value Some error occurred, but is likely to be
161 * ignored.
162 *
163 * This function is invoked on a component after all of its modules
164 * have been finalized (according to the rules of its framework) and
165 * the component will never be used in the process again; the
166 * component may be unloaded from the process memory after the close
167 * function has been invoked.
168 *
169 * This function is typically used to release any resources still in
170 * use by the component.
171 *
172 * If the component has no resources to free, it may provide NULL for
173 * this function. In this case, the MCA will act as if it called the
174 * close function and it returned OPAL_SUCCESS.
175 */
176 typedef int (*mca_base_close_component_1_0_0_fn_t)(void);
177
178 /**
179 * MCA component query function.
180 *
181 * @retval OPAL_SUCCESS The component successfully queried.
182 *
183 * @retval any_other_value Some error occurred, but is likely to be
184 * ignored.
185 *
186 * @param module The module to be used if this component is selected.
187 *
188 * @param priority The priority of this component.
189 *
190 * This function is used by the mca_base_select function to find the
191 * highest priority component to select. Frameworks are free to
192 * implement their own query function, but must also implment their
193 * own select function as a result.
194 */
195 typedef int (*mca_base_query_component_2_0_0_fn_t)(mca_base_module_2_0_0_t **module, int *priority);
196
197 /**
198 * MCA component parameter registration function.
199 *
200 * @retval OPAL_SUCCESS This component successfully registered its
201 * parameters and can be used in this process.
202 * @retval OPAL_ERR_BAD_PARAM Indicates that the register function
203 * failed because an MCA parameter got an invalid/incorrect value.
204 *
205 * @retval anything_else The MCA will ignore this component for the
206 * duration of the process.
207 *
208 * If a component has a non-NULL parameter registration function, it
209 * will be invoked to register all MCA parameters associated with the
210 * component. This function is invoked *before* the component "open"
211 * function is invoked.
212 *
213 * The registration function should not allocate any resources that
214 * need to be freed (aside from registering MCA parameters).
215 * Specifically, strings that are passed to the MCA parameter
216 * registration functions are all internally copied; there's no need
217 * for the caller to keep them after registering a parameter. Hence,
218 * it is possible that the registration function will be the *only*
219 * function invoked on a component; component authors should take care
220 * that no resources are leaked in this case.
221 *
222 * This function should return OPAL_SUCCESS if it wishes to remain
223 * loaded in the process. Any other return value will cause the MCA
224 * base to unload the component. Although most components do not use
225 * this mechanism to force themselves to be unloaded (because if they
226 * are immediately unloaded, ompi_info will not display them), the
227 * mechanism is available should the need arise.
228 *
229 * Note that if the function returns OPAL_ERR_BAD_PARAM, it is
230 * possible (likely?) that the component didn't register all of its
231 * parameters. When this happens, ompi_info (and friends) will stop
232 * execution and print out all existing registered parameters from the
233 * entire framework (since ompi_info doesn't track individual
234 * component register failures). This allows a user to know exactly
235 * what value is incorrect, and from where it was set (e.g., via an
236 * MCA params file).
237 *
238 * If the component a) has no MCA parameters to register, b) no
239 * resources to allocate, and c) can always be used in a process
240 * (albiet perhaps not selected), it may provide NULL for this
241 * function. In this cause, the MCA will act as if it called the
242 * registration function and it returned OPAL_SUCCESS.
243 */
244 typedef int (*mca_base_register_component_params_2_0_0_fn_t)(void);
245
246
247 /**
248 * Maximum length of MCA project string names.
249 */
250 #define MCA_BASE_MAX_PROJECT_NAME_LEN 15
251 /**
252 * Maximum length of MCA framework string names.
253 */
254 #define MCA_BASE_MAX_TYPE_NAME_LEN 31
255 /**
256 * Maximum length of MCA component string names.
257 */
258 #define MCA_BASE_MAX_COMPONENT_NAME_LEN 63
259 /**
260 * Maximum length of MCA component variable names.
261 */
262 #define MCA_BASE_MAX_VARIABLE_NAME_LEN 63
263
264 /**
265 * Component flags (mca_component_flags field)
266 */
267 enum {
268 /** Always consider this component for selection. For this flag to
269 * work properly the component must always be built statically.
270 *
271 * Enforecement of this flag is left to the individual frameworks
272 * so as to limit its use. See discussion from the Open MPI
273 * face-to-face meeting Jan. 2017 */
274 MCA_BASE_COMPONENT_FLAG_REQUIRED = 1,
275 };
276
277 /**
278 * Common type for all MCA components.
279 *
280 * An instance of this type is always the first element in MCA
281 * components, allowing the component to be associated with a
282 * particular version of a specific framework, and to publish its own
283 * name and version.
284 */
285 struct mca_base_component_2_1_0_t {
286
287 int mca_major_version;
288 /**< Major number of the MCA. */
289 int mca_minor_version;
290 /**< Minor number of the MCA. */
291 int mca_release_version;
292 /**< Release number of the MCA. */
293
294 char mca_project_name[MCA_BASE_MAX_PROJECT_NAME_LEN + 1];
295 /**< String name of the project that this component belongs to. */
296 int mca_project_major_version;
297 /**< Major version number of the project that this component
298 belongs to. */
299 int mca_project_minor_version;
300 /**< Minor version number of the project that this component
301 belongs to. */
302 int mca_project_release_version;
303 /**< Release version number of the project that this component
304 belongs to. */
305
306 char mca_type_name[MCA_BASE_MAX_TYPE_NAME_LEN + 1];
307 /**< String name of the framework that this component belongs to. */
308 int mca_type_major_version;
309 /**< Major version number of the framework that this component
310 belongs to. */
311 int mca_type_minor_version;
312 /**< Minor version number of the framework that this component
313 belongs to. */
314 int mca_type_release_version;
315 /**< Release version number of the framework that this component
316 belongs to. */
317
318 char mca_component_name[MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
319 /**< This comopnent's string name. */
320 int mca_component_major_version;
321 /**< This component's major version number. */
322 int mca_component_minor_version;
323 /**< This component's minor version number. */
324 int mca_component_release_version;
325 /**< This component's release version number. */
326
327 mca_base_open_component_1_0_0_fn_t mca_open_component;
328 /**< Method for opening this component. */
329 mca_base_close_component_1_0_0_fn_t mca_close_component;
330 /**< Method for closing this component. */
331 mca_base_query_component_2_0_0_fn_t mca_query_component;
332 /**< Method for querying this component. */
333 mca_base_register_component_params_2_0_0_fn_t mca_register_component_params;
334 /**< Method for registering the component's MCA parameters */
335
336 int32_t mca_component_flags;
337 /**< flags for this component */
338
339 /** Extra space to allow for expansion in the future without
340 breaking older components. */
341 char reserved[28];
342 };
343 /** Unversioned convenience typedef; use this name in
344 frameworks/components to stay forward source-compatible */
345 typedef struct mca_base_component_2_1_0_t mca_base_component_t;
346 /** Versioned convenience typedef */
347 typedef struct mca_base_component_2_1_0_t mca_base_component_2_1_0_t;
348
349 /*
350 * Metadata Bit field parameters
351 */
352 #define MCA_BASE_METADATA_PARAM_NONE (uint32_t)0x00 /**< No Metadata flags */
353 #define MCA_BASE_METADATA_PARAM_CHECKPOINT (uint32_t)0x02 /**< Checkpoint enabled Component */
354 #define MCA_BASE_METADATA_PARAM_DEBUG (uint32_t)0x04 /**< Debug enabled/only Component */
355
356 /**
357 * Meta data for MCA v2.0.0 components.
358 */
359 struct mca_base_component_data_2_0_0_t {
360 uint32_t param_field;
361 /**< Metadata parameter bit field filled in by the parameters
362 defined above */
363
364 /** Extra space to allow for expansion in the future without
365 breaking older components. */
366 char reserved[32];
367 };
368 /** Unversioned convenience typedef; use this name in
369 frameworks/components to stay forward source-compatible */
370 typedef struct mca_base_component_data_2_0_0_t mca_base_component_data_t;
371 /** Versioned convenience typedef */
372 typedef struct mca_base_component_data_2_0_0_t mca_base_component_data_2_0_0_t;
373
374 /**
375 * Macro for framework author convenience.
376 *
377 * This macro is used by frameworks defining their component types,
378 * indicating that they subscribe to the MCA version 2.0.0. See
379 * component header files (e.g., coll.h) for examples of its usage.
380 */
381 #define MCA_BASE_VERSION_MAJOR 2
382 #define MCA_BASE_VERSION_MINOR 1
383 #define MCA_BASE_VERSION_RELEASE 0
384
385 #define MCA_BASE_MAKE_VERSION(level, MAJOR, MINOR, RELEASE) \
386 .mca_## level ##_major_version = MAJOR, \
387 .mca_## level ##_minor_version = MINOR, \
388 .mca_## level ##_release_version = RELEASE
389
390
391 #define MCA_BASE_VERSION_2_1_0(PROJECT, project_major, project_minor, project_release, TYPE, type_major, type_minor, type_release) \
392 .mca_major_version = MCA_BASE_VERSION_MAJOR, \
393 .mca_minor_version = MCA_BASE_VERSION_MINOR, \
394 .mca_release_version = MCA_BASE_VERSION_RELEASE, \
395 .mca_project_name = PROJECT, \
396 MCA_BASE_MAKE_VERSION(project, project_major, project_minor, project_release), \
397 .mca_type_name = TYPE, \
398 MCA_BASE_MAKE_VERSION(type, type_major, type_minor, type_release)
399
400 #define OPAL_MCA_BASE_VERSION_2_1_0(type, type_major, type_minor, type_release) \
401 MCA_BASE_VERSION_2_1_0("opal", OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, OPAL_RELEASE_VERSION, type, type_major, type_minor, type_release)
402
403 #endif /* OPAL_MCA_H */