Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
explicitely capture variables in lambda to please sonar
[simgrid.git] / src / mc / RegionSnapshot.cpp
1 /* Copyright (c) 2007-2015. 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 <cstdlib>
8
9 #include <sys/mman.h>
10 #ifdef __FreeBSD__
11 # define MAP_POPULATE MAP_PREFAULT_READ
12 #endif
13
14 #include "mc/mc.h"
15 #include "src/mc/mc_snapshot.h"
16
17 #include "src/mc/ChunkedData.hpp"
18 #include "src/mc/RegionSnapshot.hpp"
19
20 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_RegionSnaphot, mc,
21                                 "Logging specific to region snapshots");
22
23 namespace simgrid {
24 namespace mc {
25
26 static inline
27 const char* to_cstr(RegionType region)
28 {
29   switch (region) {
30   case RegionType::Unknown:
31     return "unknown";
32   case RegionType::Heap:
33     return "Heap";
34   case RegionType::Data:
35     return "Data";
36   default:
37     return "?";
38   }
39 }
40
41 Buffer::Buffer(std::size_t size, Type type) : size_(size), type_(type)
42 {
43   switch(type_) {
44   case Type::Malloc:
45     data_ = ::malloc(size_);
46     break;
47   case Type::Mmap:
48     data_ = ::mmap(nullptr, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0);
49     if (data_ == MAP_FAILED) {
50       data_ = nullptr;
51       size_ = 0;
52       type_ = Type::Malloc;
53       throw std::bad_alloc();
54     }
55     break;
56   default:
57     abort();
58   }
59 }
60
61 void Buffer::clear() noexcept
62 {
63   switch(type_) {
64   case Type::Malloc:
65     std::free(data_);
66     break;
67   case Type::Mmap:
68     if (munmap(data_, size_) != 0)
69       abort();
70     break;
71   default:
72     abort();
73   }
74   data_ = nullptr;
75   size_ = 0;
76   type_ = Type::Malloc;
77 }
78
79 RegionSnapshot dense_region(
80   RegionType region_type,
81   void *start_addr, void* permanent_addr, size_t size)
82 {
83   // When KSM support is enables, we allocate memory using mmap:
84   // * we don't want to advise bits of the heap as mergable;
85   // * mmap gives data aligned on page boundaries which is merge friendly.
86   simgrid::mc::Buffer data;
87   if (_sg_mc_ksm)
88     data = Buffer::mmap(size);
89   else
90     data = Buffer::malloc(size);
91
92   mc_model_checker->process().read_bytes(data.get(), size,
93     remote(permanent_addr),
94     simgrid::mc::ProcessIndexDisabled);
95
96 #ifdef __linux__
97   if (_sg_mc_ksm)
98     // Mark the region as mergeable *after* we have written into it.
99     // Trying to merge them before is useless/counterproductive.
100     madvise(data.get(), size, MADV_MERGEABLE);
101 #endif
102
103   simgrid::mc::RegionSnapshot region(
104     region_type, start_addr, permanent_addr, size);
105   region.flat_data(std::move(data));
106
107   XBT_DEBUG("New region : type : %s, data : %p (real addr %p), size : %zu",
108             to_cstr(region_type), region.flat_data().get(), permanent_addr, size);
109   return region;
110 }
111
112 /** @brief Take a snapshot of a given region
113  *
114  * @param type
115  * @param start_addr   Address of the region in the simulated process
116  * @param permanent_addr Permanent address of this data (for privatized variables, this is the virtual address of the privatized mapping)
117  * @param size         Size of the data*
118  */
119 RegionSnapshot region(
120   RegionType type, void *start_addr, void* permanent_addr, size_t size)
121 {
122   if (_sg_mc_sparse_checkpoint)
123     return sparse_region(type, start_addr, permanent_addr, size);
124   else
125     return dense_region(type, start_addr, permanent_addr, size);
126 }
127
128 RegionSnapshot sparse_region(RegionType region_type,
129   void *start_addr, void* permanent_addr, size_t size)
130 {
131   simgrid::mc::Process* process = &mc_model_checker->process();
132   assert(process != nullptr);
133
134   xbt_assert((((uintptr_t)start_addr) & (xbt_pagesize-1)) == 0,
135     "Not at the beginning of a page");
136   xbt_assert((((uintptr_t)permanent_addr) & (xbt_pagesize-1)) == 0,
137     "Not at the beginning of a page");
138   size_t page_count = simgrid::mc::mmu::chunkCount(size);
139
140   simgrid::mc::ChunkedData page_data(
141     mc_model_checker->page_store(), *process, permanent_addr, page_count);
142
143   simgrid::mc::RegionSnapshot region(
144     region_type, start_addr, permanent_addr, size);
145   region.page_data(std::move(page_data));
146   return region;
147 }
148   
149 }
150 }