root/opal/mca/hwloc/hwloc201/hwloc/hwloc/shmem.c

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

DEFINITIONS

This source file includes following definitions.
  1. tma_shmem_malloc
  2. tma_get_length_malloc
  3. hwloc_shmem_topology_get_length
  4. hwloc_shmem_topology_write
  5. hwloc_shmem_topology_adopt
  6. hwloc__topology_disadopt
  7. hwloc_shmem_topology_get_length
  8. hwloc_shmem_topology_write
  9. hwloc_shmem_topology_adopt
  10. hwloc__topology_disadopt

   1 /*
   2  * Copyright © 2017 Inria.  All rights reserved.
   3  * See COPYING in top-level directory.
   4  */
   5 
   6 #include <private/autogen/config.h>
   7 #include <hwloc.h>
   8 #include <hwloc/shmem.h>
   9 #include <private/private.h>
  10 
  11 #ifndef HWLOC_WIN_SYS
  12 
  13 #include <sys/mman.h>
  14 #include <unistd.h>
  15 #include <assert.h>
  16 
  17 #define HWLOC_SHMEM_HEADER_VERSION 1
  18 
  19 struct hwloc_shmem_header {
  20   uint32_t header_version; /* sanity check */
  21   uint32_t header_length; /* where the actual topology starts in the file/mapping */
  22   uint64_t mmap_address; /* virtual address to pass to mmap */
  23   uint64_t mmap_length; /* length to pass to mmap (includes the header) */
  24 };
  25 
  26 #define HWLOC_SHMEM_MALLOC_ALIGN 8UL
  27 
  28 static void *
  29 tma_shmem_malloc(struct hwloc_tma * tma,
  30                  size_t length)
  31 {
  32   void *current = tma->data;
  33   tma->data = (char*)tma->data  + ((length + HWLOC_SHMEM_MALLOC_ALIGN - 1) & ~(HWLOC_SHMEM_MALLOC_ALIGN - 1));
  34   return current;
  35 
  36 }
  37 
  38 static void *
  39 tma_get_length_malloc(struct hwloc_tma * tma,
  40                       size_t length)
  41 {
  42   size_t *tma_length = tma->data;
  43   *tma_length += (length + HWLOC_SHMEM_MALLOC_ALIGN - 1) & ~(HWLOC_SHMEM_MALLOC_ALIGN - 1);
  44   return malloc(length);
  45 
  46 }
  47 
  48 int
  49 hwloc_shmem_topology_get_length(hwloc_topology_t topology,
  50                                 size_t *lengthp,
  51                                 unsigned long flags)
  52 {
  53   hwloc_topology_t new;
  54   struct hwloc_tma tma;
  55   size_t length = 0;
  56   unsigned long pagesize = hwloc_getpagesize(); /* round-up to full page for mmap() */
  57   int err;
  58 
  59   if (flags) {
  60     errno = EINVAL;
  61     return -1;
  62   }
  63 
  64   tma.malloc = tma_get_length_malloc;
  65   tma.dontfree = 0;
  66   tma.data = &length;
  67 
  68   err = hwloc__topology_dup(&new, topology, &tma);
  69   if (err < 0)
  70     return err;
  71   hwloc_topology_destroy(new);
  72 
  73   *lengthp = (sizeof(struct hwloc_shmem_header) + length + pagesize - 1) & ~(pagesize - 1);
  74   return 0;
  75 }
  76 
  77 int
  78 hwloc_shmem_topology_write(hwloc_topology_t topology,
  79                            int fd, uint64_t fileoffset,
  80                            void *mmap_address, size_t length,
  81                            unsigned long flags)
  82 {
  83   hwloc_topology_t new;
  84   struct hwloc_tma tma;
  85   struct hwloc_shmem_header header;
  86   void *mmap_res;
  87   int err;
  88 
  89   if (flags) {
  90     errno = EINVAL;
  91     return -1;
  92   }
  93 
  94   /* refresh old topology distances so that we don't uselessly duplicate invalid distances
  95    * without being able to free() them.
  96    */
  97   hwloc_internal_distances_refresh(topology);
  98 
  99   header.header_version = HWLOC_SHMEM_HEADER_VERSION;
 100   header.header_length = sizeof(header);
 101   header.mmap_address = (uintptr_t) mmap_address;
 102   header.mmap_length = length;
 103 
 104   err = lseek(fd, fileoffset, SEEK_SET);
 105   if (err < 0)
 106     return -1;
 107 
 108   err = write(fd, &header, sizeof(header));
 109   if (err != sizeof(header))
 110     return -1;
 111 
 112   err = ftruncate(fd, fileoffset + length);
 113   if (err < 0)
 114     return -1;
 115 
 116   mmap_res = mmap(mmap_address, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, fileoffset);
 117   if (mmap_res == MAP_FAILED)
 118     return -1;
 119   if (mmap_res != mmap_address) {
 120     munmap(mmap_res, length);
 121     errno = EBUSY;
 122     return -1;
 123   }
 124 
 125   tma.malloc = tma_shmem_malloc;
 126   tma.dontfree = 1;
 127   tma.data = (char *)mmap_res + sizeof(header);
 128   err = hwloc__topology_dup(&new, topology, &tma);
 129   if (err < 0)
 130     return err;
 131   assert((char*)new == (char*)mmap_address + sizeof(header));
 132 
 133   assert((char *)mmap_res <= (char *)mmap_address + length);
 134 
 135   /* now refresh the new distances so that adopters can use them without refreshing the R/O shmem mapping */
 136   hwloc_internal_distances_refresh(new);
 137 
 138   /* topology is saved, release resources now */
 139   munmap(mmap_address, length);
 140   hwloc_components_fini();
 141 
 142   return 0;
 143 }
 144 
 145 int
 146 hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp,
 147                            int fd, uint64_t fileoffset,
 148                            void *mmap_address, size_t length,
 149                            unsigned long flags)
 150 {
 151   hwloc_topology_t new, old;
 152   struct hwloc_shmem_header header;
 153   void *mmap_res;
 154   int err;
 155 
 156   if (flags) {
 157     errno = EINVAL;
 158     return -1;
 159   }
 160 
 161   err = lseek(fd, fileoffset, SEEK_SET);
 162   if (err < 0)
 163     return -1;
 164 
 165   err = read(fd, &header, sizeof(header));
 166   if (err != sizeof(header))
 167     return -1;
 168 
 169   if (header.header_version != HWLOC_SHMEM_HEADER_VERSION
 170       || header.header_length != sizeof(header)
 171       || header.mmap_address != (uintptr_t) mmap_address
 172       || header.mmap_length != length) {
 173     errno = EINVAL;
 174     return -1;
 175   }
 176 
 177   mmap_res = mmap(mmap_address, length, PROT_READ, MAP_SHARED, fd, fileoffset);
 178   if (mmap_res == MAP_FAILED)
 179     return -1;
 180   if (mmap_res != mmap_address) {
 181     errno = EBUSY;
 182     goto out_with_mmap;
 183   }
 184 
 185   old = (hwloc_topology_t)((char*)mmap_address + sizeof(header));
 186   if (hwloc_topology_abi_check(old) < 0) {
 187     errno = EINVAL;
 188     goto out_with_mmap;
 189   }
 190 
 191   /* enforced by dup() inside shmem_topology_write() */
 192   assert(old->is_loaded);
 193   assert(old->backends == NULL);
 194   assert(old->get_pci_busid_cpuset_backend == NULL);
 195 
 196   hwloc_components_init();
 197 
 198   /* duplicate the topology object so that we ca change use local binding_hooks
 199    * (those are likely not mapped at the same location in both processes).
 200    */
 201   new = malloc(sizeof(struct hwloc_topology));
 202   if (!new)
 203     goto out_with_components;
 204   memcpy(new, old, sizeof(*old));
 205   new->tma = NULL;
 206   new->adopted_shmem_addr = mmap_address;
 207   new->adopted_shmem_length = length;
 208   new->topology_abi = HWLOC_TOPOLOGY_ABI;
 209   /* setting binding hooks will touch support arrays, so duplicate them too.
 210    * could avoid that by requesting a R/W mmap
 211    */
 212   new->support.discovery = malloc(sizeof(*new->support.discovery));
 213   new->support.cpubind = malloc(sizeof(*new->support.cpubind));
 214   new->support.membind = malloc(sizeof(*new->support.membind));
 215   memcpy(new->support.discovery, old->support.discovery, sizeof(*new->support.discovery));
 216   memcpy(new->support.cpubind, old->support.cpubind, sizeof(*new->support.cpubind));
 217   memcpy(new->support.membind, old->support.membind, sizeof(*new->support.membind));
 218   hwloc_set_binding_hooks(new);
 219   /* clear userdata callbacks pointing to the writer process' functions */
 220   new->userdata_export_cb = NULL;
 221   new->userdata_import_cb = NULL;
 222 
 223 #ifndef HWLOC_DEBUG
 224   if (getenv("HWLOC_DEBUG_CHECK"))
 225 #endif
 226     hwloc_topology_check(new);
 227 
 228   *topologyp = new;
 229   return 0;
 230 
 231  out_with_components:
 232   hwloc_components_fini();
 233  out_with_mmap:
 234   munmap(mmap_res, length);
 235   return -1;
 236 }
 237 
 238 void
 239 hwloc__topology_disadopt(hwloc_topology_t topology)
 240 {
 241   hwloc_components_fini();
 242   munmap(topology->adopted_shmem_addr, topology->adopted_shmem_length);
 243   free(topology->support.discovery);
 244   free(topology->support.cpubind);
 245   free(topology->support.membind);
 246   free(topology);
 247 }
 248 
 249 #else /* HWLOC_WIN_SYS */
 250 
 251 int
 252 hwloc_shmem_topology_get_length(hwloc_topology_t topology __hwloc_attribute_unused,
 253                                 size_t *lengthp __hwloc_attribute_unused,
 254                                 unsigned long flags __hwloc_attribute_unused)
 255 {
 256   errno = ENOSYS;
 257   return -1;
 258 }
 259 
 260 int
 261 hwloc_shmem_topology_write(hwloc_topology_t topology __hwloc_attribute_unused,
 262                            int fd __hwloc_attribute_unused, uint64_t fileoffset __hwloc_attribute_unused,
 263                            void *mmap_address __hwloc_attribute_unused, size_t length __hwloc_attribute_unused,
 264                            unsigned long flags __hwloc_attribute_unused)
 265 {
 266   errno = ENOSYS;
 267   return -1;
 268 }
 269 
 270 int
 271 hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp __hwloc_attribute_unused,
 272                            int fd __hwloc_attribute_unused, uint64_t fileoffset __hwloc_attribute_unused,
 273                            void *mmap_address __hwloc_attribute_unused, size_t length __hwloc_attribute_unused,
 274                            unsigned long flags __hwloc_attribute_unused)
 275 {
 276   errno = ENOSYS;
 277   return -1;
 278 }
 279 
 280 void
 281 hwloc__topology_disadopt(hwloc_topology_t topology __hwloc_attribute_unused)
 282 {
 283 }
 284 
 285 #endif /* HWLOC_WIN_SYS */

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