root/ompi/info/info.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ompi_mpiinfo_init
  2. ompi_info_dup
  3. ompi_info_dup_mpistandard
  4. ompi_info_set
  5. ompi_info_set_value_enum
  6. ompi_info_get
  7. ompi_info_get_value_enum
  8. ompi_info_get_bool
  9. ompi_info_delete
  10. ompi_info_get_valuelen
  11. ompi_info_get_nthkey
  12. ompi_info_get_nkeys
  13. ompi_mpiinfo_finalize
  14. info_constructor
  15. info_destructor
  16. ompi_info_free

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2017 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) 2007-2018 Cisco Systems, Inc.  All rights reserved
  14  * Copyright (c) 2009      Sun Microsystems, Inc.  All rights reserved.
  15  * Copyright (c) 2012-2015 Los Alamos National Security, LLC. All rights
  16  *                         reserved.
  17  * Copyright (c) 2015-2018 Research Organization for Information Science
  18  *                         and Technology (RIST). All rights reserved.
  19  * Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  25  */
  26 
  27 #include "ompi_config.h"
  28 #include "ompi/constants.h"
  29 
  30 #include <string.h>
  31 #include <errno.h>
  32 #include <stdlib.h>
  33 #ifdef HAVE_UNISTD_H
  34 #include <unistd.h>
  35 #endif
  36 #include <limits.h>
  37 #include <ctype.h>
  38 #ifdef HAVE_SYS_UTSNAME_H
  39 #include <sys/utsname.h>
  40 #endif
  41 #include <assert.h>
  42 
  43 #include "opal/util/argv.h"
  44 #include "opal/util/opal_getcwd.h"
  45 #include "opal/util/output.h"
  46 #include "opal/util/info.h"
  47 
  48 #include "ompi/info/info.h"
  49 #include "ompi/runtime/mpiruntime.h"
  50 #include "ompi/runtime/params.h"
  51 
  52 /*
  53  * Global variables
  54  */
  55 ompi_predefined_info_t ompi_mpi_info_null = {{{{{0}}}}};
  56 ompi_predefined_info_t *ompi_mpi_info_null_addr = &ompi_mpi_info_null;
  57 ompi_predefined_info_t ompi_mpi_info_env = {{{{{0}}}}};
  58 
  59 /*
  60  * Local functions
  61  */
  62 static void info_constructor(ompi_info_t *info);
  63 static void info_destructor(ompi_info_t *info);
  64 
  65 /*
  66  * ompi_info_t classes
  67  */
  68 OBJ_CLASS_INSTANCE(ompi_info_t,
  69                    opal_info_t,
  70                    info_constructor,
  71                    info_destructor);
  72 
  73 /*
  74  * The global fortran <-> C translation table
  75  */
  76 opal_pointer_array_t ompi_info_f_to_c_table = {{0}};
  77 
  78 /*
  79  * This function is called during ompi_init and initializes the
  80  * fortran to C translation table. It also fills in the values
  81  * for the MPI_INFO_GET_ENV object
  82  */
  83 int ompi_mpiinfo_init(void)
  84 {
  85     char val[OPAL_MAXHOSTNAMELEN];
  86     char *cptr;
  87 
  88     /* initialize table */
  89 
  90     OBJ_CONSTRUCT(&ompi_info_f_to_c_table, opal_pointer_array_t);
  91     if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_info_f_to_c_table, 0,
  92                                                 OMPI_FORTRAN_HANDLE_MAX, 16) ) {
  93         return OMPI_ERROR;
  94     }
  95 
  96     /* Create MPI_INFO_NULL */
  97     OBJ_CONSTRUCT(&ompi_mpi_info_null.info, ompi_info_t);
  98     assert(ompi_mpi_info_null.info.i_f_to_c_index == 0);
  99 
 100     /* Create MPI_INFO_ENV */
 101     OBJ_CONSTRUCT(&ompi_mpi_info_env.info, ompi_info_t);
 102     assert(ompi_mpi_info_env.info.i_f_to_c_index == 1);
 103 
 104     /* fill the env info object */
 105 
 106     /* command for this app_context */
 107     if (NULL != (cptr = getenv("OMPI_COMMAND"))) {
 108         opal_info_set(&ompi_mpi_info_env.info.super, "command", cptr);
 109     }
 110 
 111     /* space-separated list of argv for this command */
 112     if (NULL != (cptr = getenv("OMPI_ARGV"))) {
 113         opal_info_set(&ompi_mpi_info_env.info.super, "argv", cptr);
 114     }
 115 
 116     /* max procs for the entire job */
 117     if (NULL != (cptr = getenv("OMPI_MCA_orte_ess_num_procs"))) {
 118         opal_info_set(&ompi_mpi_info_env.info.super, "maxprocs", cptr);
 119         /* Open MPI does not support the "soft" option, so set it to maxprocs */
 120         opal_info_set(&ompi_mpi_info_env.info.super, "soft", cptr);
 121     }
 122 
 123     /* local host name */
 124     gethostname(val, sizeof(val));
 125     opal_info_set(&ompi_mpi_info_env.info.super, "host", val);
 126 
 127     /* architecture name */
 128     if (NULL != (cptr = getenv("OMPI_MCA_orte_cpu_type"))) {
 129         opal_info_set(&ompi_mpi_info_env.info.super, "arch", cptr);
 130     }
 131 #ifdef HAVE_SYS_UTSNAME_H
 132     else {
 133         struct utsname sysname;
 134         uname(&sysname);
 135         cptr = sysname.machine;
 136         opal_info_set(&ompi_mpi_info_env.info.super, "arch", cptr);
 137     }
 138 #endif
 139 
 140     /* initial working dir of this process - only set when
 141      * run by mpiexec as we otherwise have no reliable way
 142      * of determining the value
 143      */
 144     if (NULL != (cptr = getenv("OMPI_MCA_initial_wdir"))) {
 145         opal_info_set(&ompi_mpi_info_env.info.super, "wdir", cptr);
 146     }
 147 
 148     /* provide the REQUESTED thread level - may be different
 149      * than the ACTUAL thread level you get.
 150      * ugly, but have to do a switch to find the string representation */
 151     switch (ompi_mpi_thread_requested) {
 152     case MPI_THREAD_SINGLE:
 153         opal_info_set(&ompi_mpi_info_env.info.super, "thread_level", "MPI_THREAD_SINGLE");
 154         break;
 155     case MPI_THREAD_FUNNELED:
 156         opal_info_set(&ompi_mpi_info_env.info.super, "thread_level", "MPI_THREAD_FUNNELED");
 157         break;
 158     case MPI_THREAD_SERIALIZED:
 159         opal_info_set(&ompi_mpi_info_env.info.super, "thread_level", "MPI_THREAD_SERIALIZED");
 160         break;
 161     case MPI_THREAD_MULTIPLE:
 162         opal_info_set(&ompi_mpi_info_env.info.super, "thread_level", "MPI_THREAD_MULTIPLE");
 163         break;
 164     default:
 165         /* do nothing - don't know the value */
 166         break;
 167     }
 168 
 169     /**** now some OMPI-specific values that other MPIs may not provide ****/
 170 
 171     /* the number of app_contexts in this job */
 172     if (NULL != (cptr = getenv("OMPI_NUM_APP_CTX"))) {
 173         opal_info_set(&ompi_mpi_info_env.info.super, "ompi_num_apps", cptr);
 174     }
 175 
 176     /* space-separated list of first MPI rank of each app_context */
 177     if (NULL != (cptr = getenv("OMPI_FIRST_RANKS"))) {
 178         opal_info_set(&ompi_mpi_info_env.info.super, "ompi_first_rank", cptr);
 179     }
 180 
 181     /* space-separated list of num procs for each app_context */
 182     if (NULL != (cptr = getenv("OMPI_APP_CTX_NUM_PROCS"))) {
 183         opal_info_set(&ompi_mpi_info_env.info.super, "ompi_np", cptr);
 184     }
 185 
 186     /* location of the directory containing any prepositioned files
 187      * the user may have requested
 188      */
 189     if (NULL != (cptr = getenv("OMPI_FILE_LOCATION"))) {
 190         opal_info_set(&ompi_mpi_info_env.info.super, "ompi_positioned_file_dir", cptr);
 191     }
 192 
 193     /* All done */
 194 
 195     return OMPI_SUCCESS;
 196 }
 197 
 198 // Generally ompi_info_t processing is handled by opal_info_t now.
 199 // But to avoid compiler warnings and to avoid having to constantly
 200 // change code to mpiinfo->super to make MPI code use the opal_info_t
 201 // it's convenient to have ompi_info_t wrappers for some of the opal_info_t
 202 // related calls:
 203 
 204 int ompi_info_dup (ompi_info_t *info, ompi_info_t **newinfo) {
 205     return opal_info_dup (&(info->super), (opal_info_t **)newinfo);
 206 }
 207 int ompi_info_dup_mpistandard (ompi_info_t *info, ompi_info_t **newinfo) {
 208     return opal_info_dup_mpistandard (&(info->super), (opal_info_t **)newinfo);
 209 }
 210 int ompi_info_set (ompi_info_t *info, const char *key, const char *value) {
 211     return opal_info_set (&(info->super), key, value);
 212 }
 213 int ompi_info_set_value_enum (ompi_info_t *info, const char *key, int value,
 214                               mca_base_var_enum_t *var_enum)
 215 {
 216     return opal_info_set_value_enum (&(info->super), key, value, var_enum);
 217 }
 218 int ompi_info_get (ompi_info_t *info, const char *key, int valuelen,
 219                    char *value, int *flag)
 220 {
 221     return opal_info_get (&(info->super), key, valuelen, value, flag);
 222 }
 223 int ompi_info_get_value_enum (ompi_info_t *info, const char *key, int *value,
 224                               int default_value, mca_base_var_enum_t *var_enum,
 225                               int *flag)
 226 {
 227     return opal_info_get_value_enum (&(info->super), key, value,
 228                               default_value, var_enum, flag);
 229 }
 230 int ompi_info_get_bool(ompi_info_t *info, char *key, bool *value, int *flag) {
 231     return opal_info_get_bool(&(info->super), key, value, flag);
 232 }
 233 int ompi_info_delete (ompi_info_t *info, const char *key) {
 234     return opal_info_delete (&(info->super), key);
 235 }
 236 int ompi_info_get_valuelen (ompi_info_t *info, const char *key, int *valuelen,
 237                             int *flag)
 238 {
 239     return opal_info_get_valuelen (&(info->super), key, valuelen, flag);
 240 }
 241 int ompi_info_get_nthkey (ompi_info_t *info, int n, char *key) {
 242     return opal_info_get_nthkey (&(info->super), n, key);
 243 }
 244 int ompi_info_get_nkeys(ompi_info_t *info, int *nkeys)
 245 {
 246     return opal_info_get_nkeys (&(info->super), nkeys);
 247 }
 248 
 249 
 250 /*
 251  * Shut down MPI_Info handling
 252  */
 253 int ompi_mpiinfo_finalize(void)
 254 {
 255     size_t i, max;
 256     ompi_info_t *info;
 257     opal_list_item_t *item;
 258     opal_info_entry_t *entry;
 259     bool found = false;
 260 
 261     OBJ_DESTRUCT(&ompi_mpi_info_null);
 262     OBJ_DESTRUCT(&ompi_mpi_info_env);
 263 
 264     /* Go through the f2c table and see if anything is left.  Free them
 265        all. */
 266 
 267     max = opal_pointer_array_get_size(&ompi_info_f_to_c_table);
 268     for (i = 2; i < max; ++i) {
 269         info = (ompi_info_t *)opal_pointer_array_get_item(&ompi_info_f_to_c_table, i);
 270 
 271         /* If the info was freed but still exists because the user
 272            told us to never free handles, then do an OBJ_RELEASE it
 273            and all is well.  Then get the value again and see if it's
 274            actually been freed. */
 275 
 276         if (NULL != info && ompi_debug_no_free_handles && info->i_freed) {
 277             OBJ_RELEASE(info);
 278             info = (ompi_info_t *)opal_pointer_array_get_item(&ompi_info_f_to_c_table, i);
 279         }
 280 
 281         /* If it still exists here and was never freed, then it's an
 282            orphan */
 283 
 284         if (NULL != info) {
 285 
 286             /* If the user wanted warnings about MPI object leaks, print out
 287                a message */
 288 
 289             if (!info->i_freed && ompi_debug_show_handle_leaks) {
 290                 if (ompi_debug_show_handle_leaks) {
 291                     opal_output(0, "WARNING: MPI_Info still allocated at MPI_FINALIZE");
 292 
 293                     for (item = opal_list_get_first(&info->super.super);
 294                          opal_list_get_end(&(info->super.super)) != item;
 295                          item = opal_list_get_next(item)) {
 296                         entry = (opal_info_entry_t *) item;
 297                         opal_output(0, "WARNING:   key=\"%s\", value=\"%s\"",
 298                                     entry->ie_key,
 299                                     NULL != entry->ie_value ? entry->ie_value : "(null)");
 300                         found = true;
 301                     }
 302                 }
 303                 OBJ_RELEASE(info);
 304             }
 305 
 306             /* Don't bother setting each element back down to NULL; it
 307                would just take a lot of thread locks / unlocks and
 308                since we're destroying everything, it isn't worth it */
 309 
 310             if (!found && ompi_debug_show_handle_leaks) {
 311                 opal_output(0, "WARNING:   (no keys)");
 312             }
 313         }
 314     }
 315 
 316     /* All done -- destroy the table */
 317 
 318     OBJ_DESTRUCT(&ompi_info_f_to_c_table);
 319     return OPAL_SUCCESS;
 320 }
 321 
 322 
 323 
 324 /*
 325  * This function is invoked when OBJ_NEW() is called. Here, we add this
 326  * info pointer to the table and then store its index as the handle
 327  */
 328 static void info_constructor(ompi_info_t *info)
 329 {
 330     info->i_f_to_c_index = opal_pointer_array_add(&ompi_info_f_to_c_table,
 331                                                   info);
 332     info->i_freed = false;
 333 
 334 /* 
 335  * If the user doesn't want us to ever free it, then add an extra
 336  * RETAIN here 
 337  */
 338     if (ompi_debug_no_free_handles) {
 339         OBJ_RETAIN(&(info->super));
 340     }
 341 }
 342 
 343 /*
 344  *  * This function is called during OBJ_DESTRUCT of "info". When this
 345  *   * done, we need to remove the entry from the opal fortran to C
 346  *    * translation table
 347  *     */
 348 static void info_destructor(ompi_info_t *info)
 349 {
 350    /* reset the &ompi_info_f_to_c_table entry - make sure that the
 351       entry is in the table */
 352 
 353     if (MPI_UNDEFINED != info->i_f_to_c_index &&
 354         NULL != opal_pointer_array_get_item(&ompi_info_f_to_c_table,
 355                                             info->i_f_to_c_index)){
 356         opal_pointer_array_set_item(&ompi_info_f_to_c_table,
 357                                     info->i_f_to_c_index, NULL);
 358     }
 359 
 360 }
 361 
 362 
 363 /*
 364  * Free an info handle and all of its keys and values.
 365  */
 366 int ompi_info_free (ompi_info_t **info)
 367 {
 368     (*info)->i_freed = true;
 369     OBJ_RELEASE(*info);
 370     *info = MPI_INFO_NULL;
 371     return MPI_SUCCESS;
 372 }

/* [<][>][^][v][top][bottom][index][help] */