1 /* Copyright (c) 2007, 2009-2017. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
8 #include <unordered_map>
11 #include "src/internal_config.h"
13 #include "private.hpp"
16 #include "xbt/sysdep.h"
18 #include "surf/surf.h"
19 #include "simgrid/sg_config.h"
20 #include "simgrid/modelchecker.h"
21 #include "src/mc/mc_replay.h"
23 #include <sys/types.h>
30 #include <math.h> // sqrt
40 #define MAP_ANONYMOUS MAP_ANON
43 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_bench, smpi, "Logging specific to SMPI (benchmarking)");
45 /* Shared allocations are handled through shared memory segments.
46 * Associated data and metadata are used as follows:
49 * `allocs' dict ---- -.
50 * ---------- shared_data_t shared_metadata_t / | | |
51 * .->| <name> | ---> -------------------- <--. ----------------- | | | |
52 * | ---------- | fd of <name> | | | size of mmap | --| | | |
53 * | | count (2) | |-- | data | \ | | |
54 * `----------------- | <name> | | ----------------- ---- |
55 * -------------------- | ^ |
57 * | | `allocs_metadata' dict |
58 * | | ---------------------- |
59 * | `-- | <addr of mmap #1> |<-'
60 * | .-- | <addr of mmap #2> |<-.
61 * | | ---------------------- |
67 * | shared_metadata_t / | |
68 * | ----------------- | | |
69 * | | size of mmap | --| | |
71 * ----------------- | | |
76 #define PTR_STRLEN (2 + 2 * sizeof(void*) + 1)
78 xbt_dict_t samples = nullptr; /* Allocated on first use */
79 xbt_dict_t calls = nullptr; /* Allocated on first use */
81 double smpi_cpu_threshold;
82 double smpi_host_speed;
84 int smpi_loaded_page = -1;
85 char* smpi_start_data_exe = nullptr;
86 int smpi_size_data_exe = 0;
87 bool smpi_privatize_global_variables;
88 bool smpi_cfg_shared_malloc = true;
89 double smpi_total_benched_time = 0;
90 smpi_privatisation_region_t smpi_privatisation_regions;
94 /** Some location in the source code
96 * This information is used by SMPI_SHARED_MALLOC to allocate some shared memory for all simulated processes.
98 class smpi_source_location {
100 smpi_source_location(const char* filename, int line)
101 : filename(xbt_strdup(filename)), filename_length(strlen(filename)), line(line) {}
103 /** Pointer to a static string containing the file name */
104 char* filename = nullptr;
105 int filename_length = 0;
108 bool operator==(smpi_source_location const& that) const
110 return filename_length == that.filename_length
112 && std::memcmp(filename, that.filename, filename_length) == 0;
114 bool operator!=(smpi_source_location const& that) const
116 return !(*this == that);
125 class hash<smpi_source_location> {
127 typedef smpi_source_location argument_type;
128 typedef std::size_t result_type;
129 result_type operator()(smpi_source_location const& loc) const
131 return xbt_str_hash_ext(loc.filename, loc.filename_length)
132 ^ xbt_str_hash_ext((const char*) &loc.line, sizeof(loc.line));
145 std::unordered_map<smpi_source_location, shared_data_t> allocs;
146 typedef std::unordered_map<smpi_source_location, shared_data_t>::value_type shared_data_key_type;
150 shared_data_key_type* data;
153 std::unordered_map<void*, shared_metadata_t> allocs_metadata;
157 static size_t shm_size(int fd) {
160 if(fstat(fd, &st) < 0) {
161 xbt_die("Could not stat fd %d: %s", fd, strerror(errno));
163 return static_cast<size_t>(st.st_size);
167 static void* shm_map(int fd, size_t size, shared_data_key_type* data) {
168 char loc[PTR_STRLEN];
169 shared_metadata_t meta;
171 if(size > shm_size(fd) && (ftruncate(fd, static_cast<off_t>(size)) < 0)) {
172 xbt_die("Could not truncate fd %d to %zu: %s", fd, size, strerror(errno));
175 void* mem = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
176 if(mem == MAP_FAILED) {
178 "Failed to map fd %d with size %zu: %s\n"
179 "If you are running a lot of ranks, you may be exceeding the amount of mappings allowed per process.\n"
180 "On Linux systems, change this value with sudo sysctl -w vm.max_map_count=newvalue (default value: 65536)\n"
181 "Please see http://simgrid.gforge.inria.fr/simgrid/latest/doc/html/options.html#options_virt for more info.",
182 fd, size, strerror(errno));
184 snprintf(loc, PTR_STRLEN, "%p", mem);
187 allocs_metadata[mem] = meta;
188 XBT_DEBUG("MMAP %zu to %p", size, mem);
193 void smpi_bench_destroy()
196 allocs_metadata.clear();
197 xbt_dict_free(&samples);
198 xbt_dict_free(&calls);
201 extern "C" XBT_PUBLIC(void) smpi_execute_flops_(double *flops);
202 void smpi_execute_flops_(double *flops)
204 smpi_execute_flops(*flops);
207 extern "C" XBT_PUBLIC(void) smpi_execute_(double *duration);
208 void smpi_execute_(double *duration)
210 smpi_execute(*duration);
213 void smpi_execute_flops(double flops) {
214 XBT_DEBUG("Handle real computation time: %f flops", flops);
215 smx_activity_t action = simcall_execution_start("computation", flops, 1, 0);
216 simcall_set_category (action, TRACE_internal_smpi_get_category());
217 simcall_execution_wait(action);
218 smpi_switch_data_segment(smpi_process_index());
221 void smpi_execute(double duration)
223 if (duration >= smpi_cpu_threshold) {
224 XBT_DEBUG("Sleep for %g to handle real computation time", duration);
225 double flops = duration * smpi_host_speed;
226 int rank = smpi_process_index();
227 instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
228 extra->type=TRACING_COMPUTING;
229 extra->comp_size=flops;
230 TRACE_smpi_computing_in(rank, extra);
232 smpi_execute_flops(flops);
234 TRACE_smpi_computing_out(rank);
237 XBT_DEBUG("Real computation took %g while option smpi/cpu_threshold is set to %g => ignore it",
238 duration, smpi_cpu_threshold);
242 void smpi_bench_begin()
244 if (smpi_privatize_global_variables) {
245 smpi_switch_data_segment(smpi_process_index());
248 if (MC_is_active() || MC_record_replay_is_active())
252 if (xbt_cfg_get_string("smpi/papi-events")[0] != '\0') {
253 int event_set = smpi_process_papi_event_set();
254 // PAPI_start sets everything to 0! See man(3) PAPI_start
255 if (PAPI_LOW_LEVEL_INITED == PAPI_is_initialized()) {
256 if (PAPI_start(event_set) != PAPI_OK) {
257 // TODO This needs some proper handling.
258 XBT_CRITICAL("Could not start PAPI counters.\n");
264 xbt_os_threadtimer_start(smpi_process_timer());
267 void smpi_bench_end()
269 if (MC_is_active() || MC_record_replay_is_active())
273 xbt_os_timer_t timer = smpi_process_timer();
274 xbt_os_threadtimer_stop(timer);
278 * An MPI function has been called and now is the right time to update
279 * our PAPI counters for this process.
281 if (xbt_cfg_get_string("smpi/papi-events")[0] != '\0') {
282 papi_counter_t& counter_data = smpi_process_papi_counters();
283 int event_set = smpi_process_papi_event_set();
284 std::vector<long long> event_values = std::vector<long long>(counter_data.size());
286 if (PAPI_stop(event_set, &event_values[0]) != PAPI_OK) { // Error
287 XBT_CRITICAL("Could not stop PAPI counters.\n");
290 for (unsigned int i = 0; i < counter_data.size(); i++) {
291 counter_data[i].second += event_values[i];
292 // XBT_DEBUG("[%i] PAPI: Counter %s: Value is now %lli (got increment by %lli\n", smpi_process_index(),
293 // counter_data[i].first.c_str(), counter_data[i].second, event_values[i]);
299 if (smpi_process_get_sampling()) {
300 XBT_CRITICAL("Cannot do recursive benchmarks.");
301 XBT_CRITICAL("Are you trying to make a call to MPI within a SMPI_SAMPLE_ block?");
302 xbt_backtrace_display_current();
303 xbt_die("Aborting.");
306 if (xbt_cfg_get_string("smpi/comp-adjustment-file")[0] != '\0') { // Maybe we need to artificially speed up or slow
307 // down our computation based on our statistical analysis.
309 smpi_trace_call_location_t* loc = smpi_process_get_call_location();
310 std::string key = loc->get_composed_key();
311 std::unordered_map<std::string, double>::const_iterator it = location2speedup.find(key);
312 if (it != location2speedup.end()) {
313 speedup = it->second;
317 // Simulate the benchmarked computation unless disabled via command-line argument
318 if (xbt_cfg_get_boolean("smpi/simulate-computation")) {
319 smpi_execute(xbt_os_timer_elapsed(timer)/speedup);
323 if (xbt_cfg_get_string("smpi/papi-events")[0] != '\0' && TRACE_smpi_is_enabled()) {
324 char container_name[INSTR_DEFAULT_STR_SIZE];
325 smpi_container(smpi_process_index(), container_name, INSTR_DEFAULT_STR_SIZE);
326 container_t container = PJ_container_get(container_name);
327 papi_counter_t& counter_data = smpi_process_papi_counters();
329 for (auto& pair : counter_data) {
330 new_pajeSetVariable(surf_get_clock(), container,
331 PJ_type_get(/* countername */ pair.first.c_str(), container->type), pair.second);
336 smpi_total_benched_time += xbt_os_timer_elapsed(timer);
339 /* Private sleep function used by smpi_sleep() and smpi_usleep() */
340 static unsigned int private_sleep(double secs)
344 XBT_DEBUG("Sleep for: %lf secs", secs);
345 int rank = smpi_comm_rank(MPI_COMM_WORLD);
346 instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
347 extra->type=TRACING_SLEEPING;
348 extra->sleep_duration=secs;
349 TRACE_smpi_sleeping_in(rank, extra);
351 simcall_process_sleep(secs);
353 TRACE_smpi_sleeping_out(rank);
359 unsigned int smpi_sleep(unsigned int secs)
361 return private_sleep(static_cast<double>(secs));
364 int smpi_usleep(useconds_t usecs)
366 return static_cast<int>(private_sleep(static_cast<double>(usecs) / 1000000.0));
369 #if _POSIX_TIMERS > 0
370 int smpi_nanosleep(const struct timespec *tp, struct timespec * t)
372 return static_cast<int>(private_sleep(static_cast<double>(tp->tv_sec + tp->tv_nsec / 1000000000.0)));
376 int smpi_gettimeofday(struct timeval *tv, void* tz)
379 double now = SIMIX_get_clock();
381 tv->tv_sec = static_cast<time_t>(now);
383 tv->tv_usec = static_cast<useconds_t>((now - tv->tv_sec) * 1e6);
385 tv->tv_usec = static_cast<suseconds_t>((now - tv->tv_sec) * 1e6);
392 #if _POSIX_TIMERS > 0
393 int smpi_clock_gettime(clockid_t clk_id, struct timespec *tp)
395 //there is only one time in SMPI, so clk_id is ignored.
397 double now = SIMIX_get_clock();
399 tp->tv_sec = static_cast<time_t>(now);
400 tp->tv_nsec = static_cast<long int>((now - tp->tv_sec) * 1e9);
407 extern double sg_surf_precision;
408 unsigned long long smpi_rastro_resolution ()
411 double resolution = (1/sg_surf_precision);
413 return static_cast<unsigned long long>(resolution);
416 unsigned long long smpi_rastro_timestamp ()
419 double now = SIMIX_get_clock();
421 unsigned long long sec = (unsigned long long)now;
422 unsigned long long pre = (now - sec) * smpi_rastro_resolution();
424 return static_cast<unsigned long long>(sec) * smpi_rastro_resolution() + pre;
427 /* ****************************** Functions related to the SMPI_SAMPLE_ macros ************************************/
429 double threshold; /* maximal stderr requested (if positive) */
430 double relstderr; /* observed stderr so far */
431 double mean; /* mean of benched times, to be used if the block is disabled */
432 double sum; /* sum of benched times (to compute the mean and stderr) */
433 double sum_pow2; /* sum of the square of the benched times (to compute the stderr) */
434 int iters; /* amount of requested iterations */
435 int count; /* amount of iterations done so far */
436 int benching; /* 1: we are benchmarking; 0: we have enough data, no bench anymore */
439 static char *sample_location(int global, const char *file, int line) {
441 return bprintf("%s:%d", file, line);
443 return bprintf("%s:%d:%d", file, line, smpi_process_index());
447 static int sample_enough_benchs(local_data_t *data) {
448 int res = data->count >= data->iters;
449 if (data->threshold>0.0) {
451 res = 0; // not enough data
452 if (data->relstderr > data->threshold)
453 res = 0; // stderr too high yet
455 XBT_DEBUG("%s (count:%d iter:%d stderr:%f thres:%f mean:%fs)",
456 (res?"enough benchs":"need more data"), data->count, data->iters, data->relstderr, data->threshold, data->mean);
460 void smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
462 char *loc = sample_location(global, file, line);
464 smpi_bench_end(); /* Take time from previous, unrelated computation into account */
465 smpi_process_set_sampling(1);
467 if (samples==nullptr)
468 samples = xbt_dict_new_homogeneous(free);
470 local_data_t *data = static_cast<local_data_t *>(xbt_dict_get_or_null(samples, loc));
472 xbt_assert(threshold>0 || iters>0,
473 "You should provide either a positive amount of iterations to bench, or a positive maximal stderr (or both)");
474 data = static_cast<local_data_t *>( xbt_new(local_data_t, 1));
477 data->sum_pow2 = 0.0;
479 data->threshold = threshold;
480 data->benching = 1; // If we have no data, we need at least one
482 xbt_dict_set(samples, loc, data, nullptr);
483 XBT_DEBUG("XXXXX First time ever on benched nest %s.",loc);
485 if (data->iters != iters || data->threshold != threshold) {
486 XBT_ERROR("Asked to bench block %s with different settings %d, %f is not %d, %f. "
487 "How did you manage to give two numbers at the same line??",
488 loc, data->iters, data->threshold, iters,threshold);
492 // if we already have some data, check whether sample_2 should get one more bench or whether it should emulate
493 // the computation instead
494 data->benching = (sample_enough_benchs(data) == 0);
495 XBT_DEBUG("XXXX Re-entering the benched nest %s. %s",loc,
496 (data->benching?"more benching needed":"we have enough data, skip computes"));
501 int smpi_sample_2(int global, const char *file, int line)
503 char *loc = sample_location(global, file, line);
506 xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
507 local_data_t *data = static_cast<local_data_t *>(xbt_dict_get(samples, loc));
508 XBT_DEBUG("sample2 %s",loc);
511 if (data->benching==1) {
512 // we need to run a new bench
513 XBT_DEBUG("benchmarking: count:%d iter:%d stderr:%f thres:%f; mean:%f",
514 data->count, data->iters, data->relstderr, data->threshold, data->mean);
517 // Enough data, no more bench (either we got enough data from previous visits to this benched nest, or we just
518 //ran one bench and need to bail out now that our job is done). Just sleep instead
519 XBT_DEBUG("No benchmark (either no need, or just ran one): count >= iter (%d >= %d) or stderr<thres (%f<=%f)."
520 " apply the %fs delay instead", data->count, data->iters, data->relstderr, data->threshold, data->mean);
521 smpi_execute(data->mean);
522 smpi_process_set_sampling(0);
523 res = 0; // prepare to capture future, unrelated computations
529 void smpi_sample_3(int global, const char *file, int line)
531 char *loc = sample_location(global, file, line);
533 xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
534 local_data_t *data = static_cast<local_data_t *>(xbt_dict_get(samples, loc));
535 XBT_DEBUG("sample3 %s",loc);
538 if (data->benching==0)
541 // ok, benchmarking this loop is over
542 xbt_os_threadtimer_stop(smpi_process_timer());
546 double sample = xbt_os_timer_elapsed(smpi_process_timer());
548 data->sum_pow2 += sample * sample;
549 double n = static_cast<double>(data->count);
550 data->mean = data->sum / n;
551 data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
552 if (sample_enough_benchs(data)==0) {
553 data->mean = sample; // Still in benching process; We want sample_2 to simulate the exact time of this loop
554 // occurrence before leaving, not the mean over the history
556 XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
557 data->mean, data->relstderr, sample);
559 // That's enough for now, prevent sample_2 to run the same code over and over
565 void *smpi_shared_malloc(size_t size, const char *file, int line)
568 if (size > 0 && smpi_cfg_shared_malloc) {
570 smpi_source_location loc(file, line);
571 auto res = allocs.insert(std::make_pair(loc, shared_data_t()));
572 auto data = res.first;
574 // The insertion did not take place.
575 // Generate a shared memory name from the address of the shared_data:
576 char shmname[32]; // cannot be longer than PSHMNAMLEN = 31 on Mac OS X (shm_open raises ENAMETOOLONG otherwise)
577 snprintf(shmname, 31, "/shmalloc%p", &*data);
578 fd = shm_open(shmname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
581 xbt_die("Please cleanup /dev/shm/%s", shmname);
583 xbt_die("An unhandled error occurred while opening %s. shm_open: %s", shmname, strerror(errno));
585 data->second.fd = fd;
586 data->second.count = 1;
587 mem = shm_map(fd, size, &*data);
588 if (shm_unlink(shmname) < 0) {
589 XBT_WARN("Could not early unlink %s. shm_unlink: %s", shmname, strerror(errno));
591 XBT_DEBUG("Mapping %s at %p through %d", shmname, mem, fd);
593 mem = shm_map(data->second.fd, size, &*data);
594 data->second.count++;
596 XBT_DEBUG("Shared malloc %zu in %p (metadata at %p)", size, mem, &*data);
598 mem = xbt_malloc(size);
599 XBT_DEBUG("Classic malloc %zu in %p", size, mem);
605 void smpi_shared_free(void *ptr)
607 char loc[PTR_STRLEN];
609 if (smpi_cfg_shared_malloc) {
610 snprintf(loc, PTR_STRLEN, "%p", ptr);
611 auto meta = allocs_metadata.find(ptr);
612 if (meta == allocs_metadata.end()) {
613 XBT_WARN("Cannot free: %p was not shared-allocated by SMPI - maybe its size was 0?", ptr);
616 shared_data_t* data = &meta->second.data->second;
617 if (munmap(ptr, meta->second.size) < 0) {
618 XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
621 if (data->count <= 0) {
623 allocs.erase(allocs.find(meta->second.data->first));
624 XBT_DEBUG("Shared free - with removal - of %p", ptr);
626 XBT_DEBUG("Shared free - no removal - of %p, count = %d", ptr, data->count);
629 XBT_DEBUG("Classic free of %p", ptr);
635 int smpi_shared_known_call(const char* func, const char* input)
637 char* loc = bprintf("%s:%s", func, input);
640 if (calls==nullptr) {
641 calls = xbt_dict_new_homogeneous(nullptr);
644 xbt_dict_get(calls, loc); /* Succeed or throw */
650 if (ex.category != not_found_error)
660 void* smpi_shared_get_call(const char* func, const char* input) {
661 char* loc = bprintf("%s:%s", func, input);
664 calls = xbt_dict_new_homogeneous(nullptr);
665 void* data = xbt_dict_get(calls, loc);
670 void* smpi_shared_set_call(const char* func, const char* input, void* data) {
671 char* loc = bprintf("%s:%s", func, input);
674 calls = xbt_dict_new_homogeneous(nullptr);
675 xbt_dict_set(calls, loc, data, nullptr);
681 /** Map a given SMPI privatization segment (make a SMPI process active) */
682 void smpi_switch_data_segment(int dest) {
683 if (smpi_loaded_page == dest)//no need to switch, we've already loaded the one we want
687 smpi_really_switch_data_segment(dest);
690 /** Map a given SMPI privatization segment (make a SMPI process active) even if SMPI thinks it is already active
692 * When doing a state restoration, the state of the restored variables might not be consistent with the state of the
693 * virtual memory. In this case, we to change the data segment.
695 void smpi_really_switch_data_segment(int dest)
697 if(smpi_size_data_exe == 0)//no need to switch
700 #if HAVE_PRIVATIZATION
701 if(smpi_loaded_page==-1){//initial switch, do the copy from the real page here
702 for (int i=0; i< smpi_process_count(); i++){
703 memcpy(smpi_privatisation_regions[i].address, TOPAGE(smpi_start_data_exe), smpi_size_data_exe);
707 // FIXME, cross-process support (mmap across process when necessary)
708 int current = smpi_privatisation_regions[dest].file_descriptor;
709 XBT_DEBUG("Switching data frame to the one of process %d", dest);
710 void* tmp = mmap (TOPAGE(smpi_start_data_exe), smpi_size_data_exe,
711 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, current, 0);
712 if (tmp != TOPAGE(smpi_start_data_exe))
713 xbt_die("Couldn't map the new region");
714 smpi_loaded_page = dest;
718 int smpi_is_privatisation_file(char* file)
720 return strncmp("/dev/shm/my-buffer-", file, std::strlen("/dev/shm/my-buffer-")) == 0;
723 void smpi_initialize_global_memory_segments()
726 #if !HAVE_PRIVATIZATION
727 smpi_privatize_global_variables=false;
728 xbt_die("You are trying to use privatization on a system that does not support it. Don't.");
732 smpi_get_executable_global_size();
734 XBT_DEBUG ("bss+data segment found : size %d starting at %p", smpi_size_data_exe, smpi_start_data_exe );
736 if (smpi_size_data_exe == 0){//no need to switch
737 smpi_privatize_global_variables=false;
741 smpi_privatisation_regions =
742 static_cast<smpi_privatisation_region_t>( xbt_malloc(smpi_process_count() * sizeof(struct s_smpi_privatisation_region)));
744 for (int i=0; i< smpi_process_count(); i++){
745 //create SIMIX_process_count() mappings of this size with the same data inside
747 void *address = nullptr;
752 snprintf(path, sizeof(path), "/smpi-buffer-%06x", rand()%0xffffff);
753 file_descriptor = shm_open(path, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
754 } while (file_descriptor == -1 && errno == EEXIST);
755 if (file_descriptor < 0) {
757 xbt_die("Impossible to create temporary file for memory mapping: %s\n\
758 The open() system call failed with the EMFILE error code (too many files). \n\n\
759 This means that you reached the system limits concerning the amount of files per process. \
760 This is not a surprise if you are trying to virtualize many processes on top of SMPI. \
761 Don't panic -- you should simply increase your system limits and try again. \n\n\
762 First, check what your limits are:\n\
763 cat /proc/sys/fs/file-max # Gives you the system-wide limit\n\
764 ulimit -Hn # Gives you the per process hard limit\n\
765 ulimit -Sn # Gives you the per process soft limit\n\
766 cat /proc/self/limits # Displays any per-process limitation (including the one given above)\n\n\
767 If one of these values is less than the amount of MPI processes that you try to run, then you got the explanation of this error. \
768 Ask the Internet about tutorials on how to increase the files limit such as: https://rtcamp.com/tutorials/linux/increase-open-files-limit/",
771 xbt_die("Impossible to create temporary file for memory mapping: %s",
775 status = ftruncate(file_descriptor, smpi_size_data_exe);
777 xbt_die("Impossible to set the size of the temporary file for memory mapping");
779 /* Ask for a free region */
780 address = mmap (nullptr, smpi_size_data_exe, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, 0);
781 if (address == MAP_FAILED)
782 xbt_die("Couldn't find a free region for memory mapping");
784 status = shm_unlink(path);
786 xbt_die("Impossible to unlink temporary file for memory mapping");
788 //initialize the values
789 memcpy(address, TOPAGE(smpi_start_data_exe), smpi_size_data_exe);
791 //store the address of the mapping for further switches
792 smpi_privatisation_regions[i].file_descriptor = file_descriptor;
793 smpi_privatisation_regions[i].address = address;
798 void smpi_destroy_global_memory_segments(){
799 if (smpi_size_data_exe == 0)//no need to switch
801 #if HAVE_PRIVATIZATION
802 for (int i=0; i< smpi_process_count(); i++) {
803 if (munmap(smpi_privatisation_regions[i].address, smpi_size_data_exe) < 0)
804 XBT_WARN("Unmapping of fd %d failed: %s", smpi_privatisation_regions[i].file_descriptor, strerror(errno));
805 close(smpi_privatisation_regions[i].file_descriptor);
807 xbt_free(smpi_privatisation_regions);
811 extern "C" { /** These functions will be called from the user code **/
812 smpi_trace_call_location_t* smpi_trace_get_call_location() {
813 return smpi_process_get_call_location();
816 void smpi_trace_set_call_location(const char* file, const int line) {
817 smpi_trace_call_location_t* loc = smpi_process_get_call_location();
819 loc->previous_filename = loc->filename;
820 loc->previous_linenumber = loc->linenumber;
821 loc->filename = file;
822 loc->linenumber = line;
826 * Required for Fortran bindings
828 void smpi_trace_set_call_location_(const char* file, int* line) {
829 smpi_trace_set_call_location(file, *line);
833 * Required for Fortran if -fsecond-underscore is activated
835 void smpi_trace_set_call_location__(const char* file, int* line) {
836 smpi_trace_set_call_location(file, *line);