Logo AND Algorithmique Numérique Distribuée

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