Logo AND Algorithmique Numérique Distribuée

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