/** 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; }
const void* Snapshot::read_bytes(void* buffer, std::size_t size, RemotePtr<void> address, int process_index, ReadOptions options) const { mc_mem_region_t region = mc_get_snapshot_region((void*)address.address(), this, process_index); if (region) { const void* res = MC_region_read(region, buffer, (void*)address.address(), size); if (buffer == res || options & ReadOptions::lazy()) return res; else { memcpy(buffer, res, size); return buffer; } } else return this->process()->read_bytes(buffer, size, address, process_index, options); }
const void* Snapshot::read_bytes(void* buffer, std::size_t size, remote_ptr<void> address, int process_index, AddressSpace::ReadMode mode) const { mc_mem_region_t region = mc_get_snapshot_region((void*)address.address(), this, process_index); if (region) { const void* res = MC_region_read(region, buffer, (void*)address.address(), size); if (buffer == res || mode == AddressSpace::Lazy) return res; else { memcpy(buffer, res, size); return buffer; } } else return this->process()->read_bytes( buffer, size, address, process_index, mode); }
static void test_snapshot(bool sparse_checkpoint) { xbt_test_add("Initialisation"); _sg_mc_sparse_checkpoint = sparse_checkpoint; xbt_assert(xbt_pagesize == getpagesize()); xbt_assert(1 << xbt_pagebits == xbt_pagesize); mc_model_checker = new ::simgrid::mc::ModelChecker(getpid(), -1); for(int n=1; n!=256; ++n) { // Store region page(s): size_t byte_size = n * xbt_pagesize; void* source = mmap(NULL, byte_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); xbt_assert(source!=MAP_FAILED, "Could not allocate source memory"); // Init memory and take snapshots: init_memory(source, byte_size); simgrid::mc::RegionSnapshot region0 = simgrid::mc::sparse_region( simgrid::mc::RegionType::Unknown, source, source, byte_size, nullptr); for(int i=0; i<n; i+=2) { init_memory((char*) source + i*xbt_pagesize, xbt_pagesize); } simgrid::mc::RegionSnapshot region = simgrid::mc::sparse_region( simgrid::mc::RegionType::Unknown, source, source, byte_size, nullptr); void* destination = mmap(NULL, byte_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); xbt_assert(source!=MAP_FAILED, "Could not allocate destination memory"); xbt_test_add("Reading whole region data for %i page(s)", n); const void* read = MC_region_read(®ion, destination, source, byte_size); xbt_test_assert(!memcmp(source, read, byte_size), "Mismatch in MC_region_read()"); xbt_test_add("Reading parts of region data for %i page(s)", n); for(int j=0; j!=100; ++j) { size_t offset = rand() % byte_size; size_t size = rand() % (byte_size - offset); const void* read = MC_region_read(®ion, destination, (const char*) source+offset, size); xbt_test_assert(!memcmp((char*) source+offset, read, size), "Mismatch in MC_region_read()"); } xbt_test_add("Compare whole region data for %i page(s)", n); xbt_test_assert(MC_snapshot_region_memcmp(source, ®ion0, source, ®ion, byte_size), "Unexpected match in MC_snapshot_region_memcmp() with previous snapshot"); xbt_test_add("Compare parts of region data for %i page(s) with itself", n); for(int j=0; j!=100; ++j) { size_t offset = rand() % byte_size; size_t size = rand() % (byte_size - offset); xbt_test_assert(!MC_snapshot_region_memcmp((char*) source+offset, ®ion, (char*) source+offset, ®ion, size), "Mismatch in MC_snapshot_region_memcmp()"); } if (n==1) { xbt_test_add("Read pointer for %i page(s)", n); memcpy(source, &mc_model_checker, sizeof(void*)); simgrid::mc::RegionSnapshot region2 = simgrid::mc::sparse_region( simgrid::mc::RegionType::Unknown, source, source, byte_size, nullptr); xbt_test_assert(MC_region_read_pointer(®ion2, source) == mc_model_checker, "Mismtach in MC_region_read_pointer()"); } munmap(destination, byte_size); munmap(source, byte_size); } delete mc_model_checker; mc_model_checker = NULL; }