root/oshmem/mca/sshmem/mmap/sshmem_mmap_module.c

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

DEFINITIONS

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

   1 /*
   2  * Copyright (c) 2014      Mellanox Technologies, Inc.
   3  *                         All rights reserved.
   4  * Copyright (c) 2019      Research Organization for Information Science
   5  *                         and Technology (RIST).  All rights reserved.
   6  * $COPYRIGHT$
   7  *
   8  * Additional copyrights may follow
   9  *
  10  * $HEADER$
  11  */
  12 
  13 #include "oshmem_config.h"
  14 
  15 #include <errno.h>
  16 #ifdef HAVE_FCNTL_H
  17 #include <fcntl.h>
  18 #endif  /* HAVE_FCNTL_H */
  19 #ifdef HAVE_SYS_MMAN_H
  20 #include <sys/mman.h>
  21 #endif /* HAVE_SYS_MMAN_H */
  22 #ifdef HAVE_UNISTD_H
  23 #include <unistd.h>
  24 #endif /* HAVE_UNISTD_H */
  25 #ifdef HAVE_SYS_TYPES_H
  26 #include <sys/types.h>
  27 #endif /* HAVE_SYS_TYPES_H */
  28 #include <string.h>
  29 #ifdef HAVE_NETDB_H
  30 #include <netdb.h>
  31 #endif /* HAVE_NETDB_H */
  32 #include <time.h>
  33 #ifdef HAVE_SYS_STAT_H
  34 #include <sys/stat.h>
  35 #endif /* HAVE_SYS_STAT_H */
  36 
  37 #include "opal/constants.h"
  38 #include "opal/util/output.h"
  39 #include "opal/util/path.h"
  40 #include "opal/util/show_help.h"
  41 
  42 #include "oshmem/proc/proc.h"
  43 #include "oshmem/mca/sshmem/sshmem.h"
  44 #include "oshmem/mca/sshmem/base/base.h"
  45 #include "oshmem/util/oshmem_util.h"
  46 
  47 #include "sshmem_mmap.h"
  48 
  49 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
  50 #    define MAP_ANONYMOUS MAP_ANON
  51 #endif /* MAP_ANONYMOUS and MAP_ANON */
  52 
  53 #if !defined(MAP_FAILED)
  54 #    define MAP_FAILED ((char*)-1)
  55 #endif /* MAP_FAILED */
  56 
  57 /* ////////////////////////////////////////////////////////////////////////// */
  58 /*local functions */
  59 /* local functions */
  60 static int
  61 module_init(void);
  62 
  63 static int
  64 segment_create(map_segment_t *ds_buf,
  65                const char *file_name,
  66                size_t size, long hint);
  67 
  68 static void *
  69 segment_attach(map_segment_t *ds_buf, sshmem_mkey_t *mkey);
  70 
  71 static int
  72 segment_detach(map_segment_t *ds_buf, sshmem_mkey_t *mkey);
  73 
  74 static int
  75 segment_unlink(map_segment_t *ds_buf);
  76 
  77 static int
  78 module_finalize(void);
  79 
  80 /*
  81  * mmap shmem module
  82  */
  83 mca_sshmem_mmap_module_t mca_sshmem_mmap_module = {
  84     /* super */
  85     {
  86         module_init,
  87         segment_create,
  88         segment_attach,
  89         segment_detach,
  90         segment_unlink,
  91         module_finalize
  92     }
  93 };
  94 
  95 /* ////////////////////////////////////////////////////////////////////////// */
  96 static int
  97 module_init(void)
  98 {
  99     /* nothing to do */
 100     return OSHMEM_SUCCESS;
 101 }
 102 
 103 /* ////////////////////////////////////////////////////////////////////////// */
 104 static int
 105 module_finalize(void)
 106 {
 107     /* nothing to do */
 108     return OSHMEM_SUCCESS;
 109 }
 110 
 111 
 112 static int
 113 segment_create(map_segment_t *ds_buf,
 114                const char *file_name,
 115                size_t size, long hint)
 116 {
 117     int rc = OSHMEM_SUCCESS;
 118     void *addr = NULL;
 119 
 120     assert(ds_buf);
 121 
 122     if (hint) {
 123         return OSHMEM_ERR_NOT_IMPLEMENTED;
 124     }
 125 
 126     /* init the contents of map_segment_t */
 127     shmem_ds_reset(ds_buf);
 128 
 129     addr = mmap((void *)mca_sshmem_base_start_address,
 130                 size,
 131                 PROT_READ | PROT_WRITE,
 132                 MAP_PRIVATE |
 133 #if defined(MAP_ANONYMOUS)
 134                 MAP_ANONYMOUS |
 135 #endif
 136                 MAP_FIXED,
 137                 -1,
 138                 0);
 139 
 140     if (MAP_FAILED == addr) {
 141         opal_show_help("help-oshmem-sshmem.txt",
 142                 "create segment failure",
 143                 true,
 144                 "mmap",
 145                 ompi_process_info.nodename, (unsigned long long) size,
 146                 strerror(errno), errno);
 147         opal_show_help("help-oshmem-sshmem-mmap.txt",
 148                        "mmap:create segment failure",
 149                        true);
 150         return OSHMEM_ERR_OUT_OF_RESOURCE;
 151     }
 152 
 153     ds_buf->type = MAP_SEGMENT_ALLOC_MMAP;
 154     if (mca_sshmem_mmap_component.is_anonymous) {
 155         /*
 156          * Segment attach is not called for anonymous mmap
 157          */
 158         ds_buf->seg_id = MAP_SEGMENT_SHM_INVALID;
 159     } else {
 160         /*
 161          * Warning: implied that input file name has a fixed format
 162          * and pe which is stored as segment identifier is used in file name
 163          * generation during segment attachment
 164          */
 165         ds_buf->seg_id = oshmem_my_proc_id();
 166     }
 167     ds_buf->super.va_base = addr;
 168     ds_buf->seg_size      = size;
 169     ds_buf->super.va_end  = (void*)((uintptr_t)ds_buf->super.va_base + ds_buf->seg_size);
 170 
 171     OPAL_OUTPUT_VERBOSE(
 172           (70, oshmem_sshmem_base_framework.framework_output,
 173            "%s: %s: create %s "
 174            "(id: %d, addr: %p size: %lu)\n",
 175            mca_sshmem_mmap_component.super.base_version.mca_type_name,
 176            mca_sshmem_mmap_component.super.base_version.mca_component_name,
 177            (rc ? "failure" : "successful"),
 178            ds_buf->seg_id, ds_buf->super.va_base, (unsigned long)ds_buf->seg_size)
 179       );
 180 
 181     return rc;
 182 }
 183 
 184 /* ////////////////////////////////////////////////////////////////////////// */
 185 /**
 186  * segment_attach can only be called after a successful call to segment_create
 187  */
 188 static void *
 189 segment_attach(map_segment_t *ds_buf, sshmem_mkey_t *mkey)
 190 {
 191     void *addr = NULL;
 192 
 193     assert(ds_buf);
 194     assert(mkey->va_base == 0);
 195 
 196     if (MAP_SEGMENT_SHM_INVALID == (int)(mkey->u.key)) {
 197         return (mkey->va_base);
 198     }
 199 
 200     if (mca_sshmem_mmap_component.is_anonymous) {
 201         /*
 202          * Note: segment attach for anonymous mmap
 203          * is not called due to invalid segment id
 204          */
 205         addr = mmap((void *)mca_sshmem_base_start_address,
 206                     ds_buf->seg_size,
 207                     PROT_READ | PROT_WRITE,
 208                     MAP_SHARED |
 209 #if defined(MAP_ANONYMOUS)
 210                     MAP_ANONYMOUS |
 211 #endif
 212                     MAP_FIXED,
 213                     -1,
 214                     0);
 215     } else {
 216         char *file_name = NULL;
 217         if (NULL == (file_name = oshmem_get_unique_file_name(mkey->u.key))) {
 218             OPAL_OUTPUT(
 219                 (oshmem_sshmem_base_framework.framework_output,
 220                 "Can't get file name")
 221             );
 222             return NULL;
 223         }
 224 
 225         int fd;
 226         if (-1 == (fd = open(file_name, O_CREAT | O_RDWR, 0600))) {
 227             OPAL_OUTPUT(
 228                 (oshmem_sshmem_base_framework.framework_output,
 229                  "file open failed: %s", strerror(errno))
 230             );
 231             free(file_name);
 232             return NULL;
 233         }
 234         free(file_name);
 235 
 236         addr = mmap((void *)NULL,
 237                     ds_buf->seg_size,
 238                     PROT_READ | PROT_WRITE,
 239                     MAP_SHARED,
 240                     fd,
 241                     0);
 242 
 243         if (0 != close(fd)) {
 244             OPAL_OUTPUT(
 245                 (oshmem_sshmem_base_framework.framework_output,
 246                 "file close failed: %s", strerror(errno))
 247             );
 248         }
 249     }
 250 
 251     if (MAP_FAILED == addr) {
 252         OPAL_OUTPUT(
 253             (oshmem_sshmem_base_framework.framework_output,
 254              "Failed to mmap() %llu bytes (errno=%d)",
 255              (unsigned long long)ds_buf->seg_size, errno)
 256             );
 257         return NULL;
 258     }
 259 
 260     mkey->va_base = addr;
 261 
 262     OPAL_OUTPUT_VERBOSE(
 263         (70, oshmem_sshmem_base_framework.framework_output,
 264          "%s: %s: attach successful "
 265             "(id: %d, addr: %p size: %lu | va_base: 0x%p len: %d key %llx)\n",
 266             mca_sshmem_mmap_component.super.base_version.mca_type_name,
 267             mca_sshmem_mmap_component.super.base_version.mca_component_name,
 268             ds_buf->seg_id, ds_buf->super.va_base, (unsigned long)ds_buf->seg_size,
 269             mkey->va_base, mkey->len, (unsigned long long)mkey->u.key)
 270         );
 271 
 272     /* update returned base pointer with an offset that hides our stuff */
 273     return (mkey->va_base);
 274 }
 275 
 276 /* ////////////////////////////////////////////////////////////////////////// */
 277 static int
 278 segment_detach(map_segment_t *ds_buf, sshmem_mkey_t *mkey)
 279 {
 280     int rc = OSHMEM_SUCCESS;
 281 
 282     assert(ds_buf);
 283 
 284     OPAL_OUTPUT_VERBOSE(
 285         (70, oshmem_sshmem_base_framework.framework_output,
 286          "%s: %s: detaching "
 287             "(id: %d, addr: %p size: %lu)\n",
 288             mca_sshmem_mmap_component.super.base_version.mca_type_name,
 289             mca_sshmem_mmap_component.super.base_version.mca_component_name,
 290             ds_buf->seg_id, ds_buf->super.va_base, (unsigned long)ds_buf->seg_size)
 291     );
 292 
 293     munmap((void *)ds_buf->super.va_base, ds_buf->seg_size);
 294 
 295     /* reset the contents of the map_segment_t associated with this
 296      * shared memory segment.
 297      */
 298     shmem_ds_reset(ds_buf);
 299 
 300     return rc;
 301 }
 302 
 303 /* ////////////////////////////////////////////////////////////////////////// */
 304 static int
 305 segment_unlink(map_segment_t *ds_buf)
 306 {
 307     /* not much unlink work needed for sysv */
 308 
 309     OPAL_OUTPUT_VERBOSE(
 310         (70, oshmem_sshmem_base_framework.framework_output,
 311          "%s: %s: unlinking "
 312             "(id: %d, addr: %p size: %lu)\n",
 313             mca_sshmem_mmap_component.super.base_version.mca_type_name,
 314             mca_sshmem_mmap_component.super.base_version.mca_component_name,
 315             ds_buf->seg_id, ds_buf->super.va_base, (unsigned long)ds_buf->seg_size)
 316     );
 317 
 318     /* don't completely reset.  in particular, only reset
 319      * the id and flip the invalid bit.  size and name values will remain valid
 320      * across unlinks. other information stored in flags will remain untouched.
 321      */
 322     ds_buf->seg_id = MAP_SEGMENT_SHM_INVALID;
 323     /* note: this is only changing the valid bit to 0. */
 324     MAP_SEGMENT_INVALIDATE(ds_buf);
 325 
 326     return OSHMEM_SUCCESS;
 327 }
 328 

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