Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e54516a157ab9aee5d20cdbb6db203c6d6111609
[simgrid.git] / src / mc / RegionSnapshot.hpp
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 #ifndef SIMGRID_MC_REGION_SNAPSHOT_HPP
8 #define SIMGRID_MC_REGION_SNAPSHOT_HPP
9
10 #include <cstddef>
11 #include <utility>
12
13 #include <xbt/base.h>
14
15 #include "PageStore.hpp"
16 #include "AddressSpace.hpp"
17
18 namespace simgrid {
19 namespace mc {
20
21 class PerPageCopy {
22   PageStore* store_;
23   std::vector<std::size_t> pagenos_;
24 public:
25   PerPageCopy() : store_(nullptr) {}
26   PerPageCopy(PerPageCopy const& that)
27   {
28     store_ = that.store_;
29     pagenos_ = that.pagenos_;
30     for (std::size_t pageno : pagenos_)
31       store_->ref_page(pageno);
32   }
33   void clear()
34   {
35     for (std::size_t pageno : pagenos_)
36       store_->unref_page(pageno);
37     pagenos_.clear();
38   }
39   ~PerPageCopy() {
40     clear();
41   }
42
43   PerPageCopy(PerPageCopy&& that)
44   {
45     store_ = that.store_;
46     that.store_ = nullptr;
47     pagenos_ = std::move(that.pagenos_);
48     that.pagenos_.clear();
49   }
50   PerPageCopy& operator=(PerPageCopy const& that)
51   {
52     this->clear();
53     store_ = that.store_;
54     pagenos_ = that.pagenos_;
55     for (std::size_t pageno : pagenos_)
56       store_->ref_page(pageno);
57     return *this;
58   }
59   PerPageCopy& operator=(PerPageCopy && that)
60   {
61     this->clear();
62     store_ = that.store_;
63     that.store_ = nullptr;
64     pagenos_ = std::move(that.pagenos_);
65     that.pagenos_.clear();
66     return *this;
67   }
68
69   std::size_t page_count() const
70   {
71     return pagenos_.size();
72   }
73
74   std::size_t pageno(std::size_t i) const
75   {
76     return pagenos_[i];
77   }
78
79   const std::size_t* pagenos() const { return pagenos_.data(); }
80   std::size_t*       pagenos()       { return pagenos_.data(); }
81
82   const void* page(std::size_t i) const
83   {
84     return store_->get_page(pagenos_[i]);
85   }
86
87   PerPageCopy(PageStore& store, AddressSpace& as,
88     remote_ptr<void> addr, std::size_t page_count,
89     const size_t* ref_page_numbers, const std::uint64_t* pagemap);
90 };
91
92 enum class RegionType {
93   Unknown = 0,
94   Heap = 1,
95   Data = 2
96 };
97
98 // TODO, use Boost.Variant instead of this
99 enum class StorageType {
100   NoData = 0,
101   Flat = 1,
102   Chunked = 2,
103   Privatized = 3
104 };
105
106 class data_deleter {
107 public:
108   enum Type {
109     Free,
110     Munmap
111   };
112 private:
113   Type type_;
114   std::size_t size_;
115 public:
116   data_deleter() : type_(Free) {}
117   data_deleter(Type type, std::size_t size) : type_(type), size_(size) {}
118   void operator()(void* p) const;
119 };
120
121 /** @brief Copy/snapshot of a given memory region
122  *
123  *  Different types of region snapshot storage types exist:
124  *  <ul>
125  *    <li>flat/dense snapshots are a simple copy of the region;</li>
126  *    <li>sparse/per-page snapshots are snaapshots which shared
127  *    identical pages.</li>
128  *    <li>privatized (SMPI global variable privatisation).
129  *  </ul>
130  *
131  *  This is handled with a variant based approch:
132  *
133  *    * `storage_type` identified the type of storage;
134  *    * an anonymous enum is used to distinguish the relevant types for
135  *      each type.
136  */
137 class RegionSnapshot {
138 public:
139   static const RegionType UnknownRegion = RegionType::Unknown;
140   static const RegionType HeapRegion = RegionType::Heap;
141   static const RegionType DataRegion = RegionType::Data;
142   static const StorageType NoData = StorageType::NoData;
143   static const StorageType FlatData = StorageType::Flat;
144   static const StorageType ChunkedData = StorageType::Chunked;
145   static const StorageType PrivatizedData = StorageType::Privatized;
146 public:
147   typedef std::unique_ptr<char[], data_deleter> flat_data_ptr;
148 private:
149   RegionType region_type_;
150   StorageType storage_type_;
151   simgrid::mc::ObjectInformation* object_info_;
152
153   /** @brief  Virtual address of the region in the simulated process */
154   void *start_addr_;
155
156   /** @brief Size of the data region in bytes */
157   size_t size_;
158
159   /** @brief Permanent virtual address of the region
160    *
161    * This is usually the same address as the simuilated process address.
162    * However, when using SMPI privatization of global variables,
163    * each SMPI process has its own set of global variables stored
164    * at a different virtual address. The scheduler maps those region
165    * on the region of the global variables.
166    *
167    * */
168   void *permanent_addr_;
169
170   flat_data_ptr flat_data_;
171   PerPageCopy page_numbers_;
172   std::vector<RegionSnapshot> privatized_regions_;
173 public:
174   RegionSnapshot() :
175     region_type_(UnknownRegion),
176     storage_type_(NoData),
177     object_info_(nullptr),
178     start_addr_(nullptr),
179     size_(0),
180     permanent_addr_(nullptr)
181   {}
182   RegionSnapshot(RegionType type, void *start_addr, void* permanent_addr, size_t size) :
183     region_type_(type),
184     storage_type_(NoData),
185     object_info_(nullptr),
186     start_addr_(start_addr),
187     size_(size),
188     permanent_addr_(permanent_addr)
189   {}
190   ~RegionSnapshot() {}
191   RegionSnapshot(RegionSnapshot const&) = default;
192   RegionSnapshot& operator=(RegionSnapshot const&) = default;
193   RegionSnapshot(RegionSnapshot&& that)
194   {
195     region_type_ = that.region_type_;
196     storage_type_ = that.storage_type_;
197     object_info_ = that.object_info_;
198     start_addr_ = that.start_addr_;
199     size_ = that.size_;
200     permanent_addr_ = that.permanent_addr_;
201     flat_data_ = std::move(that.flat_data_);
202     page_numbers_ = std::move(that.page_numbers_);
203     privatized_regions_ = std::move(that.privatized_regions_);
204     that.clear();
205   }
206   RegionSnapshot& operator=(RegionSnapshot&& that)
207   {
208     region_type_ = that.region_type_;
209     storage_type_ = that.storage_type_;
210     object_info_ = that.object_info_;
211     start_addr_ = that.start_addr_;
212     size_ = that.size_;
213     permanent_addr_ = that.permanent_addr_;
214     flat_data_ = std::move(that.flat_data_);
215     page_numbers_ = std::move(that.page_numbers_);
216     privatized_regions_ = std::move(that.privatized_regions_);
217     that.clear();
218     return *this;
219   }
220
221   // Data
222
223   void clear()
224   {
225     region_type_ = UnknownRegion;
226     storage_type_ = NoData;
227     privatized_regions_.clear();
228     page_numbers_.clear();
229     flat_data_.reset();
230     object_info_ = nullptr;
231     start_addr_ = nullptr;
232     size_ = 0;
233     permanent_addr_ = nullptr;
234   }
235
236   void clear_data()
237   {
238     storage_type_ = NoData;
239     flat_data_.reset();
240     page_numbers_.clear();
241     privatized_regions_.clear();
242   }
243   
244   void flat_data(flat_data_ptr data)
245   {
246     storage_type_ = FlatData;
247     flat_data_ = std::move(data);
248     page_numbers_.clear();
249     privatized_regions_.clear();
250   }
251   const char* flat_data() const { return flat_data_.get(); }
252
253   void page_data(PerPageCopy page_data)
254   {
255     storage_type_ = ChunkedData;
256     flat_data_.reset();
257     page_numbers_ = std::move(page_data);
258     privatized_regions_.clear();
259   }
260   PerPageCopy const& page_data() const { return page_numbers_; }
261
262   void privatized_data(std::vector<RegionSnapshot> data)
263   {
264     storage_type_ = PrivatizedData;
265     flat_data_.reset();
266     page_numbers_.clear();
267     privatized_regions_ = std::move(data);
268   }
269   std::vector<RegionSnapshot> const& privatized_data() const
270   {
271     return privatized_regions_;
272   }
273   std::vector<RegionSnapshot>& privatized_data()
274   {
275     return privatized_regions_;
276   }
277
278   simgrid::mc::ObjectInformation* object_info() const { return object_info_; }
279   void object_info(simgrid::mc::ObjectInformation* info) { object_info_ = info; }
280
281   // Other getters
282
283   remote_ptr<void> start() const { return remote(start_addr_); }
284   remote_ptr<void> end() const { return remote((char*)start_addr_ + size_); }
285   remote_ptr<void> permanent_address() const { return remote(permanent_addr_); }
286   std::size_t size() const { return size_; }
287   StorageType storage_type() const { return storage_type_; }
288   RegionType region_type() const { return region_type_; }
289
290   bool contain(remote_ptr<void> p) const
291   {
292     return p >= start() && p < end();
293   }
294 };
295
296 RegionSnapshot privatized_region(
297   RegionType type, void *start_addr, void* data_addr, size_t size);
298 RegionSnapshot dense_region(
299   RegionType type, void *start_addr, void* data_addr, size_t size);
300 simgrid::mc::RegionSnapshot sparse_region(
301   RegionType type, void *start_addr, void* data_addr, size_t size,
302   RegionSnapshot const* ref_region);
303 simgrid::mc::RegionSnapshot region(
304   RegionType type, void *start_addr, void* data_addr, size_t size,
305   RegionSnapshot const* ref_region);
306
307 }
308 }
309
310 typedef class simgrid::mc::RegionSnapshot s_mc_mem_region_t, *mc_mem_region_t;
311
312 #endif