Logo AND Algorithmique Numérique Distribuée

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