Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Rewrote smpi_sleep() and smpi_usleep() so that:
[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 /* Private sleep function used by smpi_sleep() and smpi_usleep() */
213 static unsigned int private_sleep(double secs)
214 {
215   smpi_bench_end();
216
217   XBT_DEBUG("Sleep for: %lf secs", secs);
218   #ifdef HAVE_TRACING
219   int rank = smpi_comm_rank(MPI_COMM_WORLD);
220   instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
221   extra->type=TRACING_SLEEPING;
222   extra->sleep_duration=secs;
223   TRACE_smpi_sleeping_in(rank, extra);
224 #endif
225   simcall_process_sleep(secs);
226 #ifdef HAVE_TRACING
227   TRACE_smpi_sleeping_out(rank);
228 #endif
229
230   smpi_bench_begin();
231   return 0;
232 }
233
234 unsigned int smpi_sleep(unsigned int secs)
235 {
236   return private_sleep((double)secs);
237 }
238
239 int smpi_usleep(useconds_t usecs)
240 {
241   return (int)private_sleep((double)usecs / 1000000.0);
242 }
243
244
245 int smpi_gettimeofday(struct timeval *tv, void* tz)
246 {
247   double now;
248   smpi_bench_end();
249   now = SIMIX_get_clock();
250   if (tv) {
251     tv->tv_sec = (time_t)now;
252 #ifdef WIN32
253     tv->tv_usec = (useconds_t)((now - tv->tv_sec) * 1e6);
254 #else
255     tv->tv_usec = (suseconds_t)((now - tv->tv_sec) * 1e6);
256 #endif
257   }
258   smpi_bench_begin();
259   return 0;
260 }
261
262 extern double sg_surf_precision;
263 unsigned long long smpi_rastro_resolution (void)
264 {
265   smpi_bench_end();
266   double resolution = (1/sg_surf_precision);
267   smpi_bench_begin();
268   return (unsigned long long)resolution;
269 }
270
271 unsigned long long smpi_rastro_timestamp (void)
272 {
273   smpi_bench_end();
274   double now = SIMIX_get_clock();
275
276   unsigned long long sec = (unsigned long long)now;
277   unsigned long long pre = (now - sec) * smpi_rastro_resolution();
278   smpi_bench_begin();
279   return (unsigned long long)sec * smpi_rastro_resolution() + pre;
280 }
281
282 /* ****************************** Functions related to the SMPI_SAMPLE_ macros ************************************/
283 typedef struct {
284   double threshold; /* maximal stderr requested (if positive) */
285   double relstderr; /* observed stderr so far */
286   double mean;      /* mean of benched times, to be used if the block is disabled */
287   double sum;       /* sum of benched times (to compute the mean and stderr) */
288   double sum_pow2;  /* sum of the square of the benched times (to compute the stderr) */
289   int iters;        /* amount of requested iterations */
290   int count;        /* amount of iterations done so far */
291   int benching;     /* 1: we are benchmarking; 0: we have enough data, no bench anymore */
292 } local_data_t;
293
294 static char *sample_location(int global, const char *file, int line) {
295   if (global) {
296     return bprintf("%s:%d", file, line);
297   } else {
298     return bprintf("%s:%d:%d", file, line, smpi_process_index());
299   }
300 }
301 static int sample_enough_benchs(local_data_t *data) {
302   int res = data->count >= data->iters;
303   if (data->threshold>0.0) {
304     if (data->count <2)
305       res = 0; // not enough data
306     if (data->relstderr > data->threshold)
307       res = 0; // stderr too high yet
308   }
309   XBT_DEBUG("%s (count:%d iter:%d stderr:%f thres:%f mean:%fs)",
310       (res?"enough benchs":"need more data"),
311       data->count, data->iters, data->relstderr, data->threshold, data->mean);
312   return res;
313 }
314
315 void smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
316 {
317   char *loc = sample_location(global, file, line);
318   local_data_t *data;
319
320   smpi_bench_end();     /* Take time from previous, unrelated computation into account */
321   smpi_process_set_sampling(1);
322
323   if (!samples)
324     samples = xbt_dict_new_homogeneous(free);
325
326   data = xbt_dict_get_or_null(samples, loc);
327   if (!data) {
328     xbt_assert(threshold>0 || iters>0,
329         "You should provide either a positive amount of iterations to bench, or a positive maximal stderr (or both)");
330     data = (local_data_t *) xbt_new(local_data_t, 1);
331     data->count = 0;
332     data->sum = 0.0;
333     data->sum_pow2 = 0.0;
334     data->iters = iters;
335     data->threshold = threshold;
336     data->benching = 1; // If we have no data, we need at least one
337     data->mean = 0;
338     xbt_dict_set(samples, loc, data, NULL);
339     XBT_DEBUG("XXXXX First time ever on benched nest %s.",loc);
340   } else {
341     if (data->iters != iters || data->threshold != threshold) {
342       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??",
343           loc, data->iters, data->threshold, iters,threshold);
344       THROW_IMPOSSIBLE;
345     }
346
347     // if we already have some data, check whether sample_2 should get one more bench or whether it should emulate the computation instead
348     data->benching = !sample_enough_benchs(data);
349     XBT_DEBUG("XXXX Re-entering the benched nest %s. %s",loc, (data->benching?"more benching needed":"we have enough data, skip computes"));
350   }
351   xbt_free(loc);
352 }
353
354 int smpi_sample_2(int global, const char *file, int line)
355 {
356   char *loc = sample_location(global, file, line);
357   local_data_t *data;
358   int res;
359
360   xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
361   data = xbt_dict_get(samples, loc);
362   XBT_DEBUG("sample2 %s",loc);
363   xbt_free(loc);
364
365   if (data->benching==1) {
366     // we need to run a new bench
367     XBT_DEBUG("benchmarking: count:%d iter:%d stderr:%f thres:%f; mean:%f",
368         data->count, data->iters, data->relstderr, data->threshold, data->mean);
369     res = 1;
370   } else {
371     // 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).
372     // Just sleep instead
373     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",
374         data->count, data->iters, data->relstderr, data->threshold, data->mean);
375     smpi_execute(data->mean);
376     smpi_process_set_sampling(0);
377     res = 0; // prepare to capture future, unrelated computations
378   }
379   smpi_bench_begin();
380   return res;
381 }
382
383
384 void smpi_sample_3(int global, const char *file, int line)
385 {
386   char *loc = sample_location(global, file, line);
387   local_data_t *data;
388
389   xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
390   data = xbt_dict_get(samples, loc);
391   XBT_DEBUG("sample3 %s",loc);
392   xbt_free(loc);
393
394   if (data->benching==0) {
395     THROW_IMPOSSIBLE;
396   }
397
398   // ok, benchmarking this loop is over
399   xbt_os_threadtimer_stop(smpi_process_timer());
400
401   // update the stats
402   double sample, n;
403   data->count++;
404   sample = xbt_os_timer_elapsed(smpi_process_timer());
405   data->sum += sample;
406   data->sum_pow2 += sample * sample;
407   n = (double)data->count;
408   data->mean = data->sum / n;
409   data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
410   if (!sample_enough_benchs(data)) {
411     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
412   }
413   XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
414       data->mean, data->relstderr, sample);
415
416   // That's enough for now, prevent sample_2 to run the same code over and over
417   data->benching = 0;
418 }
419
420 #ifndef WIN32
421 static void smpi_shared_alloc_free(void *p)
422 {
423   shared_data_t *data = p;
424   xbt_free(data->loc);
425   xbt_free(data);
426 }
427
428 static char *smpi_shared_alloc_hash(char *loc)
429 {
430   char hash[42];
431   char s[7];
432   unsigned val;
433   int i, j;
434
435   xbt_sha(loc, hash);
436   hash[41] = '\0';
437   s[6] = '\0';
438   loc = xbt_realloc(loc, 30);
439   loc[0] = '/';
440   for (i = 0; i < 40; i += 6) { /* base64 encode */
441     memcpy(s, hash + i, 6);
442     val = strtoul(s, NULL, 16);
443     for (j = 0; j < 4; j++) {
444       unsigned char x = (val >> (18 - 3 * j)) & 0x3f;
445       loc[1 + 4 * i / 6 + j] =
446         "ABCDEFGHIJKLMNOPQRSTUVZXYZabcdefghijklmnopqrstuvzxyz0123456789-_"[x];
447     }
448   }
449   loc[29] = '\0';
450   return loc;
451 }
452
453 void *smpi_shared_malloc(size_t size, const char *file, int line)
454 {
455   void* mem;
456   if (sg_cfg_get_boolean("smpi/use_shared_malloc")){
457     char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
458     int fd;
459     shared_data_t *data;
460     loc = smpi_shared_alloc_hash(loc); /* hash loc, in order to have something
461                                         * not too long */
462     if (!allocs) {
463       allocs = xbt_dict_new_homogeneous(smpi_shared_alloc_free);
464     }
465     data = xbt_dict_get_or_null(allocs, loc);
466     if (!data) {
467       fd = shm_open(loc, O_RDWR | O_CREAT | O_EXCL,
468                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
469       if (fd < 0) {
470         switch(errno) {
471           case EEXIST:
472             xbt_die("Please cleanup /dev/shm/%s", loc);
473           default:
474             xbt_die("An unhandled error occured while opening %s. shm_open: %s", loc, strerror(errno));
475         }
476       }
477       data = xbt_new(shared_data_t, 1);
478       data->fd = fd;
479       data->count = 1;
480       data->loc = loc;
481       mem = shm_map(fd, size, data);
482       if (shm_unlink(loc) < 0) {
483         XBT_WARN("Could not early unlink %s. shm_unlink: %s", loc, strerror(errno));
484       }
485       xbt_dict_set(allocs, loc, data, NULL);
486       XBT_DEBUG("Mapping %s at %p through %d", loc, mem, fd);
487     } else {
488       xbt_free(loc);
489       mem = shm_map(data->fd, size, data);
490       data->count++;
491     }
492     XBT_DEBUG("Shared malloc %zu in %p (metadata at %p)", size, mem, data);
493   } else {
494     mem = xbt_malloc(size);
495     XBT_DEBUG("Classic malloc %zu in %p", size, mem);
496   }
497
498   return mem;
499 }
500 void smpi_shared_free(void *ptr)
501 {
502   char loc[PTR_STRLEN];
503   shared_metadata_t* meta;
504   shared_data_t* data;
505   if (sg_cfg_get_boolean("smpi/use_shared_malloc")){
506   
507     if (!allocs) {
508       XBT_WARN("Cannot free: nothing was allocated");
509       return;
510     }
511     if(!allocs_metadata) {
512       XBT_WARN("Cannot free: no metadata was allocated");
513     }
514     snprintf(loc, PTR_STRLEN, "%p", ptr);
515     meta = (shared_metadata_t*)xbt_dict_get_or_null(allocs_metadata, loc);
516     if (!meta) {
517       XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
518       return;
519     }
520     data = meta->data;
521     if(!data) {
522       XBT_WARN("Cannot free: something is broken in the metadata link");
523       return;
524     }
525     if(munmap(ptr, meta->size) < 0) {
526       XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
527     }
528     data->count--;
529     XBT_DEBUG("Shared free - no removal - of %p, count = %d", ptr, data->count);
530     if (data->count <= 0) {
531       close(data->fd);
532       xbt_dict_remove(allocs, data->loc);
533       XBT_DEBUG("Shared free - with removal - of %p", ptr);
534     }
535   }else{
536     XBT_DEBUG("Classic free of %p", ptr);
537     xbt_free(ptr);
538   }
539 }
540 #endif
541
542 int smpi_shared_known_call(const char* func, const char* input)
543 {
544   char* loc = bprintf("%s:%s", func, input);
545   xbt_ex_t ex;
546   int known = 0;
547
548   if (!calls) {
549     calls = xbt_dict_new_homogeneous(NULL);
550   }
551   TRY {
552     xbt_dict_get(calls, loc); /* Succeed or throw */
553     known = 1;
554   }
555   TRY_CLEANUP {
556     xbt_free(loc);
557   }
558   CATCH(ex) {
559     if (ex.category != not_found_error)
560       RETHROW;
561     xbt_ex_free(ex);
562   }
563   return known;
564 }
565
566 void* smpi_shared_get_call(const char* func, const char* input) {
567    char* loc = bprintf("%s:%s", func, input);
568    void* data;
569
570    if(!calls) {
571       calls = xbt_dict_new_homogeneous(NULL);
572    }
573    data = xbt_dict_get(calls, loc);
574    free(loc);
575    return data;
576 }
577
578 void* smpi_shared_set_call(const char* func, const char* input, void* data) {
579    char* loc = bprintf("%s:%s", func, input);
580
581    if(!calls) {
582       calls = xbt_dict_new_homogeneous(NULL);
583    }
584    xbt_dict_set(calls, loc, data, NULL);
585    free(loc);
586    return data;
587 }
588
589
590
591
592 #define TOPAGE(addr) (void *)(((unsigned long)(addr) / xbt_pagesize) * xbt_pagesize)
593
594
595 /*
596  * - read the executable data+bss section addresses and sizes
597  * - for each process create a copy of these sections with mmap
598  * - store them in a dynar
599  *
600  */
601
602
603
604 void switch_data_segment(int dest){
605
606   if(size_data_exe == 0)//no need to switch
607     return;
608
609   if (loaded_page==dest)//no need to switch either
610     return;
611
612
613 #ifdef HAVE_MMAP
614   int i;
615   if(loaded_page==-1){//initial switch, do the copy from the real page here
616     for (i=0; i< SIMIX_process_count(); i++){
617       memcpy(mappings[i],TOPAGE(start_data_exe),size_data_exe);
618     }
619   }
620   int current= fds[dest];
621   XBT_VERB("Switching data frame to the one of process %d", dest);
622   void* tmp = mmap (TOPAGE(start_data_exe), size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, current, 0);
623   if (tmp != TOPAGE(start_data_exe))
624     xbt_die("Couldn't map the new region");
625   loaded_page=dest;
626 #endif
627 }
628
629 void smpi_get_executable_global_size(){
630   int size_bss_binary=0;
631   int size_data_binary=0;
632   FILE *fp;
633   char *line = NULL;            /* Temporal storage for each line that is readed */
634   ssize_t read;                 /* Number of bytes readed */
635   size_t n = 0;                 /* Amount of bytes to read by xbt_getline */
636
637   char *lfields[7];
638   int i, found = 0;
639
640   char *command = bprintf("objdump --section-headers %s", xbt_binary_name);
641
642   fp = popen(command, "r");
643
644   if(fp == NULL){
645     perror("popen failed");
646     xbt_abort();
647   }
648
649   while ((read = xbt_getline(&line, &n, fp)) != -1 && found != 2) {
650
651     if(n == 0)
652       continue;
653
654     /* Wipeout the new line character */
655     line[read - 1] = '\0';
656
657     lfields[0] = strtok(line, " ");
658
659     if(lfields[0] == NULL)
660       continue;
661
662     if(strcmp(lfields[0], "Sections:") == 0
663         || strcmp(lfields[0], "Idx") == 0
664         || strncmp(lfields[0], xbt_binary_name, strlen(xbt_binary_name)) == 0)
665       continue;
666
667     for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) {
668       lfields[i] = strtok(NULL, " ");
669     }
670
671     /*
672      * we are looking for these fields
673     23 .data         02625a20  00000000006013e0  00000000006013e0  000013e0  2**5
674                      CONTENTS, ALLOC, LOAD, DATA
675     24 .bss          02625a40  0000000002c26e00  0000000002c26e00  02626e00  2**5
676                      ALLOC
677     */
678
679     if(i>=6){
680       if(strcmp(lfields[1], ".data") == 0){
681         size_data_binary = strtoul(lfields[2], NULL, 16);
682         start_data_exe = (char*) strtoul(lfields[4], NULL, 16);
683         found++;
684       }else if(strcmp(lfields[1], ".bss") == 0){
685         //the beginning of bss is not exactly the end of data if not aligned, grow bss reported size accordingly
686         //TODO : check if this is OK, as some segments may be inserted between them.. 
687         size_bss_binary = ((char*) strtoul(lfields[4], NULL, 16) - (start_data_exe + size_data_binary))
688                           + strtoul(lfields[2], NULL, 16);
689         found++;
690        }
691
692     }
693
694   }
695
696   size_data_exe =(unsigned long)start_data_exe - (unsigned long)TOPAGE(start_data_exe)+ size_data_binary+size_bss_binary;
697   xbt_free(command);
698   xbt_free(line);
699   pclose(fp);
700
701 }
702
703 void smpi_initialize_global_memory_segments(){
704
705 #ifndef HAVE_MMAP
706   smpi_privatize_global_variables=0;
707   return;
708 #else
709
710   unsigned int i = 0;
711   smpi_get_executable_global_size();
712
713   XBT_DEBUG ("bss+data segment found : size %d starting at %p",size_data_exe, start_data_exe );
714
715   if(size_data_exe == 0){//no need to switch
716     smpi_privatize_global_variables=0;
717     return;
718   }
719
720   fds= (int*)xbt_malloc((smpi_process_count())*sizeof(int));
721   mappings= (void**)xbt_malloc((smpi_process_count())*sizeof(void*));
722
723
724   for (i=0; i< SIMIX_process_count(); i++){
725       //create SIMIX_process_count() mappings of this size with the same data inside
726       void *address = NULL, *tmp = NULL;
727       char path[] = "/dev/shm/my-buffer-XXXXXX";
728       int status;
729       int file_descriptor= mkstemp (path);
730       if (file_descriptor < 0)
731         xbt_die("Impossible to create temporary file for memory mapping");
732       status = unlink (path);
733       if (status)
734         xbt_die("Impossible to unlink temporary file for memory mapping");
735
736       status = ftruncate(file_descriptor, size_data_exe);
737       if(status)
738         xbt_die("Impossible to set the size of the temporary file for memory mapping");
739
740       /* Ask for a free region */
741       address = mmap (NULL, size_data_exe, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
742
743       if (address == MAP_FAILED)
744         xbt_die("Couldn't find a free region for memory mapping");
745
746       tmp = mmap (address, size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, file_descriptor, 0);
747
748       if (tmp != address)
749         xbt_die("Couldn't obtain the right address");
750       //initialize the values
751       memcpy(address,TOPAGE(start_data_exe),size_data_exe);
752
753       //store the address of the mapping for further switches
754       fds[i]=file_descriptor;
755       mappings[i]= address;
756   }
757
758 #endif
759
760 }
761
762 void smpi_destroy_global_memory_segments(){
763   if(size_data_exe == 0)//no need to switch
764     return;
765 #ifdef HAVE_MMAP
766   int i;
767   for (i=0; i< smpi_process_count(); i++){
768     if(munmap(mappings[i],size_data_exe) < 0) {
769       XBT_WARN("Unmapping of fd %d failed: %s", fds[i], strerror(errno));
770     }
771     close(fds[i]);
772   }
773   xbt_free(mappings);
774   xbt_free(fds);
775
776 #endif
777
778 }
779