X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/e7173457dce01a608824b72d2e4ff62572d51d13..a816142ba29faddef700304e151716780d431d20:/src/mc/mc_checkpoint.cpp diff --git a/src/mc/mc_checkpoint.cpp b/src/mc/mc_checkpoint.cpp index 9d38793d4c..4360d0648b 100644 --- a/src/mc/mc_checkpoint.cpp +++ b/src/mc/mc_checkpoint.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2014. The SimGrid Team. +/* Copyright (c) 2008-2015. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@ -36,6 +36,10 @@ #include "mc_smx.h" #include "mc_hash.hpp" +#include "mc/ObjectInformation.hpp" +#include "mc/Frame.hpp" +#include "mc/Variable.hpp" + using simgrid::mc::remote; extern "C" { @@ -46,22 +50,6 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkpoint, mc, /************************************ Free functions **************************************/ /*****************************************************************************************/ -static void MC_snapshot_stack_free_voidp(void *s) -{ - mc_snapshot_stack_t stack = (mc_snapshot_stack_t) * (void **) s; - delete stack; -} - -static void local_variable_free_voidp(void *v) -{ - local_variable_t var = *(local_variable_t*)v; - delete var; -} - -} - -extern "C" { - /** @brief Restore a region from a snapshot * * @param reg Target region @@ -75,7 +63,7 @@ static void MC_region_restore(mc_mem_region_t region) break; case simgrid::mc::StorageType::Flat: - mc_model_checker->process().write_bytes(region->flat_data().data(), + mc_model_checker->process().write_bytes(region->flat_data(), region->size(), region->permanent_address()); break; @@ -95,8 +83,10 @@ static void MC_region_restore(mc_mem_region_t region) namespace simgrid { namespace mc { +#ifdef HAVE_SMPI simgrid::mc::RegionSnapshot privatized_region( - RegionType region_type, void *start_addr, void* permanent_addr, size_t size + RegionType region_type, void *start_addr, void* permanent_addr, + std::size_t size, const simgrid::mc::RegionSnapshot* ref_region ) { size_t process_count = MC_smpi_process_count(); @@ -113,17 +103,20 @@ simgrid::mc::RegionSnapshot privatized_region( 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, - privatisation_regions[i].address, size) - ); + for (size_t i = 0; i < process_count; i++) { + const simgrid::mc::RegionSnapshot* ref_privatized_region = nullptr; + if (ref_region && ref_region->storage_type() == StorageType::Privatized) + ref_privatized_region = &ref_region->privatized_data()[i]; + data.push_back(simgrid::mc::region(region_type, start_addr, + privatisation_regions[i].address, size, ref_privatized_region)); + } simgrid::mc::RegionSnapshot region = simgrid::mc::RegionSnapshot( region_type, start_addr, permanent_addr, size); region.privatized_data(std::move(data)); return std::move(region); } +#endif } } @@ -132,21 +125,28 @@ extern "C" { static void MC_snapshot_add_region(int index, mc_snapshot_t snapshot, simgrid::mc::RegionType type, - mc_object_info_t object_info, - void *start_addr, void* permanent_addr, size_t size) + 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(!object_info, "Unexpected object info for heap region."); - const bool privatization_aware = object_info && object_info->privatized(); + simgrid::mc::RegionSnapshot const* ref_region = nullptr; + if (mc_model_checker->parent_snapshot_) + ref_region = mc_model_checker->parent_snapshot_->snapshot_regions[index].get(); simgrid::mc::RegionSnapshot region; +#ifdef HAVE_SMPI + const bool privatization_aware = object_info && object_info->privatized(); if (privatization_aware && MC_smpi_process_count()) - region = simgrid::mc::privatized_region(type, start_addr, permanent_addr, size); + region = simgrid::mc::privatized_region( + type, start_addr, permanent_addr, size, ref_region); else - region = simgrid::mc::region(type, start_addr, permanent_addr, size); +#endif + region = simgrid::mc::region(type, start_addr, permanent_addr, size, ref_region); region.object_info(object_info); snapshot->snapshot_regions[index] @@ -155,7 +155,7 @@ static void MC_snapshot_add_region(int index, mc_snapshot_t snapshot, return; } -static void MC_get_memory_regions(mc_process_t process, mc_snapshot_t snapshot) +static void MC_get_memory_regions(simgrid::mc::Process* process, mc_snapshot_t snapshot) { const size_t n = process->object_infos.size(); snapshot->snapshot_regions.resize(n + 1); @@ -196,9 +196,12 @@ static void MC_get_memory_regions(mc_process_t process, mc_snapshot_t snapshot) * * `dl_iterate_phdr` would be more robust but would not work in cross-process. * */ -void MC_find_object_address(std::vector const& maps, mc_object_info_t result) +void MC_find_object_address( + std::vector const& maps, + simgrid::mc::ObjectInformation* result) { - const char *name = basename(result->file_name); + char* file_name = xbt_strdup(result->file_name.c_str()); + const char *name = basename(file_name); for (size_t i = 0; i < maps.size(); ++i) { simgrid::mc::VmMap const& reg = maps[i]; if (maps[i].pathname.empty() @@ -243,9 +246,9 @@ void MC_find_object_address(std::vector const& maps, mc_obje if (result->end_exec && (const void*) result->end_exec > result->end) result->end = result->end_exec; - xbt_assert(result->file_name); xbt_assert(result->start_rw); xbt_assert(result->start_exec); + free(file_name); } /************************************* Take Snapshot ************************************/ @@ -260,7 +263,8 @@ void MC_find_object_address(std::vector const& maps, mc_obje * \param ip Instruction pointer * \return true if the variable is valid * */ -static bool mc_valid_variable(mc_variable_t var, mc_frame_t scope, +static bool mc_valid_variable(simgrid::mc::Variable* var, + simgrid::mc::Frame* scope, const void *ip) { // The variable is not yet valid: @@ -271,20 +275,20 @@ static bool mc_valid_variable(mc_variable_t var, mc_frame_t scope, } static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame, - mc_frame_t scope, int process_index, + simgrid::mc::Frame* scope, + int process_index, std::vector& result) { - mc_process_t process = &mc_model_checker->process(); + simgrid::mc::Process* process = &mc_model_checker->process(); void *ip = (void *) stack_frame->ip; if (ip < scope->low_pc || ip >= scope->high_pc) return; - unsigned cursor = 0; - mc_variable_t current_variable; - xbt_dynar_foreach(scope->variables, cursor, current_variable) { + for(simgrid::mc::Variable& current_variable : + scope->variables) { - if (!mc_valid_variable(current_variable, scope, (void *) stack_frame->ip)) + if (!mc_valid_variable(¤t_variable, scope, (void *) stack_frame->ip)) continue; int region_type; @@ -297,30 +301,25 @@ static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame, 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.name = current_variable.name; + new_var.type = current_variable.type; new_var.region = region_type; new_var.address = nullptr; - if (current_variable->address != NULL) { - new_var.address = current_variable->address; - } else if (current_variable->location_list.size != 0) { - s_mc_location_t location; - mc_dwarf_resolve_locations( - &location, ¤t_variable->location_list, - current_variable->object_info, - &(stack_frame->unw_cursor), - (void *) stack_frame->frame_base, - &mc_model_checker->process(), process_index); - - switch(mc_get_location_type(&location)) { - case MC_LOCATION_TYPE_ADDRESS: - new_var.address = location.memory_location; - break; - case MC_LOCATION_TYPE_REGISTER: - default: + if (current_variable.address != NULL) { + new_var.address = current_variable.address; + } else if (!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 (!location.in_memory()) xbt_die("Cannot handle non-address variable"); - } + new_var.address = location.address(); } else { xbt_die("No address"); @@ -330,10 +329,9 @@ static void mc_fill_local_variables_values(mc_stack_frame_t stack_frame, } // Recursive processing of nested scopes: - mc_frame_t nested_scope = nullptr; - xbt_dynar_foreach(scope->scopes, cursor, nested_scope) { - mc_fill_local_variables_values(stack_frame, nested_scope, process_index, result); - } + for(simgrid::mc::Frame& nested_scope : scope->scopes) + mc_fill_local_variables_values( + stack_frame, &nested_scope, process_index, result); } static std::vector MC_get_local_variables_values( @@ -353,7 +351,7 @@ static void MC_stack_frame_free_voipd(void *s) static std::vector MC_unwind_stack_frames(mc_unw_context_t stack_context) { - mc_process_t process = &mc_model_checker->process(); + simgrid::mc::Process* process = &mc_model_checker->process(); std::vector result; unw_cursor_t c; @@ -380,13 +378,13 @@ static std::vector MC_unwind_stack_frames(mc_unw_context_t s // TODO, use real addresses in frame_t instead of fixing it here - mc_frame_t frame = process->find_function(remote(ip)); + 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) mc_find_frame_base(frame, frame->object_info, &c); + (unw_word_t) frame->frame_base(c); } else { stack_frame.frame_base = 0; stack_frame.frame_name = std::string(); @@ -476,7 +474,7 @@ static std::vector MC_take_snapshot_ignore() static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot) { - xbt_assert(snapshot->process); + xbt_assert(snapshot->process()); // Copy the memory: for (auto const& region : mc_model_checker->process().ignored_regions()) { @@ -484,7 +482,7 @@ static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot) 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( + 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)); @@ -492,7 +490,7 @@ static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot) // Zero the memory: for(auto const& region : mc_model_checker->process().ignored_regions()) { - snapshot->process->clear_bytes(remote(region.addr), region.size); + snapshot->process()->clear_bytes(remote(region.addr), region.size); } } @@ -500,7 +498,7 @@ static void MC_snapshot_handle_ignore(mc_snapshot_t snapshot) static void MC_snapshot_ignore_restore(mc_snapshot_t snapshot) { for (auto const& ignored_data : snapshot->ignored_data) - snapshot->process->write_bytes( + snapshot->process()->write_bytes( ignored_data.data.data(), ignored_data.data.size(), remote(ignored_data.start)); } @@ -548,8 +546,10 @@ static std::vector MC_get_current_fds(pid_t pid) } link[res] = '\0'; +#ifdef HAVE_SMPI if(smpi_is_privatisation_file(link)) continue; +#endif // This is (probably) the DIR* we are reading: // TODO, read all the file entries at once and close the DIR.* @@ -586,11 +586,10 @@ mc_snapshot_t MC_take_snapshot(int num_state) { XBT_DEBUG("Taking snapshot %i", num_state); - mc_process_t mc_process = &mc_model_checker->process(); + simgrid::mc::Process* mc_process = &mc_model_checker->process(); - mc_snapshot_t snapshot = new simgrid::mc::Snapshot(); + mc_snapshot_t snapshot = new simgrid::mc::Snapshot(mc_process); - snapshot->process = mc_process; snapshot->num_state = num_state; smx_process_t process; @@ -602,15 +601,19 @@ mc_snapshot_t MC_take_snapshot(int num_state) if (_sg_mc_snapshot_fds) snapshot->current_fds = MC_get_current_fds(process->pid); + const bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty; + /* Save the std heap and the writable mapped pages of libsimgrid and binary */ MC_get_memory_regions(mc_process, snapshot); + if (use_soft_dirty) + mc_process->reset_soft_dirty(); snapshot->to_ignore = MC_take_snapshot_ignore(); if (_sg_mc_visited > 0 || strcmp(_sg_mc_property_file, "")) { snapshot->stacks = MC_take_snapshot_stacks(&snapshot); - if (_sg_mc_hash && !snapshot->stacks.empty()) { + if (_sg_mc_hash) { snapshot->hash = simgrid::mc::hash(*snapshot); } else { snapshot->hash = 0; @@ -620,6 +623,8 @@ mc_snapshot_t MC_take_snapshot(int num_state) } MC_snapshot_ignore_restore(snapshot); + if (use_soft_dirty) + mc_model_checker->parent_snapshot_ = snapshot; return snapshot; } @@ -670,11 +675,16 @@ void MC_restore_snapshot_fds(mc_snapshot_t snapshot) void MC_restore_snapshot(mc_snapshot_t snapshot) { XBT_DEBUG("Restore snapshot %i", snapshot->num_state); + const bool use_soft_dirty = _sg_mc_sparse_checkpoint && _sg_mc_soft_dirty; MC_restore_snapshot_regions(snapshot); if (_sg_mc_snapshot_fds) MC_restore_snapshot_fds(snapshot); + if (use_soft_dirty) + mc_model_checker->process().reset_soft_dirty(); MC_snapshot_ignore_restore(snapshot); mc_model_checker->process().cache_flags = 0; + if (use_soft_dirty) + mc_model_checker->parent_snapshot_ = snapshot; } mc_snapshot_t simcall_HANDLER_mc_snapshot(smx_simcall_t simcall)