Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fix compil of smpi_bench.c on win32
[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 #define TOPAGE(addr) (void *)(((unsigned long)(addr) / xbt_pagesize) * xbt_pagesize)
578
579
580 /*
581  * - read the executable data+bss section addresses and sizes
582  * - for each process create a copy of these sections with mmap
583  * - store them in a dynar
584  *
585  */
586
587
588
589 void switch_data_segment(int dest){
590
591   if(size_data_exe == 0)//no need to switch
592     return;
593
594   if (loaded_page==dest)//no need to switch either
595     return;
596
597
598 #ifdef HAVE_MMAP
599   int i;
600   if(loaded_page==-1){//initial switch, do the copy from the real page here
601     for (i=0; i< SIMIX_process_count(); i++){
602       memcpy(mappings[i],TOPAGE(start_data_exe),size_data_exe);
603     }
604   }
605   int current= fds[dest];
606   XBT_VERB("Switching data frame to the one of process %d", dest);
607   void* tmp = mmap (TOPAGE(start_data_exe), size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, current, 0);
608   if (tmp != TOPAGE(start_data_exe))
609     xbt_die("Couldn't map the new region");
610   loaded_page=dest;
611 #endif
612 }
613
614 void smpi_get_executable_global_size(){
615   int size_bss_binary=0;
616   int size_data_binary=0;
617   FILE *fp;
618   char *line = NULL;            /* Temporal storage for each line that is readed */
619   ssize_t read;                 /* Number of bytes readed */
620   size_t n = 0;                 /* Amount of bytes to read by xbt_getline */
621
622   char *lfields[7];
623   int i, found = 0;
624
625   char *command = bprintf("objdump --section-headers %s", xbt_binary_name);
626
627   fp = popen(command, "r");
628
629   if(fp == NULL){
630     perror("popen failed");
631     xbt_abort();
632   }
633
634   while ((read = xbt_getline(&line, &n, fp)) != -1 && found != 2) {
635
636     if(n == 0)
637       continue;
638
639     /* Wipeout the new line character */
640     line[read - 1] = '\0';
641
642     lfields[0] = strtok(line, " ");
643
644     if(lfields[0] == NULL)
645       continue;
646
647     if(strcmp(lfields[0], "Sections:") == 0
648         || strcmp(lfields[0], "Idx") == 0
649         || strncmp(lfields[0], xbt_binary_name, strlen(xbt_binary_name)) == 0)
650       continue;
651
652     for (i = 1; i < 7 && lfields[i - 1] != NULL; i++) {
653       lfields[i] = strtok(NULL, " ");
654     }
655
656     /*
657      * we are looking for these fields
658     23 .data         02625a20  00000000006013e0  00000000006013e0  000013e0  2**5
659                      CONTENTS, ALLOC, LOAD, DATA
660     24 .bss          02625a40  0000000002c26e00  0000000002c26e00  02626e00  2**5
661                      ALLOC
662     */
663
664     if(i>=6){
665       if(strcmp(lfields[1], ".data") == 0){
666         size_data_binary = strtoul(lfields[2], NULL, 16);
667         start_data_exe = (char*) strtoul(lfields[4], NULL, 16);
668         found++;
669       }else if(strcmp(lfields[1], ".bss") == 0){
670         //the beginning of bss is not exactly the end of data if not aligned, grow bss reported size accordingly
671         //TODO : check if this is OK, as some segments may be inserted between them.. 
672         size_bss_binary = ((char*) strtoul(lfields[4], NULL, 16) - (start_data_exe + size_data_binary))
673                           + strtoul(lfields[2], NULL, 16);
674         found++;
675        }
676
677     }
678
679   }
680
681   size_data_exe =(unsigned long)start_data_exe - (unsigned long)TOPAGE(start_data_exe)+ size_data_binary+size_bss_binary;
682   xbt_free(command);
683   xbt_free(line);
684   pclose(fp);
685
686 }
687
688 void smpi_initialize_global_memory_segments(){
689
690 #ifndef HAVE_MMAP
691   smpi_privatize_global_variables=0;
692   return;
693 #else
694
695   unsigned int i = 0;
696   smpi_get_executable_global_size();
697
698   XBT_DEBUG ("bss+data segment found : size %d starting at %p",size_data_exe, start_data_exe );
699
700   if(size_data_exe == 0){//no need to switch
701     smpi_privatize_global_variables=0;
702     return;
703   }
704
705   fds= (int*)xbt_malloc((smpi_process_count())*sizeof(int));
706   mappings= (void**)xbt_malloc((smpi_process_count())*sizeof(void*));
707
708
709   for (i=0; i< SIMIX_process_count(); i++){
710       //create SIMIX_process_count() mappings of this size with the same data inside
711       void *address = NULL, *tmp = NULL;
712       char path[] = "/dev/shm/my-buffer-XXXXXX";
713       int status;
714       int file_descriptor= mkstemp (path);
715       if (file_descriptor < 0)
716         xbt_die("Impossible to create temporary file for memory mapping");
717       status = unlink (path);
718       if (status)
719         xbt_die("Impossible to unlink temporary file for memory mapping");
720
721       status = ftruncate(file_descriptor, size_data_exe);
722       if(status)
723         xbt_die("Impossible to set the size of the temporary file for memory mapping");
724
725       /* Ask for a free region */
726       address = mmap (NULL, size_data_exe, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
727
728       if (address == MAP_FAILED)
729         xbt_die("Couldn't find a free region for memory mapping");
730
731       tmp = mmap (address, size_data_exe, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, file_descriptor, 0);
732
733       if (tmp != address)
734         xbt_die("Couldn't obtain the right address");
735       //initialize the values
736       memcpy(address,TOPAGE(start_data_exe),size_data_exe);
737
738       //store the address of the mapping for further switches
739       fds[i]=file_descriptor;
740       mappings[i]= address;
741   }
742
743 #endif
744
745 }
746
747 void smpi_destroy_global_memory_segments(){
748   if(size_data_exe == 0)//no need to switch
749     return;
750 #ifdef HAVE_MMAP
751   int i;
752   for (i=0; i< smpi_process_count(); i++){
753     if(munmap(mappings[i],size_data_exe) < 0) {
754       XBT_WARN("Unmapping of fd %d failed: %s", fds[i], strerror(errno));
755     }
756     close(fds[i]);
757   }
758   xbt_free(mappings);
759   xbt_free(fds);
760
761 #endif
762
763 }
764