local_variable_free((local_variable_t) * (void **) v);
}
-void MC_region_destroy(mc_mem_region_t region)
-{
- if (!region)
- return;
- switch(region->storage_type) {
- case MC_REGION_STORAGE_TYPE_NONE:
- break;
- case MC_REGION_STORAGE_TYPE_FLAT:
- xbt_free(region->flat.data);
- break;
- case MC_REGION_STORAGE_TYPE_CHUNKED:
- mc_free_page_snapshot_region(region->chunked.page_numbers, mc_page_count(region->size));
- xbt_free(region->chunked.page_numbers);
- break;
- case MC_REGION_STORAGE_TYPE_PRIVATIZED:
- {
- size_t regions_count = region->privatized.regions_count;
- for (size_t i=0; i!=regions_count; ++i) {
- MC_region_destroy(region->privatized.regions[i]);
- }
- free(region->privatized.regions);
- break;
- }
- }
- xbt_free(region);
+}
+
+namespace simgrid {
+namespace mc {
+
+RegionSnapshot::~RegionSnapshot() {}
+
+}
}
/******************************* Snapshot regions ********************************/
/*********************************************************************************/
+extern "C" {
+
static mc_mem_region_t mc_region_new_dense(
mc_region_type_t region_type,
void *start_addr, void* permanent_addr, size_t size)
{
- mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ mc_mem_region_t region = new simgrid::mc::RegionSnapshot();
region->region_type = region_type;
region->storage_type = MC_REGION_STORAGE_TYPE_FLAT;
region->start_addr = start_addr;
region->permanent_addr = permanent_addr;
region->size = size;
- region->flat.data = xbt_malloc(size);
- mc_model_checker->process().read_bytes(region->flat.data, size,
+ region->flat_data_.resize(size);
+ mc_model_checker->process().read_bytes(region->flat_data_.data(), size,
remote(permanent_addr),
simgrid::mc::ProcessIndexDisabled);
XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu",
- region_type, region->flat.data, permanent_addr, size);
+ region_type, region->flat_data_.data(), permanent_addr, size);
return region;
}
break;
case MC_REGION_STORAGE_TYPE_FLAT:
- mc_model_checker->process().write_bytes(region->flat.data, region->size,
+ mc_model_checker->process().write_bytes(region->flat_data_.data(), region->size,
remote(region->permanent_addr));
break;
break;
case MC_REGION_STORAGE_TYPE_PRIVATIZED:
- {
- size_t process_count = region->privatized.regions_count;
- for (size_t i = 0; i < process_count; i++) {
- MC_region_restore(region->privatized.regions[i]);
- }
- break;
- }
+ for (auto const& p : region->privatized_regions_)
+ MC_region_restore(p.get());
+ break;
}
}
)
{
size_t process_count = MC_smpi_process_count();
- mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ mc_mem_region_t region = new simgrid::mc::RegionSnapshot();
region->region_type = region_type;
region->storage_type = MC_REGION_STORAGE_TYPE_PRIVATIZED;
region->start_addr = start_addr;
region->permanent_addr = permanent_addr;
region->size = size;
- region->privatized.regions_count = process_count;
- region->privatized.regions = xbt_new(mc_mem_region_t, process_count);
+ region->privatized_regions_.resize(process_count);
// Read smpi_privatisation_regions from MCed:
smpi_privatisation_region_t remote_smpi_privatisation_regions;
remote(remote_smpi_privatisation_regions));
for (size_t i = 0; i < process_count; i++) {
- region->privatized.regions[i] =
+ region->privatized_regions_[i] = std::unique_ptr<simgrid::mc::RegionSnapshot>(
MC_region_new(region_type, start_addr,
- privatisation_regions[i].address, size);
+ privatisation_regions[i].address, size)
+ );
}
return region;
}
size_t process_count = MC_smpi_process_count();
- xbt_assert(process_count == r1->privatized.regions_count
- && process_count == r2->privatized.regions_count);
+ xbt_assert(process_count == r1->privatized_regions_.size()
+ && process_count == r2->privatized_regions_.size());
// Compare the global variables separately for each simulates process:
for (size_t process_index = 0; process_index < process_count; process_index++) {
int is_diff = compare_global_variables(object_info, process_index,
- r1->privatized.regions[process_index], r2->privatized.regions[process_index],
+ r1->privatized_regions_[process_index].get(),
+ r2->privatized_regions_[process_index].get(),
snapshot1, snapshot2);
if (is_diff) return 1;
}
using simgrid::mc::remote;
-extern "C" {
-
-// ***** Region management:
+namespace simgrid {
+namespace mc {
/** @brief Take a per-page snapshot of a region
*
* @param pag_count Number of pages of the region
* @return Snapshot page numbers of this new snapshot
*/
-size_t* mc_take_page_snapshot_region(mc_process_t process,
- void* data, size_t page_count)
+PerPageCopy::PerPageCopy(PageStore& store, AddressSpace& as,
+ remote_ptr<void> addr, std::size_t page_count)
{
- size_t* pagenos = (size_t*) malloc(page_count * sizeof(size_t));
-
- const bool is_self = process->is_self();
+ store_ = &store;
+ this->pagenos_.resize(page_count);
+ std::vector<char> buffer(xbt_pagesize);
- void* temp = NULL;
- if (!is_self)
- temp = malloc(xbt_pagesize);
+ for (size_t i = 0; i != page_count; ++i) {
- for (size_t i=0; i!=page_count; ++i) {
+ remote_ptr<void> page = remote(addr.address() + (i << xbt_pagebits));
+ xbt_assert(mc_page_offset((void*)page.address())==0,
+ "Not at the beginning of a page");
- // Otherwise, we need to store the page the hard way
- // (by reading its content):
- void* page = (char*) data + (i << xbt_pagebits);
- xbt_assert(mc_page_offset(page)==0, "Not at the beginning of a page");
- void* page_data;
- if (is_self) {
- page_data = page;
- } else {
/* Adding another copy (and a syscall) will probably slow things a lot.
TODO, optimize this somehow (at least by grouping the syscalls)
if needed. Either:
- let the application snapshot itself;
- move the segments in shared memory (this will break `fork` however).
*/
- page_data = temp;
- process->read_bytes(
- temp, xbt_pagesize, remote(page),
+
+ as.read_bytes(
+ buffer.data(), xbt_pagesize, page,
simgrid::mc::ProcessIndexDisabled);
- }
- pagenos[i] = mc_model_checker->page_store().store_page(page_data);
- }
+ pagenos_[i] = store_->store_page(buffer.data());
- free(temp);
- return pagenos;
+ }
}
-void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count)
-{
- for (size_t i=0; i!=page_count; ++i) {
- mc_model_checker->page_store().unref_page(pagenos[i]);
- }
+}
}
+extern "C" {
+
/** @brief Restore a snapshot of a region
*
* If possible, the restoration will be incremental
* @param pagenos
*/
void mc_restore_page_snapshot_region(mc_process_t process,
- void* start_addr, size_t page_count, size_t* pagenos)
+ void* start_addr, simgrid::mc::PerPageCopy const& pages_copy)
{
- for (size_t i=0; i!=page_count; ++i) {
+ for (size_t i = 0; i != pages_copy.page_count(); ++i) {
// Otherwise, copy the page:
void* target_page = mc_page_from_number(start_addr, i);
- const void* source_page = mc_model_checker->page_store().get_page(pagenos[i]);
+ const void* source_page = pages_copy.page(i);
process->write_bytes(source_page, xbt_pagesize, remote(target_page));
}
}
{
mc_process_t process = &mc_model_checker->process();
- mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+ mc_mem_region_t region = new simgrid::mc::RegionSnapshot();
region->region_type = region_type;
region->storage_type = MC_REGION_STORAGE_TYPE_CHUNKED;
region->start_addr = start_addr;
size_t page_count = mc_page_count(size);
// Take incremental snapshot:
- region->chunked.page_numbers = mc_take_page_snapshot_region(process,
+ region->page_numbers_ = simgrid::mc::PerPageCopy(mc_model_checker->page_store(), *process,
permanent_addr, page_count);
return region;
{
xbt_assert((((uintptr_t)reg->permanent_addr) & (xbt_pagesize-1)) == 0,
"Not at the beginning of a page");
- size_t page_count = mc_page_count(reg->size);
-
+ xbt_assert(mc_page_count(reg->size) == reg->page_numbers_.page_count());
mc_restore_page_snapshot_region(process,
- reg->permanent_addr, page_count, reg->chunked.page_numbers);
+ reg->permanent_addr, reg->page_numbers_);
}
}
if (process_index < 0) {
xbt_die("Missing process index");
}
- if (process_index >= (int) region->privatized.regions_count) {
+ if (process_index >= (int) region->privatized_regions_.size()) {
xbt_die("Invalid process index");
}
- mc_mem_region_t priv_region = region->privatized.regions[process_index];
+ mc_mem_region_t priv_region = region->privatized_regions_[process_index].get();
xbt_assert(mc_region_contain(priv_region, addr));
return priv_region;
#else
Snapshot::~Snapshot()
{
for (size_t i = 0; i < this->snapshot_regions_count; i++) {
- MC_region_destroy(this->snapshot_regions[i]);
+ delete this->snapshot_regions[i];
}
xbt_free(this->snapshot_regions);
xbt_free(this->stack_sizes);
MC_REGION_TYPE_UNKNOWN, source, source, byte_size);
xbt_test_assert(MC_region_read_pointer(region2, source) == mc_model_checker,
"Mismtach in MC_region_read_pointer()");
- MC_region_destroy(region2);
+ delete region2;
}
- MC_region_destroy(region);
- MC_region_destroy(region0);
+ delete region;
+ delete region0;
munmap(destination, byte_size);
munmap(source, byte_size);
}
MC_REGION_STORAGE_TYPE_PRIVATIZED = 3
} mc_region_storage_type_t;
+namespace simgrid {
+namespace mc {
+
+class PerPageCopy {
+ PageStore* store_;
+ std::vector<std::size_t> pagenos_;
+public:
+ PerPageCopy() : store_(nullptr) {}
+ PerPageCopy(PerPageCopy const& that)
+ {
+ store_ = that.store_;
+ pagenos_ = that.pagenos_;
+ for (std::size_t pageno : pagenos_)
+ store_->ref_page(pageno);
+ }
+ void clear()
+ {
+ for (std::size_t pageno : pagenos_)
+ store_->unref_page(pageno);
+ pagenos_.clear();
+ }
+ ~PerPageCopy() {
+ clear();
+ }
+
+ PerPageCopy(PerPageCopy&& that)
+ {
+ store_ = that.store_;
+ that.store_ = nullptr;
+ pagenos_ = std::move(that.pagenos_);
+ that.pagenos_.clear();
+ }
+ PerPageCopy& operator=(PerPageCopy const& that)
+ {
+ this->clear();
+ store_ = that.store_;
+ pagenos_ = that.pagenos_;
+ for (std::size_t pageno : pagenos_)
+ store_->ref_page(pageno);
+ return *this;
+ }
+ PerPageCopy& operator=(PerPageCopy && that)
+ {
+ this->clear();
+ store_ = that.store_;
+ that.store_ = nullptr;
+ pagenos_ = std::move(that.pagenos_);
+ that.pagenos_.clear();
+ return *this;
+ }
+
+ std::size_t page_count() const
+ {
+ return pagenos_.size();
+ }
+
+ std::size_t pageno(std::size_t i) const
+ {
+ return pagenos_[i];
+ }
+
+ const void* page(std::size_t i) const
+ {
+ return store_->get_page(pagenos_[i]);
+ }
+
+ PerPageCopy(PageStore& store, AddressSpace& as,
+ remote_ptr<void> addr, std::size_t page_count);
+};
+
/** @brief Copy/snapshot of a given memory region
*
* Different types of region snapshot storage types exist:
* * an anonymous enum is used to distinguish the relevant types for
* each type.
*/
-typedef struct s_mc_mem_region s_mc_mem_region_t, *mc_mem_region_t;
-
-struct s_mc_mem_region {
+class RegionSnapshot {
+public:
mc_region_type_t region_type;
mc_region_storage_type_t storage_type;
mc_object_info_t object_info;
* */
void *permanent_addr;
- union {
- struct {
- /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
- void *data;
- } flat;
- struct {
- /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
- size_t* page_numbers;
- } chunked;
- struct {
- size_t regions_count;
- mc_mem_region_t* regions;
- } privatized;
- };
-
+ std::vector<char> flat_data_;
+ PerPageCopy page_numbers_;
+ std::vector<std::unique_ptr<RegionSnapshot>> privatized_regions_;
+public:
+ RegionSnapshot() :
+ region_type(MC_REGION_TYPE_UNKNOWN),
+ storage_type(MC_REGION_STORAGE_TYPE_NONE),
+ object_info(nullptr),
+ start_addr(nullptr),
+ size(0),
+ permanent_addr(nullptr)
+ {}
+ ~RegionSnapshot();
+ RegionSnapshot(RegionSnapshot const&) = delete;
+ RegionSnapshot& operator=(RegionSnapshot const&) = delete;
};
+}
+}
+
+typedef class simgrid::mc::RegionSnapshot s_mc_mem_region_t, *mc_mem_region_t;
+
MC_SHOULD_BE_INTERNAL mc_mem_region_t mc_region_new_sparse(
mc_region_type_t type, void *start_addr, void* data_addr, size_t size);
-MC_SHOULD_BE_INTERNAL void MC_region_destroy(mc_mem_region_t reg);
XBT_INTERNAL void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg);
static inline __attribute__ ((always_inline))
void* mc_translate_address_region_chunked(uintptr_t addr, mc_mem_region_t region)
{
size_t pageno = mc_page_number(region->start_addr, (void*) addr);
- size_t snapshot_pageno = region->chunked.page_numbers[pageno];
const void* snapshot_page =
- mc_model_checker->page_store().get_page(snapshot_pageno);
+ region->page_numbers_.page(pageno);
return (char*) snapshot_page + mc_page_offset((void*) addr);
}
case MC_REGION_STORAGE_TYPE_FLAT:
{
uintptr_t offset = addr - (uintptr_t) region->start_addr;
- return (void *) ((uintptr_t) region->flat.data + offset);
+ return (void *) ((uintptr_t) region->flat_data_.data() + offset);
}
case MC_REGION_STORAGE_TYPE_CHUNKED:
{
xbt_assert(process_index >=0,
"Missing process index for privatized region");
- xbt_assert((size_t) process_index < region->privatized.regions_count,
+ xbt_assert((size_t) process_index < region->privatized_regions_.size(),
"Out of range process index");
- mc_mem_region_t subregion = region->privatized.regions[process_index];
+ mc_mem_region_t subregion = region->privatized_regions_[process_index].get();
xbt_assert(subregion, "Missing memory region for process %i", process_index);
return mc_translate_address_region(addr, subregion, process_index);
}
XBT_INTERNAL mc_snapshot_t MC_take_snapshot(int num_state);
XBT_INTERNAL void MC_restore_snapshot(mc_snapshot_t);
-XBT_INTERNAL size_t* mc_take_page_snapshot_region(mc_process_t process,
- void* data, size_t page_count);
-XBT_INTERNAL void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count);
XBT_INTERNAL void mc_restore_page_snapshot_region(
mc_process_t process,
- void* start_addr, size_t page_count, size_t* pagenos);
+ void* start_addr, simgrid::mc::PerPageCopy const& pagenos);
MC_SHOULD_BE_INTERNAL const void* MC_region_read_fragmented(
mc_mem_region_t region, void* target, const void* addr, size_t size);
xbt_die("Storage type not supported");
case MC_REGION_STORAGE_TYPE_FLAT:
- return (char*) region->flat.data + offset;
+ return (char*) region->flat_data_.data() + offset;
case MC_REGION_STORAGE_TYPE_CHUNKED:
{