File: lstopo-shmem.c

package info (click to toggle)
mpich 4.3.0%2Breally4.2.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 419,120 kB
  • sloc: ansic: 1,215,557; cpp: 74,755; javascript: 40,763; f90: 20,649; sh: 18,463; xml: 14,418; python: 14,397; perl: 13,772; makefile: 9,279; fortran: 8,063; java: 4,553; asm: 324; ruby: 176; lisp: 19; php: 8; sed: 4
file content (185 lines) | stat: -rw-r--r-- 5,505 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Copyright © 2018-2020 Inria.  All rights reserved.
 * See COPYING in top-level directory.
 */

#include <private/autogen/config.h>
#include <private/private.h>

#include <hwloc.h>
#include <hwloc/shmem.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include "lstopo.h"

struct lstopo_shmem_header {
#define LSTOPO_SHMEM_HEADER_VERSION 1U
  uint32_t header_version;
  uint32_t header_length;
  uint64_t mmap_address;
  uint64_t mmap_length;
  uint64_t file_offset;
};

extern uint64_t shmem_output_addr;

#ifndef MAP_ANONYMOUS /* for Mac OS X 9 */
#define MAP_ANONYMOUS MAP_ANON
#endif

static unsigned long
find_mmap_addr(unsigned long length)
{
  unsigned long addr;
  void *tmp_mmap;
  int err;

  /* try to find a good address starting from something in the middle of the entire/full address space */
#if SIZEOF_VOID_P == 8
  addr = 0x8000000000000000UL;
#else
  addr = 0x80000000UL;
#endif
  printf("Testing mmaps to find room for length %lu\n", length);

again:
  tmp_mmap = mmap((void*)(uintptr_t)addr, length, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
  if (tmp_mmap != MAP_FAILED) {
    err = munmap((void*)(uintptr_t)tmp_mmap, length);
    assert(!err);
    if (tmp_mmap == (void*)(uintptr_t) addr) {
      /* worked! */
      printf(" test mmap at 0x%lx succeeded, let's use that!\n", addr);
      return addr;
    }
    printf(" test mmap at 0x%lx returned another address\n", addr);
  } else
    printf(" test mmap at 0x%lx failed (errno %d)\n", addr, errno);
  /* couldn't map there, try again with a smaller address */
  addr >>= 1;
  if (addr)
    goto again;

  return 0;
}

int
output_shmem(struct lstopo_output *loutput, const char *filename)
{
  struct lstopo_shmem_header header;
  size_t shmem_length;
  struct stat st;
  int fd, err;

  if (!filename || !strcasecmp(filename, "-.shmem")) {
    fprintf(stderr, "Cannot export shmem topology to stdout.\n");
    return -1;
  }

  if (!stat(filename, &st) && !loutput->overwrite) {
    fprintf(stderr, "Failed to export shmem topology to %s (%s)\n", filename, strerror(EEXIST));
    return -1;
  }

  err = hwloc_shmem_topology_get_length(loutput->topology, &shmem_length, 0);
  if (err < 0) {
    if (errno == ENOSYS)
      fprintf(stderr, "shmem topology not supported\n"); /* this line must match the grep line in test-lstopo-shmem */
    else
      fprintf(stderr, "Failed to compute shmem topology export length\n");
    return -1;
  }

  fd = open(filename, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
  if (fd < 0) {
    fprintf(stderr, "Failed to open shmem topology file %s (%s)\n", filename, strerror(errno));
    return -1;
  }

  if (!loutput->shmem_output_addr)
    loutput->shmem_output_addr = find_mmap_addr(shmem_length);
  if (!loutput->shmem_output_addr) {
    fprintf(stderr, "Failed to find a shmem topology mmap address\n"); /* this line must match the grep line in test-lstopo-shmem */
    close(fd);
    unlink(filename);
    return -1;
  }

  header.header_version = LSTOPO_SHMEM_HEADER_VERSION;
  header.header_length = sizeof(header);
  header.mmap_address = loutput->shmem_output_addr;
  header.mmap_length = shmem_length;
  header.file_offset = hwloc_getpagesize();
  err = write(fd, &header, sizeof(header));
  if (err != sizeof(header)) {
    fprintf(stderr, "Failed to write shmem topology header\n");
    close(fd);
    unlink(filename);
    return -1;
  }

  if (hwloc_shmem_topology_write(loutput->topology, fd, header.file_offset, (void*)(uintptr_t)loutput->shmem_output_addr, shmem_length, 0) < 0) {
    if (errno == EBUSY)
      fprintf(stderr, "Failed to export shmem topology, memory range is busy\n"); /* this line must match the grep line in test-lstopo-shmem */
    else
      fprintf(stderr, "Failed to export shmem topology to %s (%s)\n", filename, strerror(errno));
    close(fd);
    unlink(filename);
    return -1;
  }

  close(fd);

  printf("Exported shmem topology to %s for mmap address 0x%llx length %lu\n", filename, (unsigned long long) loutput->shmem_output_addr, (unsigned long) shmem_length);

  return 0;
}

int lstopo_shmem_adopt(const char *input, hwloc_topology_t *topologyp)
{
  hwloc_topology_t adopted;
  struct lstopo_shmem_header header;
  int fd, err;

  fd = open(input, O_RDONLY);
  if (fd < 0)
    return -1;

  err = read(fd, &header, sizeof(header));
  if (err < (int) sizeof(header)) {
    fprintf(stderr, "Failed to read shmem topology header\n");
    close(fd);
    return -1;
  }

  if (header.header_version != LSTOPO_SHMEM_HEADER_VERSION
      || header.header_length != sizeof(header)) {
    fprintf(stderr, "Unexpected shmem topology header version %u length %u (instead of %u %u)\n",
	    header.header_version, header.header_length,
	    LSTOPO_SHMEM_HEADER_VERSION, (unsigned) sizeof(header));
    close(fd);
    return -1;
  }

  err = hwloc_shmem_topology_adopt(&adopted, fd, header.file_offset, (void*)(uintptr_t)header.mmap_address, header.mmap_length, 0);
  close(fd);
  if (err < 0) {
    if (errno == EBUSY)
      fprintf(stderr, "Failed to adopt shmem topology, memory range is busy\n"); /* this line must match the grep line in test-lstopo-shmem */
    else
      fprintf(stderr, "Failed to adopt shmem topology (%s)\n", strerror(errno));
    return -1;
  }

  err = hwloc_topology_dup(topologyp, adopted);
  hwloc_topology_destroy(adopted);
  if (err < 0) {
    fprintf(stderr, "Failed to duplicate adopted shmem topology (%s)\n", strerror(errno));
    return -1;
  }

  return 0;
}