/** Compare memory between snapshots (with known regions) * * @param addr1 Address in the first snapshot * @param snapshot2 Region of the address in the first snapshot * @param addr2 Address in the second snapshot * @param snapshot2 Region of the address in the second snapshot * @return same as memcmp * */ int MC_snapshot_region_memcmp( const void* addr1, mc_mem_region_t region1, const void* addr2, mc_mem_region_t 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; const bool region1_need_buffer = region1==NULL || region1->storage_type()==simgrid::mc::StorageType::Flat; const bool region2_need_buffer = region2==NULL || region2->storage_type()==simgrid::mc::StorageType::Flat; void* buffer1a = region1_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(size); void* buffer2a = region2_need_buffer ? NULL : stack_alloc ? alloca(size) : malloc(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 (!stack_alloc) { free(buffer1a); free(buffer2a); } return res; }
/** 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, mc_mem_region_t region1, const void* addr2, mc_mem_region_t 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 = nullptr; void* buffer2a = nullptr; if (region1 != nullptr && region1->storage_type() != simgrid::mc::StorageType::Flat) buffer1a = stack_alloc ? alloca(size) : ::operator new(size); if (region2 != nullptr && region2->storage_type() != simgrid::mc::StorageType::Flat) 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; }
void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg) { xbt_assert(((reg->permanent_address().address()) & (xbt_pagesize-1)) == 0, "Not at the beginning of a page"); xbt_assert(mc_page_count(reg->size()) == reg->page_data().page_count()); mc_restore_page_snapshot_region(process, (void*) reg->permanent_address().address(), reg->page_data()); }
/** @brief Restore a region from a snapshot * * @param reg Target region */ static void MC_region_restore(mc_mem_region_t region) { switch(region->storage_type()) { case simgrid::mc::StorageType::NoData: default: xbt_die("Storage type not supported"); break; case simgrid::mc::StorageType::Flat: mc_model_checker->process().write_bytes(region->flat_data().data(), 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()) MC_region_restore(&p); break; } }