From: Gabriel Corona Date: Fri, 29 May 2015 08:05:36 +0000 (+0200) Subject: [mc] RegionSnapshot class X-Git-Tag: v3_12~701 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/02a7d032779c8f37702c9513f1c3fbb988088677 [mc] RegionSnapshot class --- diff --git a/src/mc/mc_checkpoint.cpp b/src/mc/mc_checkpoint.cpp index 32e0a9aa0a..26c6a2a185 100644 --- a/src/mc/mc_checkpoint.cpp +++ b/src/mc/mc_checkpoint.cpp @@ -73,52 +73,37 @@ static void local_variable_free_voidp(void *v) 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; } @@ -152,7 +137,7 @@ static void MC_region_restore(mc_mem_region_t 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; @@ -161,13 +146,9 @@ static void MC_region_restore(mc_mem_region_t region) 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; } } @@ -176,14 +157,13 @@ static mc_mem_region_t MC_region_new_privatized( ) { 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; @@ -196,9 +176,10 @@ static mc_mem_region_t MC_region_new_privatized( 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( MC_region_new(region_type, start_addr, - privatisation_regions[i].address, size); + privatisation_regions[i].address, size) + ); } return region; diff --git a/src/mc/mc_compare.cpp b/src/mc/mc_compare.cpp index 2a5a53d7b7..9887e55ac1 100644 --- a/src/mc/mc_compare.cpp +++ b/src/mc/mc_compare.cpp @@ -275,13 +275,14 @@ static int compare_global_variables(mc_object_info_t object_info, } 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; } diff --git a/src/mc/mc_page_snapshot.cpp b/src/mc/mc_page_snapshot.cpp index 7725f414ae..79e38e420f 100644 --- a/src/mc/mc_page_snapshot.cpp +++ b/src/mc/mc_page_snapshot.cpp @@ -16,9 +16,8 @@ using simgrid::mc::remote; -extern "C" { - -// ***** Region management: +namespace simgrid { +namespace mc { /** @brief Take a per-page snapshot of a region * @@ -26,27 +25,19 @@ extern "C" { * @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 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 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 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: @@ -54,26 +45,21 @@ size_t* mc_take_page_snapshot_region(mc_process_t process, - 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 @@ -84,12 +70,12 @@ void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count) * @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)); } } @@ -101,7 +87,7 @@ mc_mem_region_t mc_region_new_sparse(mc_region_type_t region_type, { 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; @@ -115,7 +101,7 @@ mc_mem_region_t mc_region_new_sparse(mc_region_type_t region_type, 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; @@ -125,10 +111,9 @@ void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg) { 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_); } } diff --git a/src/mc/mc_snapshot.cpp b/src/mc/mc_snapshot.cpp index 46c0a4692f..5a101b92ce 100644 --- a/src/mc/mc_snapshot.cpp +++ b/src/mc/mc_snapshot.cpp @@ -41,10 +41,10 @@ mc_mem_region_t mc_get_snapshot_region( 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 @@ -174,7 +174,7 @@ Snapshot::Snapshot() : 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); @@ -300,11 +300,11 @@ static void test_snapshot(bool sparse_checkpoint) { 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); } diff --git a/src/mc/mc_snapshot.h b/src/mc/mc_snapshot.h index 279ca5b849..412606f15e 100644 --- a/src/mc/mc_snapshot.h +++ b/src/mc/mc_snapshot.h @@ -40,6 +40,76 @@ typedef enum e_mc_region_storeage_type_t { MC_REGION_STORAGE_TYPE_PRIVATIZED = 3 } mc_region_storage_type_t; +namespace simgrid { +namespace mc { + +class PerPageCopy { + PageStore* store_; + std::vector 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 addr, std::size_t page_count); +}; + /** @brief Copy/snapshot of a given memory region * * Different types of region snapshot storage types exist: @@ -56,9 +126,8 @@ typedef enum e_mc_region_storeage_type_t { * * 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; @@ -80,26 +149,30 @@ struct s_mc_mem_region { * */ 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 flat_data_; + PerPageCopy page_numbers_; + std::vector> 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)) @@ -113,9 +186,8 @@ 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); } @@ -130,7 +202,7 @@ void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region, int pr 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: @@ -140,9 +212,9 @@ void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region, int pr { 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); } @@ -252,12 +324,9 @@ static const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot); 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); @@ -311,7 +380,7 @@ const void* MC_region_read(mc_mem_region_t region, void* target, const void* add 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: {