Logo AND Algorithmique Numérique Distribuée

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