extern XBT_PRIVATE int _sg_mc_checkpoint;
extern XBT_PUBLIC(int) _sg_mc_sparse_checkpoint;
extern XBT_PUBLIC(int) _sg_mc_ksm;
-extern XBT_PUBLIC(int) _sg_mc_soft_dirty;
extern XBT_PUBLIC(char*) _sg_mc_property_file;
extern XBT_PRIVATE int _sg_mc_timeout;
extern XBT_PRIVATE int _sg_mc_hash;
XBT_PRIVATE void _mc_cfg_cb_checkpoint(const char *name);
XBT_PRIVATE void _mc_cfg_cb_sparse_checkpoint(const char *name);
XBT_PRIVATE void _mc_cfg_cb_ksm(const char *name);
-XBT_PRIVATE void _mc_cfg_cb_soft_dirty(const char *name);
XBT_PRIVATE void _mc_cfg_cb_property(const char *name);
XBT_PRIVATE void _mc_cfg_cb_timeout(const char *name);
XBT_PRIVATE void _mc_cfg_cb_snapshot_fds(const char *name);
#include "src/mc/ChunkedData.hpp"
#include "src/mc/PageStore.hpp"
-#define SOFT_DIRTY_BIT_NUMBER 55
-#define SOFT_DIRTY (((uint64_t)1) << SOFT_DIRTY_BIT_NUMBER)
-
namespace simgrid {
namespace mc {
* @return Snapshot page numbers of this new snapshot
*/
ChunkedData::ChunkedData(PageStore& store, AddressSpace& as,
- RemotePtr<void> addr, std::size_t page_count,
- const std::size_t* ref_page_numbers, const std::uint64_t* pagemap)
+ RemotePtr<void> addr, std::size_t page_count)
{
store_ = &store;
this->pagenos_.resize(page_count);
for (size_t i = 0; i != page_count; ++i) {
- // We don't have to compare soft-clean pages:
- if (ref_page_numbers && pagemap && !(pagemap[i] & SOFT_DIRTY)) {
- pagenos_[i] = ref_page_numbers[i];
- store_->ref_page(ref_page_numbers[i]);
- continue;
- }
-
RemotePtr<void> page = remote((void*)
simgrid::mc::mmu::join(i, addr.address()));
xbt_assert(simgrid::mc::mmu::split(page.address()).second == 0,
}
ChunkedData(PageStore& store, AddressSpace& as,
- RemotePtr<void> addr, std::size_t page_count,
- const std::size_t* ref_page_numbers, const std::uint64_t* pagemap);
+ RemotePtr<void> addr, std::size_t page_count);
};
}
* The first (lower) layer of the per-page snapshot mechanism is a page
* store: its responsibility is to store immutable shareable
* reference-counted memory pages independently of the snapshotting
- * logic. Snapshot management and representation, soft-dirty tracking is
+ * logic. Snapshot management and representation is
* handled to an higher layer. READMORE
*
* Data structure:
close(fd);
}
-static
-int open_process_file(pid_t pid, const char* file, int flags)
-{
- char buff[50];
- snprintf(buff, sizeof(buff), "/proc/%li/%s", (long) pid, file);
- return open(buff, flags);
-}
-
int open_vm(pid_t pid, int flags)
{
const size_t buffer_size = 30;
}
unw_destroy_addr_space(this->unw_addr_space);
-
- if (this->clear_refs_fd_ >= 0)
- close(this->clear_refs_fd_);
- if (this->pagemap_fd_ >= 0)
- close(this->pagemap_fd_);
}
/** Refresh the information about the process
ignored_regions_.begin() + position, region);
}
-void Process::reset_soft_dirty()
-{
- if (this->clear_refs_fd_ < 0) {
- this->clear_refs_fd_ = open_process_file(pid_, "clear_refs", O_WRONLY|O_CLOEXEC);
- if (this->clear_refs_fd_ < 0)
- xbt_die("Could not open clear_refs file for soft-dirty tracking. Run as root?");
- }
- if(::write(this->clear_refs_fd_, "4\n", 2) != 2)
- xbt_die("Could not reset softdirty bits");
-}
-
-void Process::read_pagemap(uint64_t* pagemap, size_t page_start, size_t page_count)
-{
- if (pagemap_fd_ < 0) {
- pagemap_fd_ = open_process_file(pid_, "pagemap", O_RDONLY|O_CLOEXEC);
- if (pagemap_fd_ < 0)
- xbt_die("Could not open pagemap file for soft-dirty tracking. Run as root?");
- }
- ssize_t bytesize = sizeof(uint64_t) * page_count;
- off_t offset = sizeof(uint64_t) * page_start;
- if (pread_whole(pagemap_fd_, pagemap, bytesize, offset) != bytesize)
- xbt_die("Could not read pagemap");
-}
-
void Process::ignore_heap(IgnoredHeapRegion const& region)
{
if (ignored_heap_.empty()) {
running_ = false;
}
- void reset_soft_dirty();
- void read_pagemap(uint64_t* pagemap, size_t start_page, size_t page_count);
-
bool privatized(ObjectInformation const& info) const
{
return privatized_ && info.executable();
RemotePtr<void> maestro_stack_start_, maestro_stack_end_;
int memory_file = -1;
std::vector<IgnoredRegion> ignored_regions_;
- int clear_refs_fd_ = -1;
- int pagemap_fd_ = -1;
bool privatized_ = false;
std::vector<s_stack_region_t> stack_areas_;
std::vector<IgnoredHeapRegion> ignored_heap_;
* @param size Size of the data*
*/
RegionSnapshot region(
- RegionType type, void *start_addr, void* permanent_addr, size_t size,
- RegionSnapshot const* ref_region)
+ RegionType type, void *start_addr, void* permanent_addr, size_t size)
{
if (_sg_mc_sparse_checkpoint)
- return sparse_region(type, start_addr, permanent_addr, size, ref_region);
+ return sparse_region(type, start_addr, permanent_addr, size);
else
return dense_region(type, start_addr, permanent_addr, size);
}
RegionSnapshot sparse_region(RegionType region_type,
- void *start_addr, void* permanent_addr, size_t size,
- RegionSnapshot const* ref_region)
+ void *start_addr, void* permanent_addr, size_t size)
{
simgrid::mc::Process* process = &mc_model_checker->process();
assert(process != nullptr);
- bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty
- && ref_region != nullptr
- && ref_region->storage_type() == simgrid::mc::StorageType::Chunked;
-
xbt_assert((((uintptr_t)start_addr) & (xbt_pagesize-1)) == 0,
"Not at the beginning of a page");
xbt_assert((((uintptr_t)permanent_addr) & (xbt_pagesize-1)) == 0,
"Not at the beginning of a page");
size_t page_count = simgrid::mc::mmu::chunkCount(size);
- std::vector<std::uint64_t> pagemap;
- const size_t* ref_page_numbers = nullptr;
- if (use_soft_dirty) {
- pagemap.resize(page_count);
- process->read_pagemap(pagemap.data(),
- simgrid::mc::mmu::split((std::size_t) permanent_addr).first, page_count);
- ref_page_numbers = ref_region->page_data().pagenos();
- }
-
simgrid::mc::ChunkedData page_data(
- mc_model_checker->page_store(), *process, permanent_addr, page_count,
- ref_page_numbers,
- use_soft_dirty ? pagemap.data() : nullptr);
+ mc_model_checker->page_store(), *process, permanent_addr, page_count);
simgrid::mc::RegionSnapshot region(
region_type, start_addr, permanent_addr, size);
RegionSnapshot privatized_region(
RegionType region_type, void *start_addr, void* permanent_addr,
- std::size_t size, const RegionSnapshot* ref_region);
+ std::size_t size);
RegionSnapshot dense_region(
RegionType type, void *start_addr, void* data_addr, std::size_t size);
simgrid::mc::RegionSnapshot sparse_region(
- RegionType type, void *start_addr, void* data_addr, std::size_t size,
- RegionSnapshot const* ref_region);
+ RegionType type, void *start_addr, void* data_addr, std::size_t size);
simgrid::mc::RegionSnapshot region(
- RegionType type, void *start_addr, void* data_addr, std::size_t size,
- RegionSnapshot const* ref_region);
+ RegionType type, void *start_addr, void* data_addr, std::size_t size);
}
}
#if HAVE_SMPI
RegionSnapshot privatized_region(
RegionType region_type, void *start_addr, void* permanent_addr,
- std::size_t size, const RegionSnapshot* ref_region
+ std::size_t size
)
{
size_t process_count = MC_smpi_process_count();
std::vector<simgrid::mc::RegionSnapshot> data;
data.reserve(process_count);
- for (size_t i = 0; i < process_count; i++) {
- const simgrid::mc::RegionSnapshot* ref_privatized_region = nullptr;
- if (ref_region && ref_region->storage_type() == StorageType::Privatized)
- ref_privatized_region = &ref_region->privatized_data()[i];
+ for (size_t i = 0; i < process_count; i++)
data.push_back(simgrid::mc::region(region_type, start_addr,
- privatisation_regions[i].address, size, ref_privatized_region));
- }
+ privatisation_regions[i].address, size));
simgrid::mc::RegionSnapshot region = simgrid::mc::RegionSnapshot(
region_type, start_addr, permanent_addr, size);
else if (type == simgrid::mc::RegionType::Heap)
xbt_assert(!object_info, "Unexpected object info for heap region.");
- simgrid::mc::RegionSnapshot const* ref_region = nullptr;
- if (mc_model_checker->parent_snapshot_)
- ref_region = mc_model_checker->parent_snapshot_->snapshot_regions[index].get();
-
simgrid::mc::RegionSnapshot region;
#if HAVE_SMPI
const bool privatization_aware = object_info
&& mc_model_checker->process().privatized(*object_info);
if (privatization_aware && MC_smpi_process_count())
region = simgrid::mc::privatized_region(
- type, start_addr, permanent_addr, size, ref_region);
+ type, start_addr, permanent_addr, size);
else
#endif
- region = simgrid::mc::region(type, start_addr, permanent_addr, size, ref_region);
+ region = simgrid::mc::region(type, start_addr, permanent_addr, size);
region.object_info(object_info);
snapshot->snapshot_regions[index]
if (_sg_mc_snapshot_fds)
snapshot->current_fds = get_current_fds(mc_model_checker->process().pid());
- const bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty;
-
/* Save the std heap and the writable mapped pages of libsimgrid and binary */
get_memory_regions(mc_process, snapshot.get());
- if (use_soft_dirty)
- mc_process->reset_soft_dirty();
snapshot->to_ignore = mc_model_checker->process().ignored_heap();
snapshot->hash = 0;
snapshot_ignore_restore(snapshot.get());
- if (use_soft_dirty)
- mc_model_checker->parent_snapshot_ = snapshot;
return snapshot;
}
void restore_snapshot(std::shared_ptr<simgrid::mc::Snapshot> snapshot)
{
XBT_DEBUG("Restore snapshot %i", snapshot->num_state);
- const bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty;
restore_snapshot_regions(snapshot.get());
if (_sg_mc_snapshot_fds)
restore_snapshot_fds(snapshot.get());
- if (use_soft_dirty)
- mc_model_checker->process().reset_soft_dirty();
snapshot_ignore_restore(snapshot.get());
mc_model_checker->process().clear_cache();
- if (use_soft_dirty)
- mc_model_checker->parent_snapshot_ = snapshot;
}
}
int _sg_do_model_check_record = 0;
int _sg_mc_checkpoint = 0;
int _sg_mc_sparse_checkpoint = 0;
-int _sg_mc_soft_dirty = 0;
int _sg_mc_ksm = 0;
char *_sg_mc_property_file = nullptr;
int _sg_mc_hash = 0;
_sg_mc_sparse_checkpoint = xbt_cfg_get_boolean(name);
}
-void _mc_cfg_cb_soft_dirty(const char *name) {
- if (_sg_cfg_init_status && !_sg_do_model_check)
- xbt_die("You are specifying a soft dirty value after the initialization "
- "(through MSG_config?), but model-checking was not activated "
- "at config time (through --cfg=model-check:1). "
- "This won't work, sorry.");
-
- _sg_mc_soft_dirty = xbt_cfg_get_boolean(name);
-}
-
void _mc_cfg_cb_ksm(const char *name)
{
if (_sg_cfg_init_status && !_sg_do_model_check)
// Init memory and take snapshots:
init_memory(source, byte_size);
simgrid::mc::RegionSnapshot region0 = simgrid::mc::sparse_region(
- simgrid::mc::RegionType::Unknown, source, source, byte_size, nullptr);
+ simgrid::mc::RegionType::Unknown, source, source, byte_size);
for(int i=0; i<n; i+=2) {
init_memory((char*) source + i*xbt_pagesize, xbt_pagesize);
}
simgrid::mc::RegionSnapshot region = simgrid::mc::sparse_region(
- simgrid::mc::RegionType::Unknown, source, source, byte_size, nullptr);
+ simgrid::mc::RegionType::Unknown, source, source, byte_size);
void* destination = mmap(nullptr, byte_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
xbt_assert(source!=MAP_FAILED, "Could not allocate destination memory");
xbt_test_add("Read pointer for %i page(s)", n);
memcpy(source, &mc_model_checker, sizeof(void*));
simgrid::mc::RegionSnapshot region2 = simgrid::mc::sparse_region(
- simgrid::mc::RegionType::Unknown, source, source, byte_size, nullptr);
+ simgrid::mc::RegionType::Unknown, source, source, byte_size);
xbt_test_assert(MC_region_read_pointer(®ion2, source) == mc_model_checker,
"Mismtach in MC_region_read_pointer()");
}
"If value=1, one checkpoint is saved for each step => faster verification, but huge memory consumption; higher values are good compromises between speed and memory consumption.");
xbt_cfg_register_boolean("model-check/sparse_checkpoint", "no", _mc_cfg_cb_sparse_checkpoint, "Use sparse per-page snapshots.");
- xbt_cfg_register_boolean("model-check/soft-dirty", "no", _mc_cfg_cb_soft_dirty, "Use sparse per-page snapshots.");
xbt_cfg_register_boolean("model-check/ksm", "no", _mc_cfg_cb_ksm, "Kernel same-page merging");
xbt_cfg_register_string("model-check/property","", _mc_cfg_cb_property,