This source file includes following definitions.
- set_flags
- pmix_hwloc_get_topology
- pmix_hwloc_cleanup
- parse_map_line
- use_hole
- find_hole
- enough_space
1
2
3
4
5
6
7
8
9
10
11
12 #include <src/include/pmix_config.h>
13 #include <pmix_common.h>
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdint.h>
18 #include <assert.h>
19 #include <errno.h>
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #include <string.h>
24 #include <sys/mman.h>
25 #ifdef HAVE_SYS_STAT_H
26 #include <sys/stat.h>
27 #endif
28 #if HAVE_FCNTL_H
29 #include <fcntl.h>
30 #endif
31
32 #include "src/util/error.h"
33 #include "src/util/fd.h"
34 #include "src/util/path.h"
35 #include "src/mca/bfrops/bfrops_types.h"
36 #include "src/server/pmix_server_ops.h"
37 #include "hwloc-internal.h"
38
39 #if PMIX_HAVE_HWLOC
40
41 #if HWLOC_API_VERSION >= 0x20000
42 #include <hwloc/shmem.h>
43 #endif
44
45
46 PMIX_EXPORT hwloc_topology_t pmix_hwloc_topology = NULL;
47 static bool external_topology = false;
48
49 #if HWLOC_API_VERSION >= 0x20000
50 static size_t shmemsize = 0;
51 static size_t shmemaddr;
52 static char *shmemfile = NULL;
53 static int shmemfd = -1;
54
55 static int parse_map_line(const char *line,
56 unsigned long *beginp,
57 unsigned long *endp,
58 pmix_hwloc_vm_map_kind_t *kindp);
59 static int use_hole(unsigned long holebegin,
60 unsigned long holesize,
61 unsigned long *addrp,
62 unsigned long size);
63 static int find_hole(pmix_hwloc_vm_hole_kind_t hkind,
64 size_t *addrp,
65 size_t size);
66 static int enough_space(const char *filename,
67 size_t space_req,
68 uint64_t *space_avail,
69 bool *result);
70 #endif
71
72 static int set_flags(hwloc_topology_t topo, unsigned int flags)
73 {
74 #if HWLOC_API_VERSION < 0x20000
75 flags = HWLOC_TOPOLOGY_FLAG_IO_DEVICES;
76 #else
77 int ret = hwloc_topology_set_io_types_filter(topo, HWLOC_TYPE_FILTER_KEEP_IMPORTANT);
78 if (0 != ret) return ret;
79 #endif
80 if (0 != hwloc_topology_set_flags(topo, flags)) {
81 return PMIX_ERR_INIT;
82 }
83 return PMIX_SUCCESS;
84 }
85 #endif
86
87 pmix_status_t pmix_hwloc_get_topology(pmix_info_t *info, size_t ninfo)
88 {
89 #if PMIX_HAVE_HWLOC
90 size_t n;
91 bool save_xml_v1 = false;
92 bool save_xml_v2 = false;
93 #if HWLOC_API_VERSION < 0x20000
94 bool save_xml_v2_reqd = false;
95 #endif
96 bool share_topo = false;
97 bool share_reqd = false;
98 pmix_kval_t *kp2;
99 char *xml;
100 int sz;
101 pmix_status_t rc;
102 #if HWLOC_API_VERSION >= 0x20000
103 pmix_hwloc_vm_hole_kind_t hole = VM_HOLE_BIGGEST;
104 #endif
105
106 if (NULL == info || 0 == ninfo) {
107 if (0 != hwloc_topology_init(&pmix_hwloc_topology)) {
108 return PMIX_ERR_INIT;
109 }
110
111 if (0 != set_flags(pmix_hwloc_topology, 0)) {
112 hwloc_topology_destroy(pmix_hwloc_topology);
113 return PMIX_ERR_INIT;
114 }
115
116 if (0 != hwloc_topology_load(pmix_hwloc_topology)) {
117 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
118 hwloc_topology_destroy(pmix_hwloc_topology);
119 return PMIX_ERR_NOT_SUPPORTED;
120 }
121 return PMIX_SUCCESS;
122 }
123
124
125 for (n=0; n < ninfo; n++) {
126 if (0 == strncmp(info[n].key, PMIX_TOPOLOGY, PMIX_MAX_KEYLEN)) {
127
128
129
130 if (NULL != pmix_hwloc_topology) {
131
132 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
133 return PMIX_ERR_BAD_PARAM;
134 }
135 if (NULL != info[n].value.data.ptr) {
136 pmix_hwloc_topology = (hwloc_topology_t)info[n].value.data.ptr;
137 external_topology = true;
138 } else {
139 if (0 != hwloc_topology_init(&pmix_hwloc_topology)) {
140 return PMIX_ERR_INIT;
141 }
142
143 if (0 != set_flags(pmix_hwloc_topology, 0)) {
144 hwloc_topology_destroy(pmix_hwloc_topology);
145 return PMIX_ERR_INIT;
146 }
147
148 if (0 != hwloc_topology_load(pmix_hwloc_topology)) {
149 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
150 hwloc_topology_destroy(pmix_hwloc_topology);
151 return PMIX_ERR_NOT_SUPPORTED;
152 }
153 }
154 } else if (0 == strncmp(info[n].key, PMIX_HWLOC_XML_V1, PMIX_MAX_KEYLEN)) {
155
156
157
158 if (NULL == info[n].value.data.string) {
159 save_xml_v1 = true;
160 } else if (NULL != pmix_hwloc_topology) {
161
162 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
163 return PMIX_ERR_BAD_PARAM;
164 } else {
165
166 if (0 != hwloc_topology_init(&pmix_hwloc_topology)) {
167 return PMIX_ERROR;
168 }
169 if (0 != hwloc_topology_set_xmlbuffer(pmix_hwloc_topology,
170 info[n].value.data.string,
171 strlen(info[n].value.data.string))) {
172 hwloc_topology_destroy(pmix_hwloc_topology);
173 return PMIX_ERROR;
174 }
175
176
177
178 if (0 != set_flags(pmix_hwloc_topology, HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM)) {
179 hwloc_topology_destroy(pmix_hwloc_topology);
180 return PMIX_ERROR;
181 }
182
183 if (0 != hwloc_topology_load(pmix_hwloc_topology)) {
184 hwloc_topology_destroy(pmix_hwloc_topology);
185 return PMIX_ERROR;
186 }
187
188 kp2 = PMIX_NEW(pmix_kval_t);
189 if (NULL == kp2) {
190 return PMIX_ERR_NOMEM;
191 }
192 kp2->key = strdup(info[n].key);
193 PMIX_VALUE_XFER(rc, kp2->value, &info[n].value);
194 if (PMIX_SUCCESS != rc) {
195 PMIX_ERROR_LOG(rc);
196 PMIX_RELEASE(kp2);
197 return rc;
198 }
199 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
200 }
201 } else if (0 == strncmp(info[n].key, PMIX_HWLOC_XML_V2, PMIX_MAX_KEYLEN)) {
202
203
204
205 if (NULL == info[n].value.data.string) {
206 save_xml_v2 = true;
207 #if HWLOC_API_VERSION < 0x20000
208 save_xml_v2_reqd = PMIX_INFO_REQUIRED(&info[n]);
209 #endif
210 } else if (NULL != pmix_hwloc_topology) {
211
212 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
213 return PMIX_ERR_BAD_PARAM;
214 } else {
215
216 if (0 != hwloc_topology_init(&pmix_hwloc_topology)) {
217 return PMIX_ERROR;
218 }
219 if (0 != hwloc_topology_set_xmlbuffer(pmix_hwloc_topology,
220 info[n].value.data.string,
221 strlen(info[n].value.data.string))) {
222 hwloc_topology_destroy(pmix_hwloc_topology);
223 return PMIX_ERROR;
224 }
225
226
227
228 if (0 != set_flags(pmix_hwloc_topology, HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM)) {
229 hwloc_topology_destroy(pmix_hwloc_topology);
230 return PMIX_ERROR;
231 }
232
233 if (0 != hwloc_topology_load(pmix_hwloc_topology)) {
234 hwloc_topology_destroy(pmix_hwloc_topology);
235 return PMIX_ERROR;
236 }
237
238 kp2 = PMIX_NEW(pmix_kval_t);
239 if (NULL == kp2) {
240 return PMIX_ERR_NOMEM;
241 }
242 kp2->key = strdup(info[n].key);
243 PMIX_VALUE_XFER(rc, kp2->value, &info[n].value);
244 if (PMIX_SUCCESS != rc) {
245 PMIX_ERROR_LOG(rc);
246 PMIX_RELEASE(kp2);
247 return rc;
248 }
249 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
250 }
251 } else if (0 == strncmp(info[n].key, PMIX_TOPOLOGY_FILE, PMIX_MAX_KEYLEN)) {
252 if (NULL == info[n].value.data.string) {
253 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
254 return PMIX_ERR_BAD_PARAM;
255 } else if (NULL != pmix_hwloc_topology) {
256
257 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
258 return PMIX_ERR_BAD_PARAM;
259 } else {
260 if (0 != hwloc_topology_init(&pmix_hwloc_topology)) {
261 return PMIX_ERR_NOT_SUPPORTED;
262 }
263 if (0 != hwloc_topology_set_xml(pmix_hwloc_topology, info[n].value.data.string)) {
264 hwloc_topology_destroy(pmix_hwloc_topology);
265 return PMIX_ERR_NOT_SUPPORTED;
266 }
267
268
269
270 if (0 != set_flags(pmix_hwloc_topology, HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM)) {
271 hwloc_topology_destroy(pmix_hwloc_topology);
272 return PMIX_ERR_NOT_SUPPORTED;
273 }
274 if (0 != hwloc_topology_load(pmix_hwloc_topology)) {
275 hwloc_topology_destroy(pmix_hwloc_topology);
276 return PMIX_ERR_NOT_SUPPORTED;
277 }
278
279 kp2 = PMIX_NEW(pmix_kval_t);
280 if (NULL == kp2) {
281 return PMIX_ERR_NOMEM;
282 }
283 kp2->key = strdup(info[n].key);
284 PMIX_VALUE_XFER(rc, kp2->value, &info[n].value);
285 if (PMIX_SUCCESS != rc) {
286 PMIX_ERROR_LOG(rc);
287 PMIX_RELEASE(kp2);
288 return rc;
289 }
290 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
291 }
292 } else if (0 == strncmp(info[n].key, PMIX_HWLOC_SHARE_TOPO, PMIX_MAX_KEYLEN)) {
293 share_topo = PMIX_INFO_TRUE(&info[n]);
294 share_reqd = PMIX_INFO_IS_REQUIRED(&info[n]);
295 } else if (0 == strncmp(info[n].key, PMIX_HWLOC_HOLE_KIND, PMIX_MAX_KEYLEN)) {
296 #if HWLOC_API_VERSION >= 0x20000
297 if (0 == strcasecmp(info[n].value.data.string, "none")) {
298 hole = VM_HOLE_NONE;
299 } else if (0 == strcasecmp(info[n].value.data.string, "begin")) {
300 hole = VM_HOLE_BEGIN;
301 } else if (0 == strcasecmp(info[n].value.data.string, "biggest")) {
302 hole = VM_HOLE_BIGGEST;
303 } else if (0 == strcasecmp(info[n].value.data.string, "libs")) {
304 hole = VM_HOLE_IN_LIBS;
305 } else if (0 == strcasecmp(info[n].value.data.string, "heap")) {
306 hole = VM_HOLE_AFTER_HEAP;
307 } else if (0 == strcasecmp(info[n].value.data.string, "stack")) {
308 hole = VM_HOLE_BEFORE_STACK;
309 } else {
310 PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM);
311 return PMIX_ERR_BAD_PARAM;
312 }
313 #endif
314 }
315 }
316
317 if (save_xml_v1) {
318
319 #if HWLOC_API_VERSION >= 0x20000
320 if (0 != hwloc_topology_export_xmlbuffer(pmix_hwloc_topology, &xml, &sz, HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1)) {
321 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
322 return PMIX_ERR_NOT_SUPPORTED;
323 }
324 #else
325 if (0 != hwloc_topology_export_xmlbuffer(pmix_hwloc_topology, &xml, &sz)) {
326 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
327 return PMIX_ERR_NOT_SUPPORTED;
328 }
329 #endif
330
331 kp2 = PMIX_NEW(pmix_kval_t);
332 if (NULL == kp2) {
333 return PMIX_ERR_NOMEM;
334 }
335 kp2->key = strdup(PMIX_HWLOC_XML_V1);
336 PMIX_VALUE_LOAD(kp2->value, xml, PMIX_STRING);
337 hwloc_free_xmlbuffer(pmix_hwloc_topology, xml);
338 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
339 }
340 if (save_xml_v2) {
341
342 #if HWLOC_API_VERSION >= 0x20000
343 if (0 != hwloc_topology_export_xmlbuffer(pmix_hwloc_topology, &xml, &sz, 0)) {
344 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
345 return PMIX_ERR_NOT_SUPPORTED;
346 }
347
348 kp2 = PMIX_NEW(pmix_kval_t);
349 if (NULL == kp2) {
350 return PMIX_ERR_NOMEM;
351 }
352 kp2->key = strdup(PMIX_HWLOC_XML_V1);
353 PMIX_VALUE_LOAD(kp2->value, xml, PMIX_STRING);
354 hwloc_free_xmlbuffer(pmix_hwloc_topology, xml);
355 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
356 #else
357 if (save_xml_v2_reqd) {
358 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
359 return PMIX_ERR_NOT_SUPPORTED;
360 }
361 #endif
362 }
363
364 if (share_topo) {
365 #if HWLOC_API_VERSION < 0x20000
366 if (share_reqd) {
367 return PMIX_ERR_NOT_SUPPORTED;
368 }
369 #else
370 pmix_status_t rc;
371 bool space_available = false;
372 uint64_t amount_space_avail = 0;
373
374 if (VM_HOLE_NONE == hole) {
375 return PMIX_SUCCESS;
376 }
377
378
379 if (0 != hwloc_shmem_topology_get_length(pmix_hwloc_topology, &shmemsize, 0)) {
380 if (share_reqd) {
381 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
382 return PMIX_ERR_NOT_SUPPORTED;
383 }
384 return PMIX_SUCCESS;
385 }
386
387 if (PMIX_SUCCESS != (rc = find_hole(hole, &shmemaddr, shmemsize))) {
388
389 if (share_reqd) {
390 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
391 return PMIX_ERR_NOT_SUPPORTED;
392 }
393 return PMIX_SUCCESS;
394 }
395
396
397 asprintf(&shmemfile, "%s/hwloc.sm", pmix_server_globals.tmpdir);
398
399 if (PMIX_SUCCESS != (rc = enough_space(shmemfile, shmemsize,
400 &amount_space_avail,
401 &space_available))) {
402 free(shmemfile);
403 shmemfile = NULL;
404 if (share_reqd) {
405 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
406 return PMIX_ERR_NOT_SUPPORTED;
407 } else {
408 return PMIX_SUCCESS;
409 }
410 }
411 if (!space_available) {
412 free(shmemfile);
413 shmemfile = NULL;
414 if (share_reqd) {
415 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
416 return PMIX_ERR_NOT_SUPPORTED;
417 } else {
418 return PMIX_SUCCESS;
419 }
420 }
421
422 if (-1 == (shmemfd = open(shmemfile, O_CREAT | O_RDWR, 0600))) {
423 free(shmemfile);
424 shmemfile = NULL;
425 if (share_reqd) {
426 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
427 return PMIX_ERR_NOT_SUPPORTED;
428 } else {
429 return PMIX_SUCCESS;
430 }
431 }
432
433 pmix_fd_set_cloexec(shmemfd);
434
435 if (0 != (rc = hwloc_shmem_topology_write(pmix_hwloc_topology, shmemfd, 0,
436 (void*)shmemaddr, shmemsize, 0))) {
437 unlink(shmemfile);
438 free(shmemfile);
439 shmemfile = NULL;
440 close(shmemfd);
441 shmemfd = -1;
442 if (share_reqd) {
443 PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED);
444 return PMIX_ERR_NOT_SUPPORTED;
445 } else {
446 return PMIX_SUCCESS;
447 }
448 }
449
450 kp2 = PMIX_NEW(pmix_kval_t);
451 if (NULL == kp2) {
452 return PMIX_ERR_NOMEM;
453 }
454 kp2->key = strdup(PMIX_HWLOC_SHMEM_FILE);
455 PMIX_VALUE_CREATE(kp2->value, 1);
456 PMIX_VALUE_LOAD(kp2->value, shmemfile, PMIX_STRING);
457 if (PMIX_SUCCESS != rc) {
458 PMIX_ERROR_LOG(rc);
459 PMIX_RELEASE(kp2);
460 return rc;
461 }
462 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
463 kp2 = PMIX_NEW(pmix_kval_t);
464 if (NULL == kp2) {
465 return PMIX_ERR_NOMEM;
466 }
467 kp2->key = strdup(PMIX_HWLOC_SHMEM_ADDR);
468 PMIX_VALUE_CREATE(kp2->value, 1);
469 PMIX_VALUE_LOAD(kp2->value, &shmemaddr, PMIX_SIZE);
470 if (PMIX_SUCCESS != rc) {
471 PMIX_ERROR_LOG(rc);
472 PMIX_RELEASE(kp2);
473 return rc;
474 }
475 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
476 kp2 = PMIX_NEW(pmix_kval_t);
477 if (NULL == kp2) {
478 return PMIX_ERR_NOMEM;
479 }
480 kp2->key = strdup(PMIX_HWLOC_SHMEM_SIZE);
481 PMIX_VALUE_CREATE(kp2->value, 1);
482 PMIX_VALUE_LOAD(kp2->value, &shmemsize, PMIX_SIZE);
483 if (PMIX_SUCCESS != rc) {
484 PMIX_ERROR_LOG(rc);
485 PMIX_RELEASE(kp2);
486 return rc;
487 }
488 pmix_list_append(&pmix_server_globals.gdata, &kp2->super);
489
490
491 #endif
492 }
493
494 return PMIX_SUCCESS;
495 #else
496 return PMIX_SUCCESS;
497 #endif
498 }
499
500 void pmix_hwloc_cleanup(void)
501 {
502 #if PMIX_HAVE_HWLOC
503 #if HWLOC_API_VERSION >= 0x20000
504 if (NULL != shmemfile) {
505 unlink(shmemfile);
506 free(shmemfile);
507 }
508 if (0 <= shmemfd) {
509 close(shmemfd);
510 }
511 #endif
512 if (NULL != pmix_hwloc_topology && !external_topology) {
513 hwloc_topology_destroy(pmix_hwloc_topology);
514 }
515 #endif
516 return;
517 }
518
519 #if PMIX_HAVE_HWLOC
520 #if HWLOC_API_VERSION >= 0x20000
521
522 static int parse_map_line(const char *line,
523 unsigned long *beginp,
524 unsigned long *endp,
525 pmix_hwloc_vm_map_kind_t *kindp)
526 {
527 const char *tmp = line, *next;
528 unsigned long value;
529
530
531 value = strtoull(tmp, (char **) &next, 16);
532 if (next == tmp) {
533 return PMIX_ERROR;
534 }
535
536 *beginp = (unsigned long) value;
537
538 if (*next != '-') {
539 return PMIX_ERROR;
540 }
541
542 tmp = next + 1;
543
544 value = strtoull(tmp, (char **) &next, 16);
545 if (next == tmp) {
546 return PMIX_ERROR;
547 }
548 *endp = (unsigned long) value;
549 tmp = next;
550
551 if (*next != ' ') {
552 return PMIX_ERROR;
553 }
554 tmp = next + 1;
555
556
557 next = strchr(tmp, '/');
558 if (next) {
559 *kindp = VM_MAP_FILE;
560 } else {
561
562 next = strchr(tmp, '[');
563 if (next) {
564 if (!strncmp(next, "[heap]", 6)) {
565 *kindp = VM_MAP_HEAP;
566 } else if (!strncmp(next, "[stack]", 7)) {
567 *kindp = VM_MAP_STACK;
568 } else {
569 char *end;
570 if ((end = strchr(next, '\n')) != NULL) {
571 *end = '\0';
572 }
573 *kindp = VM_MAP_OTHER;
574 }
575 } else {
576 *kindp = VM_MAP_ANONYMOUS;
577 }
578 }
579
580 return PMIX_SUCCESS;
581 }
582
583 #define ALIGN2MB (2*1024*1024UL)
584
585 static int use_hole(unsigned long holebegin,
586 unsigned long holesize,
587 unsigned long *addrp,
588 unsigned long size)
589 {
590 unsigned long aligned;
591 unsigned long middle = holebegin+holesize/2;
592
593 if (holesize < size) {
594 return PMIX_ERROR;
595 }
596
597
598 #define ALIGN64MB (64*1024*1024UL)
599 aligned = (middle + ALIGN64MB) & ~(ALIGN64MB-1);
600 if (aligned + size <= holebegin + holesize) {
601 *addrp = aligned;
602 return PMIX_SUCCESS;
603 }
604
605
606 aligned = (middle + ALIGN2MB) & ~(ALIGN2MB-1);
607 if (aligned + size <= holebegin + holesize) {
608 *addrp = aligned;
609 return PMIX_SUCCESS;
610 }
611
612
613 *addrp = holebegin + holesize - size;
614 return PMIX_SUCCESS;
615 }
616
617 static int find_hole(pmix_hwloc_vm_hole_kind_t hkind,
618 size_t *addrp, size_t size)
619 {
620 unsigned long biggestbegin = 0;
621 unsigned long biggestsize = 0;
622 unsigned long prevend = 0;
623 pmix_hwloc_vm_map_kind_t prevmkind = VM_MAP_OTHER;
624 int in_libs = 0;
625 FILE *file;
626 char line[96];
627
628 file = fopen("/proc/self/maps", "r");
629 if (!file) {
630 return PMIX_ERROR;
631 }
632
633 while (fgets(line, sizeof(line), file) != NULL) {
634 unsigned long begin=0, end=0;
635 pmix_hwloc_vm_map_kind_t mkind=VM_MAP_OTHER;
636
637 if (!parse_map_line(line, &begin, &end, &mkind)) {
638 switch (hkind) {
639 case VM_HOLE_BEGIN:
640 fclose(file);
641 return use_hole(0, begin, addrp, size);
642
643 case VM_HOLE_AFTER_HEAP:
644 if (prevmkind == VM_MAP_HEAP && mkind != VM_MAP_HEAP) {
645
646
647
648 fclose(file);
649 return use_hole(prevend, begin-prevend, addrp, size);
650 }
651 break;
652
653 case VM_HOLE_BEFORE_STACK:
654 if (mkind == VM_MAP_STACK) {
655 fclose(file);
656 return use_hole(prevend, begin-prevend, addrp, size);
657 }
658 break;
659
660 case VM_HOLE_IN_LIBS:
661
662 if (prevmkind == VM_MAP_HEAP) {
663 in_libs = 1;
664 }
665 if (mkind == VM_MAP_STACK) {
666 in_libs = 0;
667 }
668 if (!in_libs) {
669
670 break;
671 }
672
673
674
675 case VM_HOLE_BIGGEST:
676 if (begin-prevend > biggestsize) {
677 biggestbegin = prevend;
678 biggestsize = begin-prevend;
679 }
680 break;
681
682 default:
683 assert(0);
684 }
685 }
686
687 while (!strchr(line, '\n')) {
688 if (!fgets(line, sizeof(line), file)) {
689 goto done;
690 }
691 }
692
693 if (mkind == VM_MAP_STACK) {
694
695
696
697 break;
698 }
699
700 prevend = end;
701 prevmkind = mkind;
702
703 }
704
705 done:
706 fclose(file);
707 if (hkind == VM_HOLE_IN_LIBS || hkind == VM_HOLE_BIGGEST) {
708 return use_hole(biggestbegin, biggestsize, addrp, size);
709 }
710
711 return PMIX_ERROR;
712 }
713
714 static int enough_space(const char *filename,
715 size_t space_req,
716 uint64_t *space_avail,
717 bool *result)
718 {
719 uint64_t avail = 0;
720 size_t fluff = (size_t)(.05 * space_req);
721 bool enough = false;
722 char *last_sep = NULL;
723
724
725 char *target_dir = strdup(filename);
726 int rc;
727
728 if (NULL == target_dir) {
729 rc = PMIX_ERR_OUT_OF_RESOURCE;
730 goto out;
731 }
732
733 last_sep = strrchr(target_dir, PMIX_PATH_SEP[0]);
734 *last_sep = '\0';
735
736 if (PMIX_SUCCESS != (rc = pmix_path_df(target_dir, &avail))) {
737 goto out;
738 }
739
740 if (avail >= space_req + fluff) {
741 enough = true;
742 }
743
744 out:
745 if (NULL != target_dir) {
746 free(target_dir);
747 }
748 *result = enough;
749 *space_avail = avail;
750 return rc;
751 }
752 #endif
753
754 #endif