Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] RegionSnapshot class
authorGabriel Corona <gabriel.corona@loria.fr>
Fri, 29 May 2015 08:05:36 +0000 (10:05 +0200)
committerGabriel Corona <gabriel.corona@loria.fr>
Mon, 1 Jun 2015 10:41:10 +0000 (12:41 +0200)
src/mc/mc_checkpoint.cpp
src/mc/mc_compare.cpp
src/mc/mc_page_snapshot.cpp
src/mc/mc_snapshot.cpp
src/mc/mc_snapshot.h

index 32e0a9a..26c6a2a 100644 (file)
@@ -73,52 +73,37 @@ static void local_variable_free_voidp(void *v)
   local_variable_free((local_variable_t) * (void **) v);
 }
 
-void MC_region_destroy(mc_mem_region_t region)
-{
-  if (!region)
-    return;
-  switch(region->storage_type) {
-    case MC_REGION_STORAGE_TYPE_NONE:
-      break;
-    case MC_REGION_STORAGE_TYPE_FLAT:
-      xbt_free(region->flat.data);
-      break;
-    case MC_REGION_STORAGE_TYPE_CHUNKED:
-      mc_free_page_snapshot_region(region->chunked.page_numbers, mc_page_count(region->size));
-      xbt_free(region->chunked.page_numbers);
-      break;
-    case MC_REGION_STORAGE_TYPE_PRIVATIZED:
-      {
-        size_t regions_count = region->privatized.regions_count;
-        for (size_t i=0; i!=regions_count; ++i) {
-          MC_region_destroy(region->privatized.regions[i]);
-        }
-        free(region->privatized.regions);
-        break;
-      }
-  }
-  xbt_free(region);
+}
+
+namespace simgrid {
+namespace mc {
+
+RegionSnapshot::~RegionSnapshot() {}
+
+}
 }
 
 /*******************************  Snapshot regions ********************************/
 /*********************************************************************************/
 
+extern "C" {
+
 static mc_mem_region_t mc_region_new_dense(
   mc_region_type_t region_type,
   void *start_addr, void* permanent_addr, size_t size)
 {
-  mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+  mc_mem_region_t region = new simgrid::mc::RegionSnapshot();
   region->region_type = region_type;
   region->storage_type = MC_REGION_STORAGE_TYPE_FLAT;
   region->start_addr = start_addr;
   region->permanent_addr = permanent_addr;
   region->size = size;
-  region->flat.data = xbt_malloc(size);
-  mc_model_checker->process().read_bytes(region->flat.data, size,
+  region->flat_data_.resize(size);
+  mc_model_checker->process().read_bytes(region->flat_data_.data(), size,
     remote(permanent_addr),
     simgrid::mc::ProcessIndexDisabled);
   XBT_DEBUG("New region : type : %d, data : %p (real addr %p), size : %zu",
-            region_type, region->flat.data, permanent_addr, size);
+            region_type, region->flat_data_.data(), permanent_addr, size);
   return region;
 }
 
@@ -152,7 +137,7 @@ static void MC_region_restore(mc_mem_region_t region)
     break;
 
   case MC_REGION_STORAGE_TYPE_FLAT:
-    mc_model_checker->process().write_bytes(region->flat.data, region->size,
+    mc_model_checker->process().write_bytes(region->flat_data_.data(), region->size,
       remote(region->permanent_addr));
     break;
 
@@ -161,13 +146,9 @@ static void MC_region_restore(mc_mem_region_t region)
     break;
 
   case MC_REGION_STORAGE_TYPE_PRIVATIZED:
-    {
-      size_t process_count = region->privatized.regions_count;
-      for (size_t i = 0; i < process_count; i++) {
-        MC_region_restore(region->privatized.regions[i]);
-      }
-      break;
-    }
+    for (auto const& p : region->privatized_regions_)
+      MC_region_restore(p.get());
+    break;
   }
 }
 
@@ -176,14 +157,13 @@ static mc_mem_region_t MC_region_new_privatized(
     )
 {
   size_t process_count = MC_smpi_process_count();
-  mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+  mc_mem_region_t region = new simgrid::mc::RegionSnapshot();
   region->region_type = region_type;
   region->storage_type = MC_REGION_STORAGE_TYPE_PRIVATIZED;
   region->start_addr = start_addr;
   region->permanent_addr = permanent_addr;
   region->size = size;
-  region->privatized.regions_count = process_count;
-  region->privatized.regions = xbt_new(mc_mem_region_t, process_count);
+  region->privatized_regions_.resize(process_count);
 
   // Read smpi_privatisation_regions from MCed:
   smpi_privatisation_region_t remote_smpi_privatisation_regions;
@@ -196,9 +176,10 @@ static mc_mem_region_t MC_region_new_privatized(
     remote(remote_smpi_privatisation_regions));
 
   for (size_t i = 0; i < process_count; i++) {
-    region->privatized.regions[i] =
+    region->privatized_regions_[i] = std::unique_ptr<simgrid::mc::RegionSnapshot>(
       MC_region_new(region_type, start_addr,
-        privatisation_regions[i].address, size);
+        privatisation_regions[i].address, size)
+      );
   }
 
   return region;
index 2a5a53d..9887e55 100644 (file)
@@ -275,13 +275,14 @@ static int compare_global_variables(mc_object_info_t object_info,
     }
 
     size_t process_count = MC_smpi_process_count();
-    xbt_assert(process_count == r1->privatized.regions_count
-      && process_count == r2->privatized.regions_count);
+    xbt_assert(process_count == r1->privatized_regions_.size()
+      && process_count == r2->privatized_regions_.size());
 
     // Compare the global variables separately for each simulates process:
     for (size_t process_index = 0; process_index < process_count; process_index++) {
       int is_diff = compare_global_variables(object_info, process_index,
-        r1->privatized.regions[process_index], r2->privatized.regions[process_index],
+        r1->privatized_regions_[process_index].get(),
+        r2->privatized_regions_[process_index].get(),
         snapshot1, snapshot2);
       if (is_diff) return 1;
     }
index 7725f41..79e38e4 100644 (file)
@@ -16,9 +16,8 @@
 
 using simgrid::mc::remote;
 
-extern "C" {
-
-// ***** Region management:
+namespace simgrid {
+namespace mc {
 
 /** @brief Take a per-page snapshot of a region
  *
@@ -26,27 +25,19 @@ extern "C" {
  *  @param pag_count       Number of pages of the region
  *  @return                Snapshot page numbers of this new snapshot
  */
-size_t* mc_take_page_snapshot_region(mc_process_t process,
-  void* data, size_t page_count)
+PerPageCopy::PerPageCopy(PageStore& store, AddressSpace& as,
+    remote_ptr<void> addr, std::size_t page_count)
 {
-  size_t* pagenos = (size_t*) malloc(page_count * sizeof(size_t));
-
-  const bool is_self = process->is_self();
+  store_ = &store;
+  this->pagenos_.resize(page_count);
+  std::vector<char> buffer(xbt_pagesize);
 
-  void* temp = NULL;
-  if (!is_self)
-    temp = malloc(xbt_pagesize);
+  for (size_t i = 0; i != page_count; ++i) {
 
-  for (size_t i=0; i!=page_count; ++i) {
+      remote_ptr<void> page = remote(addr.address() + (i << xbt_pagebits));
+      xbt_assert(mc_page_offset((void*)page.address())==0,
+        "Not at the beginning of a page");
 
-      // Otherwise, we need to store the page the hard way
-      // (by reading its content):
-      void* page = (char*) data + (i << xbt_pagebits);
-      xbt_assert(mc_page_offset(page)==0, "Not at the beginning of a page");
-      void* page_data;
-      if (is_self) {
-        page_data = page;
-      } else {
         /* Adding another copy (and a syscall) will probably slow things a lot.
            TODO, optimize this somehow (at least by grouping the syscalls)
            if needed. Either:
@@ -54,26 +45,21 @@ size_t* mc_take_page_snapshot_region(mc_process_t process,
             - let the application snapshot itself;
             - move the segments in shared memory (this will break `fork` however).
         */
-        page_data = temp;
-        process->read_bytes(
-          temp, xbt_pagesize, remote(page),
+
+        as.read_bytes(
+          buffer.data(), xbt_pagesize, page,
           simgrid::mc::ProcessIndexDisabled);
-      }
-      pagenos[i] = mc_model_checker->page_store().store_page(page_data);
 
-  }
+      pagenos_[i] = store_->store_page(buffer.data());
 
-  free(temp);
-  return pagenos;
+  }
 }
 
-void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count)
-{
-  for (size_t i=0; i!=page_count; ++i) {
-    mc_model_checker->page_store().unref_page(pagenos[i]);
-  }
+}
 }
 
+extern "C" {
+
 /** @brief Restore a snapshot of a region
  *
  *  If possible, the restoration will be incremental
@@ -84,12 +70,12 @@ void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count)
  *  @param pagenos
  */
 void mc_restore_page_snapshot_region(mc_process_t process,
-  void* start_addr, size_t page_count, size_t* pagenos)
+  void* start_addr, simgrid::mc::PerPageCopy const& pages_copy)
 {
-  for (size_t i=0; i!=page_count; ++i) {
+  for (size_t i = 0; i != pages_copy.page_count(); ++i) {
     // Otherwise, copy the page:
     void* target_page = mc_page_from_number(start_addr, i);
-    const void* source_page = mc_model_checker->page_store().get_page(pagenos[i]);
+    const void* source_page = pages_copy.page(i);
     process->write_bytes(source_page, xbt_pagesize, remote(target_page));
   }
 }
@@ -101,7 +87,7 @@ mc_mem_region_t mc_region_new_sparse(mc_region_type_t region_type,
 {
   mc_process_t process = &mc_model_checker->process();
 
-  mc_mem_region_t region = xbt_new(s_mc_mem_region_t, 1);
+  mc_mem_region_t region = new simgrid::mc::RegionSnapshot();
   region->region_type = region_type;
   region->storage_type = MC_REGION_STORAGE_TYPE_CHUNKED;
   region->start_addr = start_addr;
@@ -115,7 +101,7 @@ mc_mem_region_t mc_region_new_sparse(mc_region_type_t region_type,
   size_t page_count = mc_page_count(size);
 
   // Take incremental snapshot:
-  region->chunked.page_numbers = mc_take_page_snapshot_region(process,
+  region->page_numbers_ = simgrid::mc::PerPageCopy(mc_model_checker->page_store(), *process,
     permanent_addr, page_count);
 
   return region;
@@ -125,10 +111,9 @@ void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg)
 {
   xbt_assert((((uintptr_t)reg->permanent_addr) & (xbt_pagesize-1)) == 0,
     "Not at the beginning of a page");
-  size_t page_count = mc_page_count(reg->size);
-
+  xbt_assert(mc_page_count(reg->size) == reg->page_numbers_.page_count());
   mc_restore_page_snapshot_region(process,
-    reg->permanent_addr, page_count, reg->chunked.page_numbers);
+    reg->permanent_addr, reg->page_numbers_);
 }
 
 }
index 46c0a46..5a101b9 100644 (file)
@@ -41,10 +41,10 @@ mc_mem_region_t mc_get_snapshot_region(
       if (process_index < 0) {
         xbt_die("Missing process index");
       }
-      if (process_index >= (int) region->privatized.regions_count) {
+      if (process_index >= (int) region->privatized_regions_.size()) {
         xbt_die("Invalid process index");
       }
-      mc_mem_region_t priv_region = region->privatized.regions[process_index];
+      mc_mem_region_t priv_region = region->privatized_regions_[process_index].get();
       xbt_assert(mc_region_contain(priv_region, addr));
       return priv_region;
 #else
@@ -174,7 +174,7 @@ Snapshot::Snapshot() :
 Snapshot::~Snapshot()
 {
   for (size_t i = 0; i < this->snapshot_regions_count; i++) {
-    MC_region_destroy(this->snapshot_regions[i]);
+    delete this->snapshot_regions[i];
   }
   xbt_free(this->snapshot_regions);
   xbt_free(this->stack_sizes);
@@ -300,11 +300,11 @@ static void test_snapshot(bool sparse_checkpoint) {
         MC_REGION_TYPE_UNKNOWN, source, source, byte_size);
       xbt_test_assert(MC_region_read_pointer(region2, source) == mc_model_checker,
         "Mismtach in MC_region_read_pointer()");
-      MC_region_destroy(region2);
+      delete region2;
     }
 
-    MC_region_destroy(region);
-    MC_region_destroy(region0);
+    delete region;
+    delete region0;
     munmap(destination, byte_size);
     munmap(source, byte_size);
   }
index 279ca5b..412606f 100644 (file)
@@ -40,6 +40,76 @@ typedef enum e_mc_region_storeage_type_t {
   MC_REGION_STORAGE_TYPE_PRIVATIZED = 3
 } mc_region_storage_type_t;
 
+namespace simgrid {
+namespace mc {
+
+class PerPageCopy {
+  PageStore* store_;
+  std::vector<std::size_t> pagenos_;
+public:
+  PerPageCopy() : store_(nullptr) {}
+  PerPageCopy(PerPageCopy const& that)
+  {
+    store_ = that.store_;
+    pagenos_ = that.pagenos_;
+    for (std::size_t pageno : pagenos_)
+      store_->ref_page(pageno);
+  }
+  void clear()
+  {
+    for (std::size_t pageno : pagenos_)
+      store_->unref_page(pageno);
+    pagenos_.clear();
+  }
+  ~PerPageCopy() {
+    clear();
+  }
+
+  PerPageCopy(PerPageCopy&& that)
+  {
+    store_ = that.store_;
+    that.store_ = nullptr;
+    pagenos_ = std::move(that.pagenos_);
+    that.pagenos_.clear();
+  }
+  PerPageCopy& operator=(PerPageCopy const& that)
+  {
+    this->clear();
+    store_ = that.store_;
+    pagenos_ = that.pagenos_;
+    for (std::size_t pageno : pagenos_)
+      store_->ref_page(pageno);
+    return *this;
+  }
+  PerPageCopy& operator=(PerPageCopy && that)
+  {
+    this->clear();
+    store_ = that.store_;
+    that.store_ = nullptr;
+    pagenos_ = std::move(that.pagenos_);
+    that.pagenos_.clear();
+    return *this;
+  }
+
+  std::size_t page_count() const
+  {
+    return pagenos_.size();
+  }
+
+  std::size_t pageno(std::size_t i) const
+  {
+    return pagenos_[i];
+  }
+
+  const void* page(std::size_t i) const
+  {
+    return store_->get_page(pagenos_[i]);
+  }
+
+  PerPageCopy(PageStore& store, AddressSpace& as,
+    remote_ptr<void> addr, std::size_t page_count);
+};
+
 /** @brief Copy/snapshot of a given memory region
  *
  *  Different types of region snapshot storage types exist:
@@ -56,9 +126,8 @@ typedef enum e_mc_region_storeage_type_t {
  *    * an anonymous enum is used to distinguish the relevant types for
  *      each type.
  */
-typedef struct s_mc_mem_region s_mc_mem_region_t, *mc_mem_region_t;
-
-struct s_mc_mem_region {
+class RegionSnapshot {
+public:
   mc_region_type_t region_type;
   mc_region_storage_type_t storage_type;
   mc_object_info_t object_info;
@@ -80,26 +149,30 @@ struct s_mc_mem_region {
    * */
   void *permanent_addr;
 
-  union {
-    struct {
-      /** @brief Copy of the snapshot for flat snapshots regions (NULL otherwise) */
-      void *data;
-    } flat;
-    struct {
-      /** @brief Pages indices in the page store for per-page snapshots (NULL otherwise) */
-      size_t* page_numbers;
-    } chunked;
-    struct {
-      size_t regions_count;
-      mc_mem_region_t* regions;
-    } privatized;
-  };
-
+  std::vector<char> flat_data_;
+  PerPageCopy page_numbers_;
+  std::vector<std::unique_ptr<RegionSnapshot>> privatized_regions_;
+public:
+  RegionSnapshot() :
+    region_type(MC_REGION_TYPE_UNKNOWN),
+    storage_type(MC_REGION_STORAGE_TYPE_NONE),
+    object_info(nullptr),
+    start_addr(nullptr),
+    size(0),
+    permanent_addr(nullptr)
+  {}
+  ~RegionSnapshot();
+  RegionSnapshot(RegionSnapshot const&) = delete;
+  RegionSnapshot& operator=(RegionSnapshot const&) = delete;
 };
 
+}
+}
+
+typedef class simgrid::mc::RegionSnapshot s_mc_mem_region_t, *mc_mem_region_t;
+
 MC_SHOULD_BE_INTERNAL mc_mem_region_t mc_region_new_sparse(
   mc_region_type_t type, void *start_addr, void* data_addr, size_t size);
-MC_SHOULD_BE_INTERNAL void MC_region_destroy(mc_mem_region_t reg);
 XBT_INTERNAL void mc_region_restore_sparse(mc_process_t process, mc_mem_region_t reg);
 
 static inline  __attribute__ ((always_inline))
@@ -113,9 +186,8 @@ static inline __attribute__((always_inline))
 void* mc_translate_address_region_chunked(uintptr_t addr, mc_mem_region_t region)
 {
   size_t pageno = mc_page_number(region->start_addr, (void*) addr);
-  size_t snapshot_pageno = region->chunked.page_numbers[pageno];
   const void* snapshot_page =
-    mc_model_checker->page_store().get_page(snapshot_pageno);
+    region->page_numbers_.page(pageno);
   return (char*) snapshot_page + mc_page_offset((void*) addr);
 }
 
@@ -130,7 +202,7 @@ void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region, int pr
   case MC_REGION_STORAGE_TYPE_FLAT:
     {
       uintptr_t offset = addr - (uintptr_t) region->start_addr;
-      return (void *) ((uintptr_t) region->flat.data + offset);
+      return (void *) ((uintptr_t) region->flat_data_.data() + offset);
     }
 
   case MC_REGION_STORAGE_TYPE_CHUNKED:
@@ -140,9 +212,9 @@ void* mc_translate_address_region(uintptr_t addr, mc_mem_region_t region, int pr
     {
       xbt_assert(process_index >=0,
         "Missing process index for privatized region");
-      xbt_assert((size_t) process_index < region->privatized.regions_count,
+      xbt_assert((size_t) process_index < region->privatized_regions_.size(),
         "Out of range process index");
-      mc_mem_region_t subregion = region->privatized.regions[process_index];
+      mc_mem_region_t subregion = region->privatized_regions_[process_index].get();
       xbt_assert(subregion, "Missing memory region for process %i", process_index);
       return mc_translate_address_region(addr, subregion, process_index);
     }
@@ -252,12 +324,9 @@ static const void* mc_snapshot_get_heap_end(mc_snapshot_t snapshot);
 XBT_INTERNAL mc_snapshot_t MC_take_snapshot(int num_state);
 XBT_INTERNAL void MC_restore_snapshot(mc_snapshot_t);
 
-XBT_INTERNAL size_t* mc_take_page_snapshot_region(mc_process_t process,
-  void* data, size_t page_count);
-XBT_INTERNAL void mc_free_page_snapshot_region(size_t* pagenos, size_t page_count);
 XBT_INTERNAL void mc_restore_page_snapshot_region(
   mc_process_t process,
-  void* start_addr, size_t page_count, size_t* pagenos);
+  void* start_addr, simgrid::mc::PerPageCopy const& pagenos);
 
 MC_SHOULD_BE_INTERNAL const void* MC_region_read_fragmented(
   mc_mem_region_t region, void* target, const void* addr, size_t size);
@@ -311,7 +380,7 @@ const void* MC_region_read(mc_mem_region_t region, void* target, const void* add
     xbt_die("Storage type not supported");
 
   case MC_REGION_STORAGE_TYPE_FLAT:
-    return (char*) region->flat.data + offset;
+    return (char*) region->flat_data_.data() + offset;
 
   case MC_REGION_STORAGE_TYPE_CHUNKED:
     {