Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Exclude preexisting region when computing smpi_data_exe_size.
authorArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Wed, 11 Apr 2018 20:38:31 +0000 (22:38 +0200)
committerArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Wed, 11 Apr 2018 20:44:18 +0000 (22:44 +0200)
The goal is to fix thread context+mmap privatization errors seen under Tsan.

src/smpi/include/private.hpp
src/smpi/internals/smpi_global.cpp
src/smpi/internals/smpi_memory.cpp

index f6f2208..4792772 100644 (file)
@@ -97,6 +97,7 @@ XBT_PRIVATE void smpi_switch_data_segment(simgrid::s4u::ActorPtr actor);
 XBT_PRIVATE void smpi_really_switch_data_segment(simgrid::s4u::ActorPtr actor);
 XBT_PRIVATE int smpi_is_privatization_file(char* file);
 
+XBT_PRIVATE void smpi_prepare_global_memory_segment();
 XBT_PRIVATE void smpi_backup_global_memory_segment();
 XBT_PRIVATE void smpi_destroy_global_memory_segments();
 XBT_PRIVATE void smpi_bench_destroy();
index 79c7a6e..edfc750 100644 (file)
@@ -549,6 +549,8 @@ int smpi_main(const char* executable, int argc, char *argv[])
     };
   }
   else {
+    if (smpi_privatize_global_variables == SmpiPrivStrategies::Mmap)
+      smpi_prepare_global_memory_segment();
     // Load the dynamic library and resolve the entry point:
     void* handle = dlopen(executable, RTLD_LAZY | RTLD_LOCAL);
     if (handle == nullptr)
index 88b1ae8..d469b16 100644 (file)
@@ -3,6 +3,7 @@
 /* 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 <algorithm>
 #include <cerrno>
 #include <climits>
 #include <cstdint>
@@ -33,6 +34,9 @@ int smpi_data_exe_size    = 0;
 SmpiPrivStrategies smpi_privatize_global_variables;
 static void* smpi_data_exe_copy;
 
+// Initialized by smpi_prepare_global_memory_segment().
+static std::vector<simgrid::xbt::VmMap> initial_vm_map;
+
 // We keep a copy of all the privatization regions: We can then delete everything easily by iterating over this
 // collection and nothing can be leaked. We could also iterate over all actors but we would have to be diligent when two
 // actors use the same privatization region (so, smart pointers would have to be used etc.)
@@ -42,6 +46,13 @@ static std::deque<s_smpi_privatization_region_t> smpi_privatization_regions;
 static constexpr int PROT_RWX = PROT_READ | PROT_WRITE | PROT_EXEC;
 static constexpr int PROT_RW  = PROT_READ | PROT_WRITE;
 
+/** Take a snapshot of the process' memory map.
+ */
+void smpi_prepare_global_memory_segment()
+{
+  initial_vm_map = simgrid::xbt::get_memory_map(getpid());
+}
+
 static void smpi_get_executable_global_size()
 {
   char buffer[PATH_MAX];
@@ -58,13 +69,17 @@ static void smpi_get_executable_global_size()
     if (i->pathname == full_name && (i->prot & PROT_RWX) == PROT_RW) {
       smpi_data_exe_start = (char*)i->start_addr;
       smpi_data_exe_size  = i->end_addr - i->start_addr;
-      ++i;
       /* Here we are making the assumption that a suitable empty region
          following the rw- area is the end of the data segment. It would
          be better to check with the size of the data segment. */
+      ++i;
       if (i != map.end() && i->pathname.empty() && (i->prot & PROT_RWX) == PROT_RW &&
           (char*)i->start_addr == smpi_data_exe_start + smpi_data_exe_size) {
-        smpi_data_exe_size = (char*)i->end_addr - smpi_data_exe_start;
+        // Only count this region if it was not already present in the initial map.
+        auto found = std::find_if(begin(initial_vm_map), end(initial_vm_map),
+                                  [&i](const simgrid::xbt::VmMap& m) { return m.start_addr == i->start_addr; });
+        if (found == end(initial_vm_map))
+          smpi_data_exe_size = (char*)i->end_addr - smpi_data_exe_start;
       }
       return;
     }
@@ -142,6 +157,8 @@ void smpi_backup_global_memory_segment()
 {
   xbt_assert(HAVE_PRIVATIZATION, "You are trying to use privatization on a system that does not support it. Don't.");
   smpi_get_executable_global_size();
+  initial_vm_map.clear();
+  initial_vm_map.shrink_to_fit();
 
   XBT_DEBUG("bss+data segment found : size %d starting at %p", smpi_data_exe_size, smpi_data_exe_start);