Logo AND Algorithmique Numérique Distribuée

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