root/opal/mca/shmem/sysv/shmem_sysv_module.c

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

DEFINITIONS

This source file includes following definitions.
  1. shmem_ds_reset
  2. module_init
  3. module_finalize
  4. ds_copy
  5. segment_create
  6. segment_attach
  7. segment_detach
  8. segment_unlink

   1 /*
   2  * Copyright (c) 2004-2008 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2007-2015 Cisco Systems, Inc.  All rights reserved.
  13  * Copyright (c) 2008      Sun Microsystems, Inc.  All rights reserved.
  14  * Copyright (c) 2010-2012 Los Alamos National Security, LLC.
  15  *                         All rights reserved.
  16  *
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 #include "opal_config.h"
  25 
  26 #include <errno.h>
  27 #ifdef HAVE_FCNTL_H
  28 #include <fcntl.h>
  29 #endif  /* HAVE_FCNTL_H */
  30 #ifdef HAVE_SYS_MMAN_H
  31 #include <sys/mman.h>
  32 #endif /* HAVE_SYS_MMAN_H */
  33 #ifdef HAVE_UNISTD_H
  34 #include <unistd.h>
  35 #endif /* HAVE_UNISTD_H */
  36 #ifdef HAVE_SYS_TYPES_H
  37 #include <sys/types.h>
  38 #endif /* HAVE_SYS_TYPES_H */
  39 #ifdef HAVE_SYS_IPC_H
  40 #include <sys/ipc.h>
  41 #endif /* HAVE_SYS_IPC_H */
  42 #if HAVE_SYS_SHM_H
  43 #include <sys/shm.h>
  44 #endif /* HAVE_SYS_SHM_H */
  45 #if HAVE_SYS_STAT_H
  46 #include <sys/stat.h>
  47 #endif /* HAVE_SYS_STAT_H */
  48 #include <string.h>
  49 #ifdef HAVE_NETDB_H
  50 #include <netdb.h>
  51 #endif /* HAVE_NETDB_H */
  52 
  53 #include "opal/constants.h"
  54 #include "opal_stdint.h"
  55 #include "opal/util/output.h"
  56 #include "opal/util/path.h"
  57 #include "opal/util/show_help.h"
  58 #include "opal/mca/shmem/shmem.h"
  59 #include "opal/mca/shmem/base/base.h"
  60 
  61 #include "shmem_sysv.h"
  62 
  63 /* for tons of debug output: -mca shmem_base_verbose 70 */
  64 
  65 /* ////////////////////////////////////////////////////////////////////////// */
  66 /* local functions */
  67 static int
  68 module_init(void);
  69 
  70 static int
  71 segment_create(opal_shmem_ds_t *ds_buf,
  72                const char *file_name,
  73                size_t size);
  74 
  75 static int
  76 ds_copy(const opal_shmem_ds_t *from,
  77         opal_shmem_ds_t *to);
  78 
  79 static void *
  80 segment_attach(opal_shmem_ds_t *ds_buf);
  81 
  82 static int
  83 segment_detach(opal_shmem_ds_t *ds_buf);
  84 
  85 static int
  86 segment_unlink(opal_shmem_ds_t *ds_buf);
  87 
  88 static int
  89 module_finalize(void);
  90 
  91 /* sysv shmem module */
  92 opal_shmem_sysv_module_t opal_shmem_sysv_module = {
  93     .super = {
  94         .module_init = module_init,
  95         .segment_create = segment_create,
  96         .ds_copy = ds_copy,
  97         .segment_attach = segment_attach,
  98         .segment_detach = segment_detach,
  99         .unlink = segment_unlink,
 100         .module_finalize = module_finalize
 101     }
 102 };
 103 
 104 /* ////////////////////////////////////////////////////////////////////////// */
 105 /* private utility functions */
 106 /* ////////////////////////////////////////////////////////////////////////// */
 107 
 108 /* ////////////////////////////////////////////////////////////////////////// */
 109 /**
 110  * completely resets the contents of *ds_buf
 111  */
 112 static inline void
 113 shmem_ds_reset(opal_shmem_ds_t *ds_buf)
 114 {
 115     /* don't print ds_buf info here, as we may be printing garbage. */
 116     OPAL_OUTPUT_VERBOSE(
 117         (70, opal_shmem_base_framework.framework_output,
 118          "%s: %s: shmem_ds_resetting\n",
 119          mca_shmem_sysv_component.super.base_version.mca_type_name,
 120          mca_shmem_sysv_component.super.base_version.mca_component_name)
 121     );
 122 
 123     ds_buf->seg_cpid = 0;
 124     OPAL_SHMEM_DS_RESET_FLAGS(ds_buf);
 125     ds_buf->seg_id = OPAL_SHMEM_DS_ID_INVALID;
 126     ds_buf->seg_size = 0;
 127     memset(ds_buf->seg_name, '\0', OPAL_PATH_MAX);
 128     ds_buf->seg_base_addr = (unsigned char *)-1;
 129 }
 130 
 131 /* ////////////////////////////////////////////////////////////////////////// */
 132 static int
 133 module_init(void)
 134 {
 135     /* nothing to do */
 136     return OPAL_SUCCESS;
 137 }
 138 
 139 /* ////////////////////////////////////////////////////////////////////////// */
 140 static int
 141 module_finalize(void)
 142 {
 143     /* nothing to do */
 144     return OPAL_SUCCESS;
 145 }
 146 
 147 /* ////////////////////////////////////////////////////////////////////////// */
 148 static int
 149 ds_copy(const opal_shmem_ds_t *from,
 150         opal_shmem_ds_t *to)
 151 {
 152     memcpy(to, from, sizeof(opal_shmem_ds_t));
 153 
 154     OPAL_OUTPUT_VERBOSE(
 155         (70, opal_shmem_base_framework.framework_output,
 156          "%s: %s: ds_copy complete "
 157          "from: (id: %d, size: %lu, "
 158          "name: %s flags: 0x%02x) "
 159          "to: (id: %d, size: %lu, "
 160          "name: %s flags: 0x%02x)\n",
 161          mca_shmem_sysv_component.super.base_version.mca_type_name,
 162          mca_shmem_sysv_component.super.base_version.mca_component_name,
 163          from->seg_id, (unsigned long)from->seg_size, from->seg_name,
 164          from->flags, to->seg_id, (unsigned long)to->seg_size, to->seg_name,
 165          to->flags)
 166     );
 167 
 168     return OPAL_SUCCESS;
 169 }
 170 
 171 /* ////////////////////////////////////////////////////////////////////////// */
 172 static int
 173 segment_create(opal_shmem_ds_t *ds_buf,
 174                const char *file_name,
 175                size_t size)
 176 {
 177     int rc = OPAL_SUCCESS;
 178     pid_t my_pid = getpid();
 179     /* the real size of the shared memory segment.  this includes enough space
 180      * to store our segment header.
 181      */
 182     size_t real_size = size + sizeof(opal_shmem_seg_hdr_t);
 183     opal_shmem_seg_hdr_t *seg_hdrp = MAP_FAILED;
 184 
 185     /* init the contents of opal_shmem_ds_t */
 186     shmem_ds_reset(ds_buf);
 187 
 188     /* for sysv shared memory we don't have to worry about the backing store
 189      * being located on a network file system... so no check is needed here.
 190      */
 191 
 192     /* create a new shared memory segment and save the shmid. note the use of
 193      * real_size here
 194      */
 195     if (-1 == (ds_buf->seg_id = shmget(IPC_PRIVATE, real_size,
 196                                        IPC_CREAT | IPC_EXCL | S_IRWXU))) {
 197         int err = errno;
 198         char hn[OPAL_MAXHOSTNAMELEN];
 199         gethostname(hn, sizeof(hn));
 200         opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn,
 201                        "shmget(2)", "", strerror(err), err);
 202         rc = OPAL_ERROR;
 203         goto out;
 204     }
 205     /* attach to the sement */
 206     else if ((void *)-1 == (seg_hdrp = shmat(ds_buf->seg_id, NULL, 0))) {
 207         int err = errno;
 208         char hn[OPAL_MAXHOSTNAMELEN];
 209         gethostname(hn, sizeof(hn));
 210         opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn,
 211                        "shmat(2)", "", strerror(err), err);
 212         shmctl(ds_buf->seg_id, IPC_RMID, NULL);
 213         rc = OPAL_ERROR;
 214         goto out;
 215     }
 216     /* mark the segment for destruction - if we are here, then the run-time
 217      * component selection test detected adequate support for this type of
 218      * thing.
 219      */
 220     else if (0 != shmctl(ds_buf->seg_id, IPC_RMID, NULL)) {
 221         int err = errno;
 222         char hn[OPAL_MAXHOSTNAMELEN];
 223         gethostname(hn, sizeof(hn));
 224         opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn,
 225                        "shmctl(2)", "", strerror(err), err);
 226         rc = OPAL_ERROR;
 227         goto out;
 228     }
 229     /* all is well */
 230     else {
 231         /* -- initialize the shared memory segment -- */
 232         opal_atomic_rmb();
 233 
 234         /* init segment lock */
 235         opal_atomic_lock_init(&seg_hdrp->lock, OPAL_ATOMIC_LOCK_UNLOCKED);
 236         /* i was the creator of this segment, so note that fact */
 237         seg_hdrp->cpid = my_pid;
 238 
 239         opal_atomic_wmb();
 240 
 241         /* -- initialize the contents of opal_shmem_ds_t -- */
 242         ds_buf->seg_cpid = my_pid;
 243         ds_buf->seg_size = real_size;
 244         ds_buf->seg_base_addr = (unsigned char *)seg_hdrp;
 245 
 246         /* notice that we are not setting ds_buf->name here. sysv doesn't use
 247          * it, so don't worry about it - shmem_ds_reset took care of
 248          * initialization, so we aren't passing garbage around.
 249          */
 250 
 251         /* set "valid" bit because setment creation was successful */
 252         OPAL_SHMEM_DS_SET_VALID(ds_buf);
 253 
 254         OPAL_OUTPUT_VERBOSE(
 255             (70, opal_shmem_base_framework.framework_output,
 256              "%s: %s: create successful "
 257              "(id: %d, size: %lu, name: %s)\n",
 258              mca_shmem_sysv_component.super.base_version.mca_type_name,
 259              mca_shmem_sysv_component.super.base_version.mca_component_name,
 260              ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name)
 261         );
 262     }
 263 
 264 out:
 265     /* an error occured, so invalidate the shmem object and release any
 266      * allocated resources.
 267      */
 268     if (OPAL_SUCCESS != rc) {
 269         /* best effort to delete the segment. */
 270         if ((void *)-1 != seg_hdrp) {
 271             shmdt((char*)seg_hdrp);
 272         }
 273         shmctl(ds_buf->seg_id, IPC_RMID, NULL);
 274 
 275         /* always invalidate in this error path */
 276         shmem_ds_reset(ds_buf);
 277     }
 278     return rc;
 279 }
 280 
 281 /* ////////////////////////////////////////////////////////////////////////// */
 282 /**
 283  * segment_attach can only be called after a successful call to segment_create
 284  */
 285 static void *
 286 segment_attach(opal_shmem_ds_t *ds_buf)
 287 {
 288     pid_t my_pid = getpid();
 289 
 290     if (my_pid != ds_buf->seg_cpid) {
 291         if ((void *)-1 == (ds_buf->seg_base_addr = shmat(ds_buf->seg_id, NULL,
 292                                                          0))) {
 293             int err = errno;
 294             char hn[OPAL_MAXHOSTNAMELEN];
 295             gethostname(hn, sizeof(hn));
 296             opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn,
 297                            "shmat(2)", "", strerror(err), err);
 298             shmctl(ds_buf->seg_id, IPC_RMID, NULL);
 299             return NULL;
 300         }
 301     }
 302     /* else i was the segment creator.  nothing to do here because all the hard
 303      * work was done in segment_create :-).
 304      */
 305 
 306     OPAL_OUTPUT_VERBOSE(
 307         (70, opal_shmem_base_framework.framework_output,
 308          "%s: %s: attach successful "
 309          "(id: %d, size: %lu, name: %s)\n",
 310          mca_shmem_sysv_component.super.base_version.mca_type_name,
 311          mca_shmem_sysv_component.super.base_version.mca_component_name,
 312          ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name)
 313     );
 314 
 315     /* update returned base pointer with an offset that hides our stuff */
 316     return (ds_buf->seg_base_addr + sizeof(opal_shmem_seg_hdr_t));
 317 }
 318 
 319 /* ////////////////////////////////////////////////////////////////////////// */
 320 static int
 321 segment_detach(opal_shmem_ds_t *ds_buf)
 322 {
 323     int rc = OPAL_SUCCESS;
 324 
 325     OPAL_OUTPUT_VERBOSE(
 326         (70, opal_shmem_base_framework.framework_output,
 327          "%s: %s: detaching "
 328          "(id: %d, size: %lu, name: %s)\n",
 329          mca_shmem_sysv_component.super.base_version.mca_type_name,
 330          mca_shmem_sysv_component.super.base_version.mca_component_name,
 331          ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name)
 332     );
 333 
 334     if (0 != shmdt((char*)ds_buf->seg_base_addr)) {
 335         int err = errno;
 336         char hn[OPAL_MAXHOSTNAMELEN];
 337         gethostname(hn, sizeof(hn));
 338         opal_show_help("help-opal-shmem-sysv.txt", "sys call fail", 1, hn,
 339                        "shmdt(2)", "", strerror(err), err);
 340         rc = OPAL_ERROR;
 341     }
 342 
 343     /* reset the contents of the opal_shmem_ds_t associated with this
 344      * shared memory segment.
 345      */
 346     shmem_ds_reset(ds_buf);
 347     return rc;
 348 }
 349 
 350 /* ////////////////////////////////////////////////////////////////////////// */
 351 static int
 352 segment_unlink(opal_shmem_ds_t *ds_buf)
 353 {
 354     /* not much unlink work needed for sysv */
 355 
 356     OPAL_OUTPUT_VERBOSE(
 357         (70, opal_shmem_base_framework.framework_output,
 358          "%s: %s: unlinking "
 359          "(id: %d, size: %lu, name: %s)\n",
 360          mca_shmem_sysv_component.super.base_version.mca_type_name,
 361          mca_shmem_sysv_component.super.base_version.mca_component_name,
 362          ds_buf->seg_id, (unsigned long)ds_buf->seg_size, ds_buf->seg_name)
 363     );
 364 
 365     /* don't completely reset the opal_shmem_ds_t.  in particular, only reset
 366      * the id and flip the invalid bit.  size and name values will remain valid
 367      * across unlinks. other information stored in flags will remain untouched.
 368      */
 369     ds_buf->seg_id = OPAL_SHMEM_DS_ID_INVALID;
 370     /* note: this is only chaning the valid bit to 0. */
 371     OPAL_SHMEM_DS_INVALIDATE(ds_buf);
 372     return OPAL_SUCCESS;
 373 }
 374 

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