X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/b20181dac355021101b67ba77ff07f135419e00c..394c1a744abaf32ddcc2c594c2208c30932f885a:/src/mc/sosp/mc_checkpoint.cpp diff --git a/src/mc/sosp/mc_checkpoint.cpp b/src/mc/sosp/mc_checkpoint.cpp index 0ae2a09557..24f38d6037 100644 --- a/src/mc/sosp/mc_checkpoint.cpp +++ b/src/mc/sosp/mc_checkpoint.cpp @@ -3,42 +3,18 @@ /* 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 - #ifndef WIN32 #include #endif -#include "src/internal_config.h" -#include "src/mc/mc_private.hpp" -#include "src/smpi/include/private.hpp" #include "xbt/file.hpp" -#include "xbt/mmalloc.h" -#include "xbt/module.h" - -#include "src/xbt/mmalloc/mmprivate.h" - -#include "src/simix/smx_private.hpp" - -#include -#include - -#include "src/mc/mc_private.hpp" -#include #include "src/mc/mc_config.hpp" #include "src/mc/mc_hash.hpp" -#include "src/mc/mc_mmu.hpp" +#include "src/mc/mc_private.hpp" #include "src/mc/mc_smx.hpp" -#include "src/mc/mc_unw.hpp" -#include "src/mc/remote/mc_protocol.h" #include "src/mc/sosp/mc_snapshot.hpp" -#include "src/mc/Frame.hpp" -#include "src/mc/ObjectInformation.hpp" -#include "src/mc/Variable.hpp" -#include "src/mc/sosp/RegionSnapshot.hpp" - using simgrid::mc::remote; XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkpoint, mc, "Logging specific to mc_checkpoint"); @@ -53,107 +29,7 @@ namespace mc { /************************************ Free functions **************************************/ /*****************************************************************************************/ -/** @brief Restore a region from a snapshot - * - * @param region Target region - */ -static void restore(RegionSnapshot* region) -{ - switch (region->storage_type()) { - case simgrid::mc::StorageType::Flat: - mc_model_checker->process().write_bytes(region->flat_data().get(), region->size(), region->permanent_address()); - break; - - case simgrid::mc::StorageType::Chunked: - mc_region_restore_sparse(&mc_model_checker->process(), region); - break; - - case simgrid::mc::StorageType::Privatized: - for (auto& p : region->privatized_data()) - restore(&p); - break; - - default: // includes StorageType::NoData - xbt_die("Storage type not supported"); - break; - } -} - -#if HAVE_SMPI -RegionSnapshot privatized_region(RegionType region_type, void* start_addr, void* permanent_addr, std::size_t size) -{ - size_t process_count = MC_smpi_process_count(); - - // Read smpi_privatization_regions from MCed: - smpi_privatization_region_t remote_smpi_privatization_regions; - mc_model_checker->process().read_variable("smpi_privatization_regions", &remote_smpi_privatization_regions, - sizeof(remote_smpi_privatization_regions)); - s_smpi_privatization_region_t privatization_regions[process_count]; - mc_model_checker->process().read_bytes(&privatization_regions, sizeof(privatization_regions), - remote(remote_smpi_privatization_regions)); - - std::vector data; - data.reserve(process_count); - for (size_t i = 0; i < process_count; i++) - data.push_back(simgrid::mc::region(region_type, start_addr, privatization_regions[i].address, size)); - - simgrid::mc::RegionSnapshot region = simgrid::mc::RegionSnapshot(region_type, start_addr, permanent_addr, size); - region.privatized_data(std::move(data)); - return region; -} -#endif - -static void add_region(int index, simgrid::mc::Snapshot* snapshot, simgrid::mc::RegionType type, - simgrid::mc::ObjectInformation* object_info, void* start_addr, void* permanent_addr, - std::size_t size) -{ - if (type == simgrid::mc::RegionType::Data) - xbt_assert(object_info, "Missing object info for object."); - else if (type == simgrid::mc::RegionType::Heap) - xbt_assert(not object_info, "Unexpected object info for heap region."); - - 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); - else -#endif - region = simgrid::mc::region(type, start_addr, permanent_addr, size); - - region.object_info(object_info); - snapshot->snapshot_regions[index] = - std::unique_ptr(new simgrid::mc::RegionSnapshot(std::move(region))); -} - -static void get_memory_regions(simgrid::mc::RemoteClient* process, simgrid::mc::Snapshot* snapshot) -{ - const size_t n = process->object_infos.size(); - snapshot->snapshot_regions.resize(n + 1); - int i = 0; - for (auto const& object_info : process->object_infos) { - add_region(i, snapshot, simgrid::mc::RegionType::Data, object_info.get(), object_info->start_rw, - object_info->start_rw, object_info->end_rw - object_info->start_rw); - ++i; - } - xbt_mheap_t heap = process->get_heap(); - void* start_heap = heap->base; - void* end_heap = heap->breakval; - - add_region(n, snapshot, simgrid::mc::RegionType::Heap, nullptr, start_heap, start_heap, - (char*)end_heap - (char*)start_heap); - snapshot->heap_bytes_used = mmalloc_get_bytes_used_remote(heap->heaplimit, process->get_malloc_info()); - -#if HAVE_SMPI - if (mc_model_checker->process().privatized() && MC_smpi_process_count()) - // snapshot->privatization_index = smpi_loaded_page - mc_model_checker->process().read_variable("smpi_loaded_page", &snapshot->privatization_index, - sizeof(snapshot->privatization_index)); - else -#endif - snapshot->privatization_index = simgrid::mc::ProcessIndexMissing; -} /** @brief Fills the position of the segments (executable, read-only, read/write). * */ @@ -220,253 +96,5 @@ void find_object_address(std::vector const& maps, simgrid:: xbt_assert(result->start_exec || result->start_rw || result->start_ro); } -/************************************* Take Snapshot ************************************/ -/****************************************************************************************/ - -/** @brief Checks whether the variable is in scope for a given IP. - * - * A variable may be defined only from a given value of IP. - * - * @param var Variable description - * @param scope Scope description - * @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) -{ - // The variable is not yet valid: - if (scope->range.begin() + var->start_scope > (std::uint64_t)ip) - return false; - else - return true; -} - -static void fill_local_variables_values(mc_stack_frame_t stack_frame, simgrid::mc::Frame* scope, int process_index, - std::vector& result) -{ - simgrid::mc::RemoteClient* process = &mc_model_checker->process(); - - if (not scope || not scope->range.contain(stack_frame->ip)) - return; - - for (simgrid::mc::Variable& current_variable : scope->variables) { - - if (not valid_variable(¤t_variable, scope, (void*)stack_frame->ip)) - continue; - - int region_type; - // FIXME, get rid of `region_type` - if ((long)stack_frame->ip > (long)process->libsimgrid_info->start_exec) - region_type = 1; - else - region_type = 2; - - s_local_variable_t new_var; - new_var.subprogram = stack_frame->frame; - new_var.ip = stack_frame->ip; - new_var.name = current_variable.name; - new_var.type = current_variable.type; - new_var.region = region_type; - new_var.address = nullptr; - - 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(), process_index); - - if (not location.in_memory()) - xbt_die("Cannot handle non-address variable"); - new_var.address = location.address(); - - } else - xbt_die("No address"); - - result.push_back(std::move(new_var)); - } - - // Recursive processing of nested scopes: - for (simgrid::mc::Frame& nested_scope : scope->scopes) - fill_local_variables_values(stack_frame, &nested_scope, process_index, result); -} - -static std::vector get_local_variables_values(std::vector& stack_frames, - int process_index) -{ - std::vector variables; - for (s_mc_stack_frame_t& stack_frame : stack_frames) - fill_local_variables_values(&stack_frame, stack_frame.frame, process_index, variables); - return variables; -} - -static std::vector unwind_stack_frames(simgrid::mc::UnwindContext* stack_context) -{ - simgrid::mc::RemoteClient* process = &mc_model_checker->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) { - - s_mc_stack_frame_t stack_frame; - - stack_frame.unw_cursor = c; - - unw_word_t ip; - unw_word_t sp; - - unw_get_reg(&c, UNW_REG_IP, &ip); - unw_get_reg(&c, UNW_REG_SP, &sp); - - stack_frame.ip = ip; - stack_frame.sp = sp; - - // TODO, use real addresses in frame_t instead of fixing it here - - simgrid::mc::Frame* frame = process->find_function(remote(ip)); - stack_frame.frame = frame; - - if (frame) { - stack_frame.frame_name = frame->name; - stack_frame.frame_base = (unw_word_t)frame->frame_base(c); - } else { - stack_frame.frame_base = 0; - stack_frame.frame_name = std::string(); - } - - result.push_back(std::move(stack_frame)); - - /* Stop before context switch with maestro */ - if (frame != nullptr && frame->name == "smx_ctx_wrapper") - 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"); - } - - if (result.empty()) { - XBT_INFO("unw_init_local failed"); - xbt_abort(); - } - - return result; -} - -static std::vector take_snapshot_stacks(simgrid::mc::Snapshot* snapshot) -{ - std::vector res; - - for (auto const& stack : mc_model_checker->process().stack_areas()) { - s_mc_snapshot_stack_t st; - - // Read the context from remote process: - unw_context_t context; - mc_model_checker->process().read_bytes(&context, sizeof(context), remote(stack.context)); - - st.context.initialize(&mc_model_checker->process(), &context); - - st.stack_frames = unwind_stack_frames(&st.context); - st.local_variables = get_local_variables_values(st.stack_frames, stack.process_index); - st.process_index = stack.process_index; - - unw_word_t sp = st.stack_frames[0].sp; - - res.push_back(std::move(st)); - - size_t stack_size = (char*)stack.address + stack.size - (char*)sp; - snapshot->stack_sizes.push_back(stack_size); - } - - return res; -} - -static void snapshot_handle_ignore(simgrid::mc::Snapshot* snapshot) -{ - xbt_assert(snapshot->process()); - - // Copy the memory: - for (auto const& region : mc_model_checker->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), - simgrid::mc::ProcessIndexDisabled); - snapshot->ignored_data.push_back(std::move(ignored_data)); - } - - // Zero the memory: - for (auto const& region : mc_model_checker->process().ignored_regions()) - snapshot->process()->clear_bytes(remote(region.addr), region.size); -} - -static void snapshot_ignore_restore(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)); -} - -std::shared_ptr take_snapshot(int num_state) -{ - XBT_DEBUG("Taking snapshot %i", num_state); - - simgrid::mc::RemoteClient* mc_process = &mc_model_checker->process(); - - std::shared_ptr snapshot = std::make_shared(mc_process, num_state); - - for (auto const& p : mc_model_checker->process().actors()) - snapshot->enabled_processes.insert(p.copy.getBuffer()->get_pid()); - - snapshot_handle_ignore(snapshot.get()); - - /* Save the std heap and the writable mapped pages of libsimgrid and binary */ - get_memory_regions(mc_process, snapshot.get()); - - snapshot->to_ignore = mc_model_checker->process().ignored_heap(); - - if (_sg_mc_max_visited_states > 0 || not _sg_mc_property_file.get().empty()) { - snapshot->stacks = take_snapshot_stacks(snapshot.get()); - if (_sg_mc_hash) - snapshot->hash = simgrid::mc::hash(*snapshot); - else - snapshot->hash = 0; - } else - snapshot->hash = 0; - - snapshot_ignore_restore(snapshot.get()); - return snapshot; -} - -static inline void restore_snapshot_regions(simgrid::mc::Snapshot* snapshot) -{ - for (std::unique_ptr const& region : snapshot->snapshot_regions) { - // For privatized, variables we decided it was not necessary to take the snapshot: - if (region) - restore(region.get()); - } - -#if HAVE_SMPI - if (snapshot->privatization_index >= 0) { - // Fix the privatization mmap: - s_mc_message_restore_t message{MC_MESSAGE_RESTORE, snapshot->privatization_index}; - mc_model_checker->process().getChannel().send(message); - } -#endif -} - -void restore_snapshot(std::shared_ptr snapshot) -{ - XBT_DEBUG("Restore snapshot %i", snapshot->num_state); - restore_snapshot_regions(snapshot.get()); - snapshot_ignore_restore(snapshot.get()); - mc_model_checker->process().clear_cache(); -} - } // namespace mc } // namespace simgrid