Logo AND Algorithmique Numérique Distribuée

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