X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/e709643ef0c5b61c6c878016c418bffa2b1b20cd..8bc5f575cd87562a15e861a47995b58b24bbc811:/src/mc/sosp/Snapshot.cpp diff --git a/src/mc/sosp/Snapshot.cpp b/src/mc/sosp/Snapshot.cpp index ccc1ac9728..fee842d32c 100644 --- a/src/mc/sosp/Snapshot.cpp +++ b/src/mc/sosp/Snapshot.cpp @@ -1,34 +1,32 @@ -/* Copyright (c) 2014-2020. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2014-2023. 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. */ #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"); -namespace simgrid { -namespace mc { +namespace simgrid::mc { /************************************* Take Snapshot ************************************/ /****************************************************************************************/ -void Snapshot::snapshot_regions(RemoteSimulation* process) +void Snapshot::snapshot_regions(RemoteProcessMemory& memory) { snapshot_regions_.clear(); - for (auto const& object_info : process->object_infos) - add_region(RegionType::Data, object_info.get(), object_info->start_rw, object_info->end_rw - object_info->start_rw); + for (auto const& object_info : memory.object_infos) + add_region(RegionType::Data, memory, object_info.get(), object_info->start_rw, + object_info->end_rw - object_info->start_rw); - const s_xbt_mheap_t* heap = process->get_heap(); + const s_xbt_mheap_t* heap = memory.get_heap(); void* start_heap = heap->base; void* end_heap = heap->breakval; - 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()); + add_region(RegionType::Heap, memory, nullptr, start_heap, (char*)end_heap - (char*)start_heap); + heap_bytes_used_ = mmalloc_get_bytes_used_remote(heap->heaplimit, memory.get_malloc_info()); } /** @brief Checks whether the variable is in scope for a given IP. @@ -50,7 +48,7 @@ static bool valid_variable(const simgrid::mc::Variable* var, simgrid::mc::Frame* } static void fill_local_variables_values(mc_stack_frame_t stack_frame, Frame* scope, - std::vector& result) + std::vector& result, AddressSpace* memory) { if (not scope || not scope->range.contain(stack_frame->ip)) return; @@ -59,6 +57,12 @@ static void fill_local_variables_values(mc_stack_frame_t stack_frame, Frame* sco 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; @@ -69,12 +73,11 @@ static void fill_local_variables_values(mc_stack_frame_t stack_frame, Frame* sco if (current_variable.address != nullptr) new_var.address = current_variable.address; else if (not current_variable.location_list.empty()) { - 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_simulation()); + dwarf::Location location = + simgrid::dwarf::resolve(current_variable.location_list, current_variable.object_info, + &(stack_frame->unw_cursor), (void*)stack_frame->frame_base, memory); - 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"); @@ -84,20 +87,21 @@ static void fill_local_variables_values(mc_stack_frame_t stack_frame, Frame* sco // Recursive processing of nested scopes: for (Frame& nested_scope : scope->scopes) - fill_local_variables_values(stack_frame, &nested_scope, result); + fill_local_variables_values(stack_frame, &nested_scope, result, memory); } -static std::vector get_local_variables_values(std::vector& stack_frames) +static std::vector get_local_variables_values(std::vector& stack_frames, + AddressSpace* memory) { std::vector variables; for (s_mc_stack_frame_t& stack_frame : stack_frames) - fill_local_variables_values(&stack_frame, stack_frame.frame, variables); + fill_local_variables_values(&stack_frame, stack_frame.frame, variables, memory); return variables; } -static std::vector unwind_stack_frames(UnwindContext* stack_context) +static std::vector unwind_stack_frames(UnwindContext* stack_context, + const RemoteProcessMemory* process_memory) { - const RemoteSimulation* process = &mc_model_checker->get_remote_simulation(); std::vector result; unw_cursor_t c = stack_context->cursor(); @@ -120,7 +124,7 @@ static std::vector unwind_stack_frames(UnwindContext* stack_ // TODO, use real addresses in frame_t instead of fixing it here - Frame* frame = process->find_function(remote(ip)); + Frame* frame = process_memory->find_function(remote(ip)); stack_frame.frame = frame; if (frame) { @@ -128,7 +132,7 @@ static std::vector unwind_stack_frames(UnwindContext* stack_ stack_frame.frame_base = (unw_word_t)frame->frame_base(c); } else { stack_frame.frame_base = 0; - stack_frame.frame_name = std::string(); + stack_frame.frame_name = ""; } result.push_back(std::move(stack_frame)); @@ -138,10 +142,8 @@ static std::vector unwind_stack_frames(UnwindContext* stack_ 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"); @@ -149,19 +151,19 @@ static std::vector unwind_stack_frames(UnwindContext* stack_ return result; } -void Snapshot::snapshot_stacks(RemoteSimulation* process) +void Snapshot::snapshot_stacks(RemoteProcessMemory& process_memory) { - for (auto const& stack : process->stack_areas()) { + for (auto const& stack : process_memory.stack_areas()) { s_mc_snapshot_stack_t st; - // Read the context from remote process: + // Read the context from remote process memory: unw_context_t context; - process->read_bytes(&context, sizeof(context), remote(stack.context)); + process_memory.read_bytes(&context, sizeof(context), remote(stack.context)); - st.context.initialize(process, &context); + st.context.initialize(process_memory, &context); - st.stack_frames = unwind_stack_frames(&st.context); - st.local_variables = get_local_variables_values(st.stack_frames); + st.stack_frames = unwind_stack_frames(&st.context, &process_memory); + st.local_variables = get_local_variables_values(st.stack_frames, &process_memory); unw_word_t sp = st.stack_frames[0].sp; @@ -172,64 +174,62 @@ void Snapshot::snapshot_stacks(RemoteSimulation* process) } } -static void snapshot_handle_ignore(Snapshot* snapshot) +void Snapshot::handle_ignore() { - xbt_assert(snapshot->get_remote_simulation()); + xbt_assert(get_remote_process_memory()); // Copy the memory: - for (auto const& region : snapshot->get_remote_simulation()->ignored_regions()) { + for (auto const& region : get_remote_process_memory()->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->get_remote_simulation()->read_bytes(ignored_data.data.data(), region.size, remote(region.addr)); - snapshot->ignored_data_.push_back(std::move(ignored_data)); + get_remote_process_memory()->read_bytes(ignored_data.data.data(), region.size, remote(region.addr)); + ignored_data_.push_back(std::move(ignored_data)); } // Zero the memory: - for (auto const& region : snapshot->get_remote_simulation()->ignored_regions()) - snapshot->get_remote_simulation()->clear_bytes(remote(region.addr), region.size); + for (auto const& region : get_remote_process_memory()->ignored_regions()) + get_remote_process_memory()->clear_bytes(remote(region.addr), region.size); } -static void snapshot_ignore_restore(const simgrid::mc::Snapshot* snapshot) +void Snapshot::ignore_restore() const { - for (auto const& ignored_data : snapshot->ignored_data_) - snapshot->get_remote_simulation()->write_bytes(ignored_data.data.data(), ignored_data.data.size(), - remote(ignored_data.start)); + for (auto const& ignored_data : ignored_data_) + get_remote_process_memory()->write_bytes(ignored_data.data.data(), ignored_data.data.size(), + remote(ignored_data.start)); } -Snapshot::Snapshot(int num_state, RemoteSimulation* process) : AddressSpace(process), num_state_(num_state) +Snapshot::Snapshot(long num_state, PageStore& store, RemoteProcessMemory& memory) + : AddressSpace(memory), page_store_(store), 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); + handle_ignore(); /* Save the std heap and the writable mapped pages of libsimgrid and binary */ - snapshot_regions(process); + snapshot_regions(memory); - to_ignore_ = process->ignored_heap(); + to_ignore_ = memory.ignored_heap(); if (_sg_mc_max_visited_states > 0 || not _sg_mc_property_file.get().empty()) { - snapshot_stacks(process); - hash_ = simgrid::mc::hash(*this); + snapshot_stacks(memory); + hash_ = this->do_hash(); } - snapshot_ignore_restore(this); + ignore_restore(); } -void Snapshot::add_region(RegionType type, ObjectInformation* object_info, void* start_addr, std::size_t size) +void Snapshot::add_region(RegionType type, RemoteProcessMemory& memory, ObjectInformation* object_info, + void* start_addr, std::size_t size) { if (type == RegionType::Data) xbt_assert(object_info, "Missing object info for object."); else if (type == RegionType::Heap) xbt_assert(not object_info, "Unexpected object info for heap region."); - Region* region = new Region(type, start_addr, size); + auto* region = new Region(page_store_, memory, 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)); } void* Snapshot::read_bytes(void* buffer, std::size_t size, RemotePtr address, ReadOptions options) const @@ -244,7 +244,7 @@ void* Snapshot::read_bytes(void* buffer, std::size_t size, RemotePtr addre return buffer; } } else - return this->get_remote_simulation()->read_bytes(buffer, size, address, options); + return this->get_remote_process_memory()->read_bytes(buffer, size, address, options); } /** @brief Find the snapshotted region from a pointer * @@ -273,19 +273,39 @@ Region* Snapshot::get_region(const void* addr, Region* hinted_region) const return get_region(addr); } -void Snapshot::restore(RemoteSimulation* process) const +void Snapshot::restore(RemoteProcessMemory& memory) 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 snapshotted - region.get()->restore(); + region->restore(memory); } - snapshot_ignore_restore(this); - process->clear_cache(); + ignore_restore(); + memory.clear_cache(); +} + +/* ----------- Hashing logic -------------- */ +class djb_hash { + hash_type state_ = 5381LL; + +public: + template void update(T& x) { state_ = (state_ << 5) + state_ + x; } + hash_type value() const { return state_; } +}; +hash_type Snapshot::do_hash() const +{ + XBT_DEBUG("START hash %ld", num_state_); + djb_hash hash; + // TODO: + // * nb_processes + // * heap_bytes_used + // * root variables + // * basic stack frame information + // * stack frame local variables + XBT_DEBUG("END hash %ld", num_state_); + return hash.value(); } -} // namespace mc -} // namespace simgrid +} // namespace simgrid::mc