X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/d574355c7629f9f18b0667c69bfb0f1695b7b3b6..992bc1ec57d376cf14b124ea21b58b30f1e162f9:/src/mc/sosp/Snapshot.cpp diff --git a/src/mc/sosp/Snapshot.cpp b/src/mc/sosp/Snapshot.cpp index a3d6c79efe..bf91e7c82e 100644 --- a/src/mc/sosp/Snapshot.cpp +++ b/src/mc/sosp/Snapshot.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2019. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2014-2022. The SimGrid Team. All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ @@ -6,102 +6,26 @@ #include "src/mc/sosp/Snapshot.hpp" #include "src/mc/mc_config.hpp" #include "src/mc/mc_hash.hpp" -#include "src/mc/mc_smx.hpp" #include /* std::size_t */ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_snapshot, mc, "Taking and restoring snapshots"); - -/** @brief Read memory from a snapshot region broken across fragmented pages - * - * @param addr Process (non-snapshot) address of the data - * @param region Snapshot memory region where the data is located - * @param target Buffer to store the value - * @param size Size of the data to read in bytes - * @return Pointer where the data is located (target buffer of original location) - */ -const void* MC_region_read_fragmented(simgrid::mc::RegionSnapshot* region, void* target, const void* addr, size_t size) -{ - // Last byte of the memory area: - void* end = (char*)addr + size - 1; - - // TODO, we assume the chunks are aligned to natural chunk boundaries. - // We should remove this assumption. - - // Page of the last byte of the memory area: - size_t page_end = simgrid::mc::mmu::split((std::uintptr_t)end).first; - - void* dest = target; - - if (dest == nullptr) - xbt_die("Missing destination buffer for fragmented memory access"); - - // Read each page: - while (simgrid::mc::mmu::split((std::uintptr_t)addr).first != page_end) { - void* snapshot_addr = mc_translate_address_region((uintptr_t)addr, region); - void* next_page = (void*)simgrid::mc::mmu::join(simgrid::mc::mmu::split((std::uintptr_t)addr).first + 1, 0); - size_t readable = (char*)next_page - (char*)addr; - memcpy(dest, snapshot_addr, readable); - addr = (char*)addr + readable; - dest = (char*)dest + readable; - size -= readable; - } - - // Read the end: - void* snapshot_addr = mc_translate_address_region((uintptr_t)addr, region); - memcpy(dest, snapshot_addr, size); - - return target; -} - -/** Compare memory between snapshots (with known regions) - * - * @param addr1 Address in the first snapshot - * @param region1 Region of the address in the first snapshot - * @param addr2 Address in the second snapshot - * @param region2 Region of the address in the second snapshot - * @return same semantic as memcmp - */ -int MC_snapshot_region_memcmp(const void* addr1, simgrid::mc::RegionSnapshot* region1, const void* addr2, - simgrid::mc::RegionSnapshot* region2, size_t size) -{ - // Using alloca() for large allocations may trigger stack overflow: - // use malloc if the buffer is too big. - bool stack_alloc = size < 64; - void* buffer1a = stack_alloc ? alloca(size) : ::operator new(size); - void* buffer2a = stack_alloc ? alloca(size) : ::operator new(size); - const void* buffer1 = MC_region_read(region1, buffer1a, addr1, size); - const void* buffer2 = MC_region_read(region2, buffer2a, addr2, size); - int res; - if (buffer1 == buffer2) - res = 0; - else - res = memcmp(buffer1, buffer2, size); - if (not stack_alloc) { - ::operator delete(buffer1a); - ::operator delete(buffer2a); - } - return res; -} - -namespace simgrid { -namespace mc { +namespace simgrid::mc { /************************************* Take Snapshot ************************************/ /****************************************************************************************/ -void simgrid::mc::Snapshot::snapshot_regions(simgrid::mc::RemoteClient* process) +void Snapshot::snapshot_regions(RemoteProcess* process) { snapshot_regions_.clear(); for (auto const& object_info : process->object_infos) - add_region(simgrid::mc::RegionType::Data, object_info.get(), object_info->start_rw, - object_info->end_rw - object_info->start_rw); + add_region(RegionType::Data, object_info.get(), object_info->start_rw, object_info->end_rw - object_info->start_rw); - xbt_mheap_t heap = process->get_heap(); + const s_xbt_mheap_t* heap = process->get_heap(); void* start_heap = heap->base; void* end_heap = heap->breakval; - add_region(simgrid::mc::RegionType::Heap, nullptr, start_heap, (char*)end_heap - (char*)start_heap); + add_region(RegionType::Heap, nullptr, start_heap, (char*)end_heap - (char*)start_heap); heap_bytes_used_ = mmalloc_get_bytes_used_remote(heap->heaplimit, process->get_malloc_info()); } @@ -114,7 +38,7 @@ void simgrid::mc::Snapshot::snapshot_regions(simgrid::mc::RemoteClient* process) * @param ip Instruction pointer * @return true if the variable is valid * */ -static bool valid_variable(simgrid::mc::Variable* var, simgrid::mc::Frame* scope, const void* ip) +static bool valid_variable(const simgrid::mc::Variable* var, simgrid::mc::Frame* scope, const void* ip) { // The variable is not yet valid: if (scope->range.begin() + var->start_scope > (std::uint64_t)ip) @@ -123,17 +47,22 @@ static bool valid_variable(simgrid::mc::Variable* var, simgrid::mc::Frame* scope return true; } -static void fill_local_variables_values(mc_stack_frame_t stack_frame, simgrid::mc::Frame* scope, +static void fill_local_variables_values(mc_stack_frame_t stack_frame, Frame* scope, std::vector& result) { if (not scope || not scope->range.contain(stack_frame->ip)) return; - for (simgrid::mc::Variable& current_variable : scope->variables) { - + for (const Variable& current_variable : scope->variables) { if (not valid_variable(¤t_variable, scope, (void*)stack_frame->ip)) continue; + if (not current_variable.type) { + XBT_VERB("Ignore local variable without type: '%s' [%s]", current_variable.name.c_str(), + stack_frame->frame->name.c_str()); + continue; + } + s_local_variable_t new_var; new_var.subprogram = stack_frame->frame; new_var.ip = stack_frame->ip; @@ -144,14 +73,12 @@ static void fill_local_variables_values(mc_stack_frame_t stack_frame, simgrid::m if (current_variable.address != nullptr) new_var.address = current_variable.address; else if (not current_variable.location_list.empty()) { - simgrid::dwarf::Location location = simgrid::dwarf::resolve( - current_variable.location_list, current_variable.object_info, &(stack_frame->unw_cursor), - (void*)stack_frame->frame_base, &mc_model_checker->process()); + dwarf::Location location = simgrid::dwarf::resolve(current_variable.location_list, current_variable.object_info, + &(stack_frame->unw_cursor), (void*)stack_frame->frame_base, + &mc_model_checker->get_remote_process()); - if (not location.in_memory()) - xbt_die("Cannot handle non-address variable"); + xbt_assert(location.in_memory(), "Cannot handle non-address variable"); new_var.address = location.address(); - } else xbt_die("No address"); @@ -159,7 +86,7 @@ static void fill_local_variables_values(mc_stack_frame_t stack_frame, simgrid::m } // Recursive processing of nested scopes: - for (simgrid::mc::Frame& nested_scope : scope->scopes) + for (Frame& nested_scope : scope->scopes) fill_local_variables_values(stack_frame, &nested_scope, result); } @@ -171,17 +98,16 @@ static std::vector get_local_variables_values(std::vector unwind_stack_frames(simgrid::mc::UnwindContext* stack_context) +static std::vector unwind_stack_frames(UnwindContext* stack_context) { - simgrid::mc::RemoteClient* process = &mc_model_checker->process(); + const RemoteProcess* process = &mc_model_checker->get_remote_process(); std::vector result; unw_cursor_t c = stack_context->cursor(); // TODO, check condition check (unw_init_local==0 means end of frame) - while (1) { - + while (true) { s_mc_stack_frame_t stack_frame; stack_frame.unw_cursor = c; @@ -197,7 +123,7 @@ static std::vector unwind_stack_frames(simgrid::mc::UnwindCo // TODO, use real addresses in frame_t instead of fixing it here - simgrid::mc::Frame* frame = process->find_function(remote(ip)); + Frame* frame = process->find_function(remote(ip)); stack_frame.frame = frame; if (frame) { @@ -215,10 +141,8 @@ static std::vector unwind_stack_frames(simgrid::mc::UnwindCo break; int ret = unw_step(&c); - if (ret == 0) - xbt_die("Unexpected end of stack."); - else if (ret < 0) - xbt_die("Error while unwinding stack"); + xbt_assert(ret >= 0, "Error while unwinding stack"); + xbt_assert(ret != 0, "Unexpected end of stack."); } xbt_assert(not result.empty(), "unw_init_local failed"); @@ -226,7 +150,7 @@ static std::vector unwind_stack_frames(simgrid::mc::UnwindCo return result; } -void simgrid::mc::Snapshot::snapshot_stacks(simgrid::mc::RemoteClient* process) +void Snapshot::snapshot_stacks(RemoteProcess* process) { for (auto const& stack : process->stack_areas()) { s_mc_snapshot_stack_t st; @@ -249,37 +173,35 @@ void simgrid::mc::Snapshot::snapshot_stacks(simgrid::mc::RemoteClient* process) } } -static void snapshot_handle_ignore(simgrid::mc::Snapshot* snapshot) +static void snapshot_handle_ignore(Snapshot* snapshot) { - xbt_assert(snapshot->process()); + xbt_assert(snapshot->get_remote_process()); // Copy the memory: - for (auto const& region : snapshot->process()->ignored_regions()) { + for (auto const& region : snapshot->get_remote_process()->ignored_regions()) { s_mc_snapshot_ignored_data_t ignored_data; ignored_data.start = (void*)region.addr; ignored_data.data.resize(region.size); // TODO, we should do this once per privatization segment: - snapshot->process()->read_bytes(ignored_data.data.data(), region.size, remote(region.addr)); + snapshot->get_remote_process()->read_bytes(ignored_data.data.data(), region.size, remote(region.addr)); snapshot->ignored_data_.push_back(std::move(ignored_data)); } // Zero the memory: - for (auto const& region : snapshot->process()->ignored_regions()) - snapshot->process()->clear_bytes(remote(region.addr), region.size); + for (auto const& region : snapshot->get_remote_process()->ignored_regions()) + snapshot->get_remote_process()->clear_bytes(remote(region.addr), region.size); } -static void snapshot_ignore_restore(simgrid::mc::Snapshot* snapshot) + +static void snapshot_ignore_restore(const simgrid::mc::Snapshot* snapshot) { for (auto const& ignored_data : snapshot->ignored_data_) - snapshot->process()->write_bytes(ignored_data.data.data(), ignored_data.data.size(), remote(ignored_data.start)); + snapshot->get_remote_process()->write_bytes(ignored_data.data.data(), ignored_data.data.size(), + remote(ignored_data.start)); } -Snapshot::Snapshot(int num_state, RemoteClient* process) - : AddressSpace(process), num_state_(num_state), heap_bytes_used_(0), enabled_processes_(), hash_(0) +Snapshot::Snapshot(long num_state, RemoteProcess* process) : AddressSpace(process), num_state_(num_state) { - XBT_DEBUG("Taking snapshot %i", num_state); - - for (auto const& p : process->actors()) - enabled_processes_.insert(p.copy.get_buffer()->get_pid()); + XBT_DEBUG("Taking snapshot %ld", num_state); snapshot_handle_ignore(this); @@ -290,8 +212,7 @@ Snapshot::Snapshot(int num_state, RemoteClient* process) if (_sg_mc_max_visited_states > 0 || not _sg_mc_property_file.get().empty()) { snapshot_stacks(process); - if (_sg_mc_hash) - hash_ = simgrid::mc::hash(*this); + hash_ = simgrid::mc::hash(*this); } snapshot_ignore_restore(this); @@ -299,21 +220,21 @@ Snapshot::Snapshot(int num_state, RemoteClient* process) void Snapshot::add_region(RegionType type, ObjectInformation* object_info, void* start_addr, std::size_t size) { - if (type == simgrid::mc::RegionType::Data) + if (type == RegionType::Data) xbt_assert(object_info, "Missing object info for object."); - else if (type == simgrid::mc::RegionType::Heap) + else if (type == RegionType::Heap) xbt_assert(not object_info, "Unexpected object info for heap region."); - simgrid::mc::RegionSnapshot* region = new RegionSnapshot(type, start_addr, size); + auto* region = new Region(type, start_addr, size); region->object_info(object_info); - snapshot_regions_.push_back(std::unique_ptr(std::move(region))); + snapshot_regions_.push_back(std::unique_ptr(region)); } -const void* Snapshot::read_bytes(void* buffer, std::size_t size, RemotePtr address, ReadOptions options) const +void* Snapshot::read_bytes(void* buffer, std::size_t size, RemotePtr address, ReadOptions options) const { - RegionSnapshot* region = this->get_region((void*)address.address()); + const Region* region = this->get_region((void*)address.address()); if (region) { - const void* res = MC_region_read(region, buffer, (void*)address.address(), size); + void* res = region->read(buffer, (void*)address.address(), size); if (buffer == res || options & ReadOptions::lazy()) return res; else { @@ -321,17 +242,17 @@ const void* Snapshot::read_bytes(void* buffer, std::size_t size, RemotePtr return buffer; } } else - return this->process()->read_bytes(buffer, size, address, options); + return this->get_remote_process()->read_bytes(buffer, size, address, options); } -/** @brief Find the snapshoted region from a pointer +/** @brief Find the snapshotted region from a pointer * * @param addr Pointer * */ -RegionSnapshot* Snapshot::get_region(const void* addr) const +Region* Snapshot::get_region(const void* addr) const { size_t n = snapshot_regions_.size(); for (size_t i = 0; i != n; ++i) { - RegionSnapshot* region = snapshot_regions_[i].get(); + Region* region = snapshot_regions_[i].get(); if (not(region && region->contain(simgrid::mc::remote(addr)))) continue; @@ -341,8 +262,8 @@ RegionSnapshot* Snapshot::get_region(const void* addr) const return nullptr; } -/** @brief Find the snapshoted region from a pointer, with a hinted_region */ -RegionSnapshot* Snapshot::get_region(const void* addr, RegionSnapshot* hinted_region) const +/** @brief Find the snapshotted region from a pointer, with a hinted_region */ +Region* Snapshot::get_region(const void* addr, Region* hinted_region) const { if (hinted_region->contain(simgrid::mc::remote(addr))) return hinted_region; @@ -350,13 +271,13 @@ RegionSnapshot* Snapshot::get_region(const void* addr, RegionSnapshot* hinted_re return get_region(addr); } -void Snapshot::restore(RemoteClient* process) +void Snapshot::restore(RemoteProcess* process) const { - XBT_DEBUG("Restore snapshot %i", num_state_); + XBT_DEBUG("Restore snapshot %ld", num_state_); // Restore regions - for (std::unique_ptr const& region : snapshot_regions_) { - if (region) // privatized variables are not snapshoted + for (std::unique_ptr const& region : snapshot_regions_) { + if (region) // privatized variables are not snapshotted region.get()->restore(); } @@ -364,5 +285,4 @@ void Snapshot::restore(RemoteClient* process) process->clear_cache(); } -} // namespace mc -} // namespace simgrid +} // namespace simgrid::mc