Logo AND Algorithmique Numérique Distribuée

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