This source file includes following definitions.
- tma_shmem_malloc
- tma_get_length_malloc
- hwloc_shmem_topology_get_length
- hwloc_shmem_topology_write
- hwloc_shmem_topology_adopt
- hwloc__topology_disadopt
- hwloc_shmem_topology_get_length
- hwloc_shmem_topology_write
- hwloc_shmem_topology_adopt
- hwloc__topology_disadopt
1
2
3
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;
21 uint32_t header_length;
22 uint64_t mmap_address;
23 uint64_t mmap_length;
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();
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
95
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
136 hwloc_internal_distances_refresh(new);
137
138
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
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
199
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
210
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
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
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