Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Distinguish between time precision and sharing precision.
[simgrid.git] / src / smpi / smpi_bench.c
1 /* Copyright (c) 2007, 2009-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "internal_config.h"
8 #include "private.h"
9 #include "xbt/dict.h"
10 #include "xbt/sysdep.h"
11 #include "xbt/ex.h"
12 #include "xbt/hash.h"
13 #include "surf/surf.h"
14 #include "simgrid/sg_config.h"
15
16 #ifndef WIN32
17 #include <sys/mman.h>
18 #endif
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <math.h> // sqrt
24 #include <unistd.h>
25 #include <string.h>
26 #include <stdio.h>
27
28 #ifndef MAP_ANONYMOUS
29 #define MAP_ANONYMOUS MAP_ANON
30 #endif
31
32 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_bench, smpi,
33                                 "Logging specific to SMPI (benchmarking)");
34
35 /* Shared allocations are handled through shared memory segments.
36  * Associated data and metadata are used as follows:
37  *
38  *                                                                    mmap #1
39  *    `allocs' dict                                                     ---- -.
40  *    ----------      shared_data_t               shared_metadata_t   / |  |  |
41  * .->| <name> | ---> -------------------- <--.   -----------------   | |  |  |
42  * |  ----------      | fd of <name>     |    |   | size of mmap  | --| |  |  |
43  * |                  | count (2)        |    |-- | data          |   \ |  |  |
44  * `----------------- | <name>           |    |   -----------------     ----  |
45  *                    --------------------    |   ^                           |
46  *                                            |   |                           |
47  *                                            |   |   `allocs_metadata' dict  |
48  *                                            |   |   ----------------------  |
49  *                                            |   `-- | <addr of mmap #1>  |<-'
50  *                                            |   .-- | <addr of mmap #2>  |<-.
51  *                                            |   |   ----------------------  |
52  *                                            |   |                           |
53  *                                            |   |                           |
54  *                                            |   |                           |
55  *                                            |   |                   mmap #2 |
56  *                                            |   v                     ---- -'
57  *                                            |   shared_metadata_t   / |  |
58  *                                            |   -----------------   | |  |
59  *                                            |   | size of mmap  | --| |  |
60  *                                            `-- | data          |   | |  |
61  *                                                -----------------   | |  |
62  *                                                                    \ |  |
63  *                                                                      ----
64  */
65
66 #define PTR_STRLEN (2 + 2 * sizeof(void*) + 1)
67
68 xbt_dict_t allocs = NULL;          /* Allocated on first use */
69 xbt_dict_t allocs_metadata = NULL; /* Allocated on first use */
70 xbt_dict_t samples = NULL;         /* Allocated on first use */
71 xbt_dict_t calls = NULL;           /* Allocated on first use */
72 __thread int smpi_current_rank = 0;      /* Updated after each MPI call */
73
74 double smpi_cpu_threshold;
75 double smpi_running_power;
76
77 int* fds;
78 void** mappings;
79 int loaded_page = -1;
80 char* start_data_exe = NULL;
81 int size_data_exe = 0;
82 int smpi_privatize_global_variables;
83
84 typedef struct {
85   int fd;
86   int count;
87   char* loc;
88 } shared_data_t;
89
90 typedef struct  {
91   size_t size;
92   shared_data_t* data;
93 } shared_metadata_t;
94
95 static size_t shm_size(int fd) {
96   struct stat st;
97
98   if(fstat(fd, &st) < 0) {
99     xbt_die("Could not stat fd %d: %s", fd, strerror(errno));
100   }
101   return (size_t)st.st_size;
102 }
103
104 #ifndef WIN32
105 static void* shm_map(int fd, size_t size, shared_data_t* data) {
106   void* mem;
107   char loc[PTR_STRLEN];
108   shared_metadata_t* meta;
109
110   if(size > shm_size(fd)) {
111     if(ftruncate(fd, (off_t)size) < 0) {
112       xbt_die("Could not truncate fd %d to %zu: %s", fd, size, strerror(errno));
113     }
114   }
115
116   mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
117   if(mem == MAP_FAILED) {
118     xbt_die("Could not map fd %d: %s", fd, strerror(errno));
119   }
120   if(!allocs_metadata) {
121     allocs_metadata = xbt_dict_new_homogeneous(xbt_free);
122   }
123   snprintf(loc, PTR_STRLEN, "%p", mem);
124   meta = xbt_new(shared_metadata_t, 1);
125   meta->size = size;
126   meta->data = data;
127   xbt_dict_set(allocs_metadata, loc, meta, NULL);
128   XBT_DEBUG("MMAP %zu to %p", size, mem);
129   return mem;
130 }
131 #endif
132
133 void smpi_bench_destroy(void)
134 {
135   xbt_dict_free(&allocs);
136   xbt_dict_free(&allocs_metadata);
137   xbt_dict_free(&samples);
138   xbt_dict_free(&calls);
139 }
140
141 XBT_PUBLIC(void) smpi_execute_flops_(double *flops);
142 void smpi_execute_flops_(double *flops)
143 {
144   smpi_execute_flops(*flops);
145 }
146
147 XBT_PUBLIC(void) smpi_execute_(double *duration);
148 void smpi_execute_(double *duration)
149 {
150   smpi_execute(*duration);
151 }
152
153 void smpi_execute_flops(double flops) {
154   smx_action_t action;
155   smx_host_t host;
156   host = SIMIX_host_self();
157   XBT_DEBUG("Handle real computation time: %f flops", flops);
158   action = simcall_host_execute("computation", host, flops, 1, 0, 0);
159 #ifdef HAVE_TRACING
160   simcall_set_category (action, TRACE_internal_smpi_get_category());
161 #endif
162   simcall_host_execution_wait(action);
163 }
164
165 void smpi_execute(double duration)
166 {
167   if (duration >= smpi_cpu_threshold) {
168     XBT_DEBUG("Sleep for %g to handle real computation time", duration);
169     double flops = duration * smpi_running_power;
170 #ifdef HAVE_TRACING
171     int rank = smpi_process_index();
172     instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
173     extra->type=TRACING_COMPUTING;
174     extra->comp_size=flops;
175     TRACE_smpi_computing_in(rank, extra);
176 #endif
177     smpi_execute_flops(flops);
178
179 #ifdef HAVE_TRACING
180     TRACE_smpi_computing_out(rank);
181 #endif
182
183   } else {
184     XBT_DEBUG("Real computation took %g while option smpi/cpu_threshold is set to %g => ignore it",
185               duration, smpi_cpu_threshold);
186   }
187 }
188
189 void switch_data_segment(int dest);
190
191 void smpi_bench_begin(void)
192 {
193   switch_data_segment(smpi_process_index());
194   xbt_os_threadtimer_start(smpi_process_timer());
195   smpi_current_rank = smpi_process_index();
196 }
197
198 void smpi_bench_end(void)
199 {
200   xbt_os_timer_t timer = smpi_process_timer();
201   xbt_os_threadtimer_stop(timer);
202 //  switch_data_segment(smpi_process_count());
203   if (smpi_process_get_sampling()) {
204     XBT_CRITICAL("Cannot do recursive benchmarks.");
205     XBT_CRITICAL("Are you trying to make a call to MPI within a SMPI_SAMPLE_ block?");
206     xbt_backtrace_display_current();
207     xbt_die("Aborting.");
208   }
209   smpi_execute(xbt_os_timer_elapsed(timer));
210 }
211
212 unsigned int smpi_sleep(unsigned int secs)
213 {
214   smx_action_t action;
215
216   smpi_bench_end();
217
218   double flops = (double) secs*simcall_host_get_speed(SIMIX_host_self());
219   XBT_DEBUG("Sleep for: %f flops", flops);
220   action = simcall_host_execute("computation", SIMIX_host_self(), flops, 1, 0, 0);
221   #ifdef HAVE_TRACING
222     simcall_set_category (action, TRACE_internal_smpi_get_category());
223   #endif
224   simcall_host_execution_wait(action);
225
226   smpi_bench_begin();
227   return secs;
228 }
229
230 int smpi_gettimeofday(struct timeval *tv)
231 {
232   double now;
233   smpi_bench_end();
234   now = SIMIX_get_clock();
235   if (tv) {
236     tv->tv_sec = (time_t)now;
237 #ifdef WIN32
238     tv->tv_usec = (useconds_t)((now - tv->tv_sec) * 1e6);
239 #else
240     tv->tv_usec = (suseconds_t)((now - tv->tv_sec) * 1e6);
241 #endif
242   }
243   smpi_bench_begin();
244   return 0;
245 }
246
247 extern double sg_surf_precision;
248 unsigned long long smpi_rastro_resolution (void)
249 {
250   smpi_bench_end();
251   double resolution = (1/sg_surf_precision);
252   smpi_bench_begin();
253   return (unsigned long long)resolution;
254 }
255
256 unsigned long long smpi_rastro_timestamp (void)
257 {
258   smpi_bench_end();
259   double now = SIMIX_get_clock();
260
261   unsigned long long sec = (unsigned long long)now;
262   unsigned long long pre = (now - sec) * smpi_rastro_resolution();
263   smpi_bench_begin();
264   return (unsigned long long)sec * smpi_rastro_resolution() + pre;
265 }
266
267 /* ****************************** Functions related to the SMPI_SAMPLE_ macros ************************************/
268 typedef struct {
269   double threshold; /* maximal stderr requested (if positive) */
270   double relstderr; /* observed stderr so far */
271   double mean;      /* mean of benched times, to be used if the block is disabled */
272   double sum;       /* sum of benched times (to compute the mean and stderr) */
273   double sum_pow2;  /* sum of the square of the benched times (to compute the stderr) */
274   int iters;        /* amount of requested iterations */
275   int count;        /* amount of iterations done so far */
276   int benching;     /* 1: we are benchmarking; 0: we have enough data, no bench anymore */
277 } local_data_t;
278
279 static char *sample_location(int global, const char *file, int line) {
280   if (global) {
281     return bprintf("%s:%d", file, line);
282   } else {
283     return bprintf("%s:%d:%d", file, line, smpi_process_index());
284   }
285 }
286 static int sample_enough_benchs(local_data_t *data) {
287   int res = data->count >= data->iters;
288   if (data->threshold>0.0) {
289     if (data->count <2)
290       res = 0; // not enough data
291     if (data->relstderr > data->threshold)
292       res = 0; // stderr too high yet
293   }
294   XBT_DEBUG("%s (count:%d iter:%d stderr:%f thres:%f mean:%fs)",
295       (res?"enough benchs":"need more data"),
296       data->count, data->iters, data->relstderr, data->threshold, data->mean);
297   return res;
298 }
299
300 void smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
301 {
302   char *loc = sample_location(global, file, line);
303   local_data_t *data;
304
305   smpi_bench_end();     /* Take time from previous, unrelated computation into account */
306   smpi_process_set_sampling(1);
307
308   if (!samples)
309     samples = xbt_dict_new_homogeneous(free);
310
311   data = xbt_dict_get_or_null(samples, loc);
312   if (!data) {
313     xbt_assert(threshold>0 || iters>0,
314         "You should provide either a positive amount of iterations to bench, or a positive maximal stderr (or both)");
315     data = (local_data_t *) xbt_new(local_data_t, 1);
316     data->count = 0;
317     data->sum = 0.0;
318     data->sum_pow2 = 0.0;
319     data->iters = iters;
320     data->threshold = threshold;
321     data->benching = 1; // If we have no data, we need at least one
322     data->mean = 0;
323     xbt_dict_set(samples, loc, data, NULL);
324     XBT_DEBUG("XXXXX First time ever on benched nest %s.",loc);
325   } else {
326     if (data->iters != iters || data->threshold != threshold) {
327       XBT_ERROR("Asked to bench block %s with different settings %d, %f is not %d, %f. How did you manage to give two numbers at the same line??",
328           loc, data->iters, data->threshold, iters,threshold);
329       THROW_IMPOSSIBLE;
330     }
331
332     // if we already have some data, check whether sample_2 should get one more bench or whether it should emulate the computation instead
333     data->benching = !sample_enough_benchs(data);
334     XBT_DEBUG("XXXX Re-entering the benched nest %s. %s",loc, (data->benching?"more benching needed":"we have enough data, skip computes"));
335   }
336   xbt_free(loc);
337 }
338
339 int smpi_sample_2(int global, const char *file, int line)
340 {
341   char *loc = sample_location(global, file, line);
342   local_data_t *data;
343   int res;
344
345   xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
346   data = xbt_dict_get(samples, loc);
347   XBT_DEBUG("sample2 %s",loc);
348   xbt_free(loc);
349
350   if (data->benching==1) {
351     // we need to run a new bench
352     XBT_DEBUG("benchmarking: count:%d iter:%d stderr:%f thres:%f; mean:%f",
353         data->count, data->iters, data->relstderr, data->threshold, data->mean);
354     res = 1;
355   } else {
356     // Enough data, no more bench (either we got enough data from previous visits to this benched nest, or we just ran one bench and need to bail out now that our job is done).
357     // Just sleep instead
358     XBT_DEBUG("No benchmark (either no need, or just ran one): count >= iter (%d >= %d) or stderr<thres (%f<=%f). apply the %fs delay instead",
359         data->count, data->iters, data->relstderr, data->threshold, data->mean);
360     smpi_execute(data->mean);
361     smpi_process_set_sampling(0);
362     res = 0; // prepare to capture future, unrelated computations
363   }
364   smpi_bench_begin();
365   return res;
366 }
367
368
369 void smpi_sample_3(int global, const char *file, int line)
370 {
371   char *loc = sample_location(global, file, line);
372   local_data_t *data;
373
374   xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
375   data = xbt_dict_get(samples, loc);
376   XBT_DEBUG("sample3 %s",loc);
377   xbt_free(loc);
378
379   if (data->benching==0) {
380     THROW_IMPOSSIBLE;
381   }
382
383   // ok, benchmarking this loop is over
384   xbt_os_threadtimer_stop(smpi_process_timer());
385
386   // update the stats
387   double sample, n;
388   data->count++;
389   sample = xbt_os_timer_elapsed(smpi_process_timer());
390   data->sum += sample;
391   data->sum_pow2 += sample * sample;
392   n = (double)data->count;
393   data->mean = data->sum / n;
394   data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
395   if (!sample_enough_benchs(data)) {
396     data->mean = sample; // Still in benching process; We want sample_2 to simulate the exact time of this loop occurrence before leaving, not the mean over the history
397   }
398   XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
399       data->mean, data->relstderr, sample);
400
401   // That's enough for now, prevent sample_2 to run the same code over and over
402   data->benching = 0;
403 }
404
405 #ifndef WIN32
406 static void smpi_shared_alloc_free(void *p)
407 {
408   shared_data_t *data = p;
409   xbt_free(data->loc);
410   xbt_free(data);
411 }
412
413 static char *smpi_shared_alloc_hash(char *loc)
414 {
415   char hash[42];
416   char s[7];
417   unsigned val;
418   int i, j;
419
420   xbt_sha(loc, hash);
421   hash[41] = '\0';
422   s[6] = '\0';
423   loc = xbt_realloc(loc, 30);
424   loc[0] = '/';
425   for (i = 0; i < 40; i += 6) { /* base64 encode */
426     memcpy(s, hash + i, 6);
427     val = strtoul(s, NULL, 16);
428     for (j = 0; j < 4; j++) {
429       unsigned char x = (val >> (18 - 3 * j)) & 0x3f;
430       loc[1 + 4 * i / 6 + j] =
431         "ABCDEFGHIJKLMNOPQRSTUVZXYZabcdefghijklmnopqrstuvzxyz0123456789-_"[x];
432     }
433   }
434   loc[29] = '\0';
435   return loc;
436 }
437
438 void *smpi_shared_malloc(size_t size, const char *file, int line)
439 {
440   void* mem;
441   if (sg_cfg_get_boolean("smpi/use_shared_malloc")){
442     char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
443     int fd;
444     shared_data_t *data;
445     loc = smpi_shared_alloc_hash(loc); /* hash loc, in order to have something
446                                         * not too long */
447     if (!allocs) {
448       allocs = xbt_dict_new_homogeneous(smpi_shared_alloc_free);
449     }
450     data = xbt_dict_get_or_null(allocs, loc);
451     if (!data) {
452       fd = shm_open(loc, O_RDWR | O_CREAT | O_EXCL,
453                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
454       if (fd < 0) {
455         switch(errno) {
456           case EEXIST:
457             xbt_die("Please cleanup /dev/shm/%s", loc);
458           default:
459             xbt_die("An unhandled error occured while opening %s. shm_open: %s", loc, strerror(errno));
460         }
461       }
462       data = xbt_new(shared_data_t, 1);
463       data->fd = fd;
464       data->count = 1;
465       data->loc = loc;
466       mem = shm_map(fd, size, data);
467       if (shm_unlink(loc) < 0) {
468         XBT_WARN("Could not early unlink %s. shm_unlink: %s", loc, strerror(errno));
469       }
470       xbt_dict_set(allocs, loc, data, NULL);
471       XBT_DEBUG("Mapping %s at %p through %d", loc, mem, fd);
472     } else {
473       xbt_free(loc);
474       mem = shm_map(data->fd, size, data);
475       data->count++;
476     }
477     XBT_DEBUG("Shared malloc %zu in %p (metadata at %p)", size, mem, data);
478   } else {
479     mem = xbt_malloc(size);
480     XBT_DEBUG("Classic malloc %zu in %p", size, mem);
481   }
482
483   return mem;
484 }
485 void smpi_shared_free(void *ptr)
486 {
487   char loc[PTR_STRLEN];
488   shared_metadata_t* meta;
489   shared_data_t* data;
490   if (sg_cfg_get_boolean("smpi/use_shared_malloc")){
491   
492     if (!allocs) {
493       XBT_WARN("Cannot free: nothing was allocated");
494       return;
495     }
496     if(!allocs_metadata) {
497       XBT_WARN("Cannot free: no metadata was allocated");
498     }
499     snprintf(loc, PTR_STRLEN, "%p", ptr);
500     meta = (shared_metadata_t*)xbt_dict_get_or_null(allocs_metadata, loc);
501     if (!meta) {
502       XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
503       return;
504     }
505     data = meta->data;
506     if(!data) {
507       XBT_WARN("Cannot free: something is broken in the metadata link");
508       return;
509     }
510     if(munmap(ptr, meta->size) < 0) {
511       XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
512     }
513     data->count--;
514     XBT_DEBUG("Shared free - no removal - of %p, count = %d", ptr, data->count);
515     if (data->count <= 0) {
516       close(data->fd);
517       xbt_dict_remove(allocs, data->loc);
518       XBT_DEBUG("Shared free - with removal - of %p", ptr);
519     }
520   }else{
521     XBT_DEBUG("Classic free of %p", ptr);
522     xbt_free(ptr);
523   }
524 }
525 #endif
526
527 int smpi_shared_known_call(const char* func, const char* input)
528 {
529   char* loc = bprintf("%s:%s", func, input);
530   xbt_ex_t ex;
531   int known = 0;
532
533   if (!calls) {
534     calls = xbt_dict_new_homogeneous(NULL);
535   }
536   TRY {
537     xbt_dict_get(calls, loc); /* Succeed or throw */
538     known = 1;
539   }
540   TRY_CLEANUP {
541     xbt_free(loc);
542   }
543   CATCH(ex) {
544     if (ex.category != not_found_error)
545       RETHROW;
546     xbt_ex_free(ex);
547   }
548   return known;
549 }
550
551 void* smpi_shared_get_call(const char* func, const char* input) {
552    char* loc = bprintf("%s:%s", func, input);
553    void* data;
554
555    if(!calls) {
556       calls = xbt_dict_new_homogeneous(NULL);
557    }
558    data = xbt_dict_get(calls, loc);
559    free(loc);
560    return data;
561 }
562
563 void* smpi_shared_set_call(const char* func, const char* input, void* data) {
564    char* loc = bprintf("%s:%s", func, input);
565
566    if(!calls) {
567       calls = xbt_dict_new_homogeneous(NULL);
568    }
569    xbt_dict_set(calls, loc, data, NULL);
570    free(loc);
571    return data;
572 }
573
574
575
576
577 #ifndef WIN32
578 #define TOPAGE(addr) (void *)(((unsigned long)(addr) / xbt_pagesize) * xbt_pagesize)
579
580
581 /*
582  * - read the executable data+bss section addresses and sizes
583  * - for each process create a copy of these sections with mmap
584  * - store them in a dynar
585  *
586  */
587
588
589
590 void switch_data_segment(int dest){
591
592   if(size_data_exe == 0)//no need to switch
593     return;
594
595   if (loaded_page==dest)//no need to switch either
596     return;
597
598
599 #ifdef HAVE_MMAP
600   int i;
601   if(loaded_page==-1){//initial switch, do the copy from the real page here
602     for (i=0; i< SIMIX_process_count(); i++){
603       memcpy(mappings[i],TOPAGE(start_data_exe),size_data_exe);
604     }
605   }
606   int current= fds[dest];
607   XBT_VERB("Switching data frame to the one of process %d", dest);
608   void* tmp = mmap (TOPAGE(start_data_exe), size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, current, 0);
609   if (tmp != TOPAGE(start_data_exe))
610     xbt_die("Couldn't map the new region");
611   loaded_page=dest;
612 #endif
613 }
614
615 void smpi_get_executable_global_size(){
616   int size_bss_binary=0;
617   int size_data_binary=0;
618   FILE *fp;
619   char *line = NULL;            /* Temporal storage for each line that is readed */
620   ssize_t read;                 /* Number of bytes readed */
621   size_t n = 0;                 /* Amount of bytes to read by xbt_getline */
622
623   char *lfields[7];
624   int i, found = 0;
625
626   char *command = bprintf("objdump --section-headers %s", xbt_binary_name);
627
628   fp = popen(command, "r");
629
630   if(fp == NULL){
631     perror("popen failed");
632     xbt_abort();
633   }
634
635   while ((read = xbt_getline(&line, &n, fp)) != -1 && found != 2) {
636
637     if(n == 0)
638       continue;
639
640     /* Wipeout the new line character */
641     line[read - 1] = '\0';
642
643     lfields[0] = strtok(line, " ");
644
645     if(lfields[0] == NULL)
646       continue;
647
648     if(strcmp(lfields[0], "Sections:") == 0
649         || strcmp(lfields[0], "Idx") == 0
650         || strncmp(lfields[0], xbt_binary_name, strlen(xbt_binary_name)) == 0)
651       continue;
652
653     for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) {
654       lfields[i] = strtok(NULL, " ");
655     }
656
657     /*
658      * we are looking for these fields
659     23 .data         02625a20  00000000006013e0  00000000006013e0  000013e0  2**5
660                      CONTENTS, ALLOC, LOAD, DATA
661     24 .bss          02625a40  0000000002c26e00  0000000002c26e00  02626e00  2**5
662                      ALLOC
663     */
664
665     if(i>=6){
666       if(strcmp(lfields[1], ".data") == 0){
667         size_data_binary = strtoul(lfields[2], NULL, 16);
668         start_data_exe = (char*) strtoul(lfields[4], NULL, 16);
669         found++;
670       }else if(strcmp(lfields[1], ".bss") == 0){
671         //the beginning of bss is not exactly the end of data if not aligned, grow bss reported size accordingly
672         //TODO : check if this is OK, as some segments may be inserted between them.. 
673         size_bss_binary = ((char*) strtoul(lfields[4], NULL, 16) - (start_data_exe + size_data_binary))
674                           + strtoul(lfields[2], NULL, 16);
675         found++;
676        }
677
678     }
679
680   }
681
682   size_data_exe =(unsigned long)start_data_exe - (unsigned long)TOPAGE(start_data_exe)+ size_data_binary+size_bss_binary;
683   xbt_free(command);
684   xbt_free(line);
685   pclose(fp);
686
687 }
688
689 void smpi_initialize_global_memory_segments(){
690
691 #ifndef HAVE_MMAP
692   smpi_privatize_global_variables=0;
693   return;
694 #else
695
696   unsigned int i = 0;
697   smpi_get_executable_global_size();
698
699   XBT_DEBUG ("bss+data segment found : size %d starting at %p",size_data_exe, start_data_exe );
700
701   if(size_data_exe == 0){//no need to switch
702     smpi_privatize_global_variables=0;
703     return;
704   }
705
706   fds= (int*)xbt_malloc((smpi_process_count())*sizeof(int));
707   mappings= (void**)xbt_malloc((smpi_process_count())*sizeof(void*));
708
709
710   for (i=0; i< SIMIX_process_count(); i++){
711       //create SIMIX_process_count() mappings of this size with the same data inside
712       void *address = NULL, *tmp = NULL;
713       char path[] = "/dev/shm/my-buffer-XXXXXX";
714       int status;
715       int file_descriptor= mkstemp (path);
716       if (file_descriptor < 0)
717         xbt_die("Impossible to create temporary file for memory mapping");
718       status = unlink (path);
719       if (status)
720         xbt_die("Impossible to unlink temporary file for memory mapping");
721
722       status = ftruncate(file_descriptor, size_data_exe);
723       if(status)
724         xbt_die("Impossible to set the size of the temporary file for memory mapping");
725
726       /* Ask for a free region */
727       address = mmap (NULL, size_data_exe, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
728
729       if (address == MAP_FAILED)
730         xbt_die("Couldn't find a free region for memory mapping");
731
732       tmp = mmap (address, size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, file_descriptor, 0);
733
734       if (tmp != address)
735         xbt_die("Couldn't obtain the right address");
736       //initialize the values
737       memcpy(address,TOPAGE(start_data_exe),size_data_exe);
738
739       //store the address of the mapping for further switches
740       fds[i]=file_descriptor;
741       mappings[i]= address;
742   }
743
744 #endif
745
746 }
747
748 void smpi_destroy_global_memory_segments(){
749   if(size_data_exe == 0)//no need to switch
750     return;
751 #ifdef HAVE_MMAP
752   int i;
753   for (i=0; i< smpi_process_count(); i++){
754     if(munmap(mappings[i],size_data_exe) < 0) {
755       XBT_WARN("Unmapping of fd %d failed: %s", fds[i], strerror(errno));
756     }
757     close(fds[i]);
758   }
759   xbt_free(mappings);
760   xbt_free(fds);
761
762 #endif
763
764 }
765
766
767 #endif