Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] s/NULL/nullptr/
[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 <sys/mman.h>
8
9 #include "mc/mc.h"
10 #include "src/mc/mc_snapshot.h"
11
12 #include "src/mc/ChunkedData.hpp"
13 #include "src/mc/RegionSnapshot.hpp"
14
15 extern "C" {
16
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_RegionSnaphot, mc,
18                                 "Logging specific to region snapshots");
19
20 }
21
22 namespace simgrid {
23 namespace mc {
24
25 static inline
26 const char* to_cstr(RegionType region)
27 {
28   switch (region) {
29   case RegionType::Unknown:
30     return "unknown";
31   case RegionType::Heap:
32     return "Heap";
33   case RegionType::Data:
34     return "Data";
35   default:
36     return "?";
37   }
38 }
39
40 void data_deleter::operator()(void* p) const
41 {
42   switch(type_) {
43   case Free:
44     free(p);
45     break;
46   case Munmap:
47     munmap(p, size_);
48     break;
49   }
50 }
51
52 RegionSnapshot dense_region(
53   RegionType region_type,
54   void *start_addr, void* permanent_addr, size_t size)
55 {
56   simgrid::mc::RegionSnapshot::flat_data_ptr data;
57   if (!_sg_mc_ksm)
58     data = simgrid::mc::RegionSnapshot::flat_data_ptr((char*) malloc(size));
59   else {
60     char* ptr = (char*) mmap(nullptr, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0);
61     if (ptr == MAP_FAILED)
62       throw std::bad_alloc();
63     simgrid::mc::data_deleter deleter(
64       simgrid::mc::data_deleter::Munmap, size);
65     data = simgrid::mc::RegionSnapshot::flat_data_ptr(ptr, deleter);
66   }
67   mc_model_checker->process().read_bytes(data.get(), size,
68     remote(permanent_addr),
69     simgrid::mc::ProcessIndexDisabled);
70   if (_sg_mc_ksm)
71     // Mark the region as mergeable *after* we have written into it.
72     // There no point to let KSM do the hard work before that.
73     madvise(data.get(), size, MADV_MERGEABLE);
74
75   simgrid::mc::RegionSnapshot region(
76     region_type, start_addr, permanent_addr, size);
77   region.flat_data(std::move(data));
78
79   XBT_DEBUG("New region : type : %s, data : %p (real addr %p), size : %zu",
80             to_cstr(region_type), region.flat_data(), permanent_addr, size);
81   return std::move(region);
82 }
83
84 /** @brief Take a snapshot of a given region
85  *
86  * @param type
87  * @param start_addr   Address of the region in the simulated process
88  * @param permanent_addr Permanent address of this data (for privatized variables, this is the virtual address of the privatized mapping)
89  * @param size         Size of the data*
90  */
91 RegionSnapshot region(
92   RegionType type, void *start_addr, void* permanent_addr, size_t size,
93   RegionSnapshot const* ref_region)
94 {
95   if (_sg_mc_sparse_checkpoint) {
96     return sparse_region(type, start_addr, permanent_addr, size, ref_region);
97   } else  {
98     return dense_region(type, start_addr, permanent_addr, size);
99   }
100 }
101
102 RegionSnapshot sparse_region(RegionType region_type,
103   void *start_addr, void* permanent_addr, size_t size,
104   RegionSnapshot const* ref_region)
105 {
106   simgrid::mc::Process* process = &mc_model_checker->process();
107   assert(process != nullptr);
108
109   bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty
110     && ref_region != nullptr
111     && ref_region->storage_type() == simgrid::mc::StorageType::Chunked;
112
113   xbt_assert((((uintptr_t)start_addr) & (xbt_pagesize-1)) == 0,
114     "Not at the beginning of a page");
115   xbt_assert((((uintptr_t)permanent_addr) & (xbt_pagesize-1)) == 0,
116     "Not at the beginning of a page");
117   size_t page_count = mc_page_count(size);
118
119   std::vector<std::uint64_t> pagemap;
120   const size_t* ref_page_numbers = nullptr;
121   if (use_soft_dirty) {
122     pagemap.resize(page_count);
123     process->read_pagemap(pagemap.data(),
124       mc_page_number(nullptr, permanent_addr), page_count);
125     ref_page_numbers = ref_region->page_data().pagenos();
126   }
127
128   simgrid::mc::ChunkedData page_data(
129     mc_model_checker->page_store(), *process, permanent_addr, page_count,
130     ref_page_numbers,
131     use_soft_dirty ? pagemap.data() : nullptr);
132
133   simgrid::mc::RegionSnapshot region(
134     region_type, start_addr, permanent_addr, size);
135   region.page_data(std::move(page_data));
136   return std::move(region);
137 }
138   
139 }
140 }