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 */