Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Infrastructure for statically defined tracepoints
[simgrid.git] / src / mc / mc_compare.cpp
index ada39e6..0958d2d 100644 (file)
@@ -4,14 +4,22 @@
 /* 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. */
 
+#define __STDC_FORMAT_MACROS
 #include <inttypes.h>
 #include <boost/unordered_set.hpp>
 
+#include "internal_config.h"
 #include "mc_private.h"
 
+#ifdef HAVE_SMPI
+#include "smpi/private.h"
+#endif
+
 #include "xbt/mmalloc.h"
 #include "xbt/mmalloc/mmprivate.h"
 
+#include <xbt/probes.h>
+
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_compare, mc,
                                 "Logging specific to mc_compare");
 
@@ -86,6 +94,7 @@ static int add_compared_pointers(mc_compare_state& state, void *p1, void *p2)
 }
 
 static int compare_areas_with_type(struct mc_compare_state& state,
+                                   int process_index,
                                    void* real_area1, mc_snapshot_t snapshot1, mc_mem_region_t region1,
                                    void* real_area2, mc_snapshot_t snapshot2, mc_mem_region_t region2,
                                    dw_type_t type, int pointer_level)
@@ -103,12 +112,9 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   case DW_TAG_enumeration_type:
   case DW_TAG_union_type:
   {
-    void* data1 =
-      mc_snapshot_read_region(real_area1, region1, alloca(type->byte_size), type->byte_size);
-    void* data2 =
-      mc_snapshot_read_region(real_area2, region1, alloca(type->byte_size), type->byte_size);
-    return (memcmp(data1, data2, type->byte_size) != 0);
-    break;
+    return mc_snapshot_region_memcmp(
+      real_area1, region1, real_area2, region2,
+      type->byte_size) != 0;
   }
   case DW_TAG_typedef:
   case DW_TAG_volatile_type:
@@ -148,7 +154,7 @@ static int compare_areas_with_type(struct mc_compare_state& state,
     }
     for (i = 0; i < type->element_count; i++) {
       size_t off = i * elm_size;
-      res = compare_areas_with_type(state,
+      res = compare_areas_with_type(state, process_index,
             (char*) real_area1 + off, snapshot1, region1,
             (char*) real_area2 + off, snapshot2, region2,
             type->subtype, pointer_level);
@@ -160,9 +166,8 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   case DW_TAG_reference_type:
   case DW_TAG_rvalue_reference_type:
   {
-    void* temp;
-    void* addr_pointed1 = *(void**) mc_snapshot_read_region(real_area1, region1, &temp, sizeof(void**));
-    void* addr_pointed2 = *(void**) mc_snapshot_read_region(real_area2, region2, &temp, sizeof(void**));
+    void* addr_pointed1 = mc_snapshot_read_pointer_region(real_area1, region1);
+    void* addr_pointed2 = mc_snapshot_read_pointer_region(real_area2, region2);
 
     if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
       return (addr_pointed1 != addr_pointed2);
@@ -170,6 +175,8 @@ static int compare_areas_with_type(struct mc_compare_state& state,
 
       if (addr_pointed1 == NULL && addr_pointed2 == NULL)
         return 0;
+      if (addr_pointed1 == NULL || addr_pointed2 == NULL)
+        return 1;
       if (!add_compared_pointers(state, addr_pointed1, addr_pointed2))
         return 0;
 
@@ -187,26 +194,27 @@ static int compare_areas_with_type(struct mc_compare_state& state,
              && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)))
           return 1;
         // The pointers are both in the heap:
-        return compare_heap_area(addr_pointed1, addr_pointed2, snapshot1,
+        return compare_heap_area(process_index, addr_pointed1, addr_pointed2, snapshot1,
                                  snapshot2, NULL, type->subtype, pointer_level);
       }
+
       // The pointers are both in the current object R/W segment:
-      else if (addr_pointed1 > region1->start_addr
-               && (char *) addr_pointed1 <= (char *) region1->start_addr + region1->size) {
-        if (!
-            (addr_pointed2 > region2->start_addr
-             && (char *) addr_pointed2 <= (char *) region2->start_addr + region2->size))
+      else if (mc_region_contain(region1, addr_pointed1)) {
+        if (!mc_region_contain(region2, addr_pointed2))
           return 1;
         if (type->dw_type_id == NULL)
           return (addr_pointed1 != addr_pointed2);
         else {
-          return compare_areas_with_type(state,
+          return compare_areas_with_type(state, process_index,
                                          addr_pointed1, snapshot1, region1,
                                          addr_pointed2, snapshot2, region2,
                                          type->subtype, pointer_level);
         }
       }
 
+      // TODO, We do not handle very well the case where
+      // it belongs to a different (non-heap) region from the current one.
+
       else {
         return (addr_pointed1 != addr_pointed2);
       }
@@ -217,13 +225,13 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   case DW_TAG_class_type:
     xbt_dynar_foreach(type->members, cursor, member) {
       void *member1 =
-        mc_member_resolve(real_area1, type, member, snapshot1);
+        mc_member_resolve(real_area1, type, member, snapshot1, process_index);
       void *member2 =
-        mc_member_resolve(real_area2, type, member, snapshot2);
-      mc_mem_region_t subregion1 = mc_get_region_hinted(member1, snapshot1, region1);
-      mc_mem_region_t subregion2 = mc_get_region_hinted(member2, snapshot2, region2);
+        mc_member_resolve(real_area2, type, member, snapshot2, process_index);
+      mc_mem_region_t subregion1 = mc_get_region_hinted(member1, snapshot1, process_index, region1);
+      mc_mem_region_t subregion2 = mc_get_region_hinted(member2, snapshot2, process_index, region2);
       res =
-          compare_areas_with_type(state,
+          compare_areas_with_type(state, process_index,
                                   member1, snapshot1, subregion1,
                                   member2, snapshot2, subregion2,
                                   member->subtype, pointer_level);
@@ -242,12 +250,13 @@ static int compare_areas_with_type(struct mc_compare_state& state,
   return 0;
 }
 
-static int compare_global_variables(int region_type, mc_mem_region_t r1,
+static int compare_global_variables(mc_object_info_t object_info,
+                                    int process_index,
+                                    mc_mem_region_t r1,
                                     mc_mem_region_t r2, mc_snapshot_t snapshot1,
                                     mc_snapshot_t snapshot2)
 {
-  xbt_assert(r1 && r2,
-    "Missing region. Did you enable SMPI privatisation? It is not compatible with state comparison.");
+  xbt_assert(r1 && r2, "Missing region.");
   struct mc_compare_state state;
 
   xbt_dynar_t variables;
@@ -255,12 +264,6 @@ static int compare_global_variables(int region_type, mc_mem_region_t r1,
   unsigned int cursor = 0;
   dw_variable_t current_var;
 
-  mc_object_info_t object_info = NULL;
-  if (region_type == 2) {
-    object_info = mc_binary_info;
-  } else {
-    object_info = mc_libsimgrid_info;
-  }
   variables = object_info->global_variables;
 
   xbt_dynar_foreach(variables, cursor, current_var) {
@@ -274,11 +277,12 @@ static int compare_global_variables(int region_type, mc_mem_region_t r1,
 
     dw_type_t bvariable_type = current_var->type;
     res =
-        compare_areas_with_type(state,
+        compare_areas_with_type(state, process_index,
                                 (char *) current_var->address, snapshot1, r1,
                                 (char *) current_var->address, snapshot2, r2,
                                 bvariable_type, 0);
     if (res == 1) {
+      XBT_TRACE3(mc, global_diff, -1, -1, current_var->name);
       XBT_VERB("Global variable %s (%p) is different between snapshots",
                current_var->name, (char *) current_var->address);
       return 1;
@@ -290,7 +294,8 @@ static int compare_global_variables(int region_type, mc_mem_region_t r1,
 
 }
 
-static int compare_local_variables(mc_snapshot_t snapshot1,
+static int compare_local_variables(int process_index,
+                                   mc_snapshot_t snapshot1,
                                    mc_snapshot_t snapshot2,
                                    mc_snapshot_stack_t stack1,
                                    mc_snapshot_stack_t stack2)
@@ -327,13 +332,14 @@ static int compare_local_variables(mc_snapshot_t snapshot1,
 
         dw_type_t subtype = current_var1->type;
         res =
-            compare_areas_with_type(state,
-                                    current_var1->address, snapshot1, mc_get_snapshot_region(current_var1->address, snapshot1),
-                                    current_var2->address, snapshot2, mc_get_snapshot_region(current_var2->address, snapshot2),
+            compare_areas_with_type(state, process_index,
+                                    current_var1->address, snapshot1, mc_get_snapshot_region(current_var1->address, snapshot1, process_index),
+                                    current_var2->address, snapshot2, mc_get_snapshot_region(current_var2->address, snapshot2, process_index),
                                     subtype, 0);
 
       if (res == 1) {
         // TODO, fix current_varX->subprogram->name to include name if DW_TAG_inlined_subprogram
+        XBT_TRACE3(mc, local_diff, -1, -1, current_var1->name);
         XBT_VERB
             ("Local variable %s (%p - %p) in frame %s  is different between snapshots",
              current_var1->name, current_var1->address, current_var2->address,
@@ -380,6 +386,7 @@ int snapshot_compare(void *state1, void *state2)
   if (_sg_mc_hash) {
     hash_result = (s1->hash != s2->hash);
     if (hash_result) {
+      XBT_TRACE2(mc, hash_diff, num1, num2);
       XBT_VERB("(%d - %d) Different hash : 0x%" PRIx64 "--0x%" PRIx64, num1,
                num2, s1->hash, s2->hash);
 #ifndef MC_DEBUG
@@ -394,8 +401,11 @@ int snapshot_compare(void *state1, void *state2)
   unsigned int cursor;
   int pid;
   xbt_dynar_foreach(s1->enabled_processes, cursor, pid){
-    if(!xbt_dynar_member(s2->enabled_processes, &pid))
+    if(!xbt_dynar_member(s2->enabled_processes, &pid)) {
+      //XBT_TRACE3(mc, state_diff, num1, num2, "Different enabled processes");
       XBT_VERB("(%d - %d) Different enabled processes", num1, num2);
+      // return 1; ??
+    }
   }
 
   unsigned long i = 0;
@@ -422,6 +432,7 @@ int snapshot_compare(void *state1, void *state2)
       XBT_VERB("(%d - %d) Different size used in stacks : %zu - %zu", num1,
                num2, size_used1, size_used2);
 #endif
+      XBT_TRACE3(mc, state_diff, num1, num2, "Different stack size");
 
       xbt_os_walltimer_stop(timer);
       xbt_os_timer_free(timer);
@@ -442,9 +453,9 @@ int snapshot_compare(void *state1, void *state2)
 #endif
 
   /* Init heap information used in heap comparison algorithm */
-  xbt_mheap_t heap1 = (xbt_mheap_t) mc_snapshot_read(std_heap, s1,
+  xbt_mheap_t heap1 = (xbt_mheap_t) mc_snapshot_read(std_heap, s1, MC_NO_PROCESS_INDEX,
     alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
-  xbt_mheap_t heap2 = (xbt_mheap_t) mc_snapshot_read(std_heap, s2,
+  xbt_mheap_t heap2 = (xbt_mheap_t) mc_snapshot_read(std_heap, s2, MC_NO_PROCESS_INDEX,
     alloca(sizeof(struct mdesc)), sizeof(struct mdesc));
   res_init = init_heap_information(heap1, heap2, s1->to_ignore, s2->to_ignore);
   if (res_init == -1) {
@@ -453,6 +464,7 @@ int snapshot_compare(void *state1, void *state2)
     errors++;
 #else
 #ifdef MC_VERBOSE
+    XBT_TRACE3(mc, state_diff, num1, num2, "Different heap information");
     XBT_VERB("(%d - %d) Different heap information", num1, num2);
 #endif
 
@@ -474,7 +486,6 @@ int snapshot_compare(void *state1, void *state2)
   is_diff = 0;
 #endif
   mc_snapshot_stack_t stack1, stack2;
-
   while (cursor < xbt_dynar_length(s1->stacks)) {
     stack1 =
         (mc_snapshot_stack_t) xbt_dynar_get_as(s1->stacks, cursor,
@@ -482,9 +493,16 @@ int snapshot_compare(void *state1, void *state2)
     stack2 =
         (mc_snapshot_stack_t) xbt_dynar_get_as(s2->stacks, cursor,
                                                mc_snapshot_stack_t);
-    diff_local =
-        compare_local_variables(s1, s2, stack1, stack2);
+
+    if (stack1->process_index != stack2->process_index) {
+      diff_local = 1;
+      XBT_DEBUG("(%d - %d) Stacks with different process index (%i vs %i)", num1, num2,
+        stack1->process_index, stack2->process_index);
+    }
+    else diff_local =
+        compare_local_variables(stack1->process_index, s1, s2, stack1, stack2);
     if (diff_local > 0) {
+      XBT_TRACE3(mc, state_diff, num1, num2, "Different local variables");
 #ifdef MC_DEBUG
       if (is_diff == 0) {
         xbt_os_walltimer_stop(timer);
@@ -525,6 +543,8 @@ int snapshot_compare(void *state1, void *state2)
   };
 #endif
 
+  mc_object_info_t object_infos[] = { NULL, mc_libsimgrid_info, mc_binary_info };
+
   int k = 0;
   for (k = 2; k != 0; --k) {
 #ifdef MC_DEBUG
@@ -534,9 +554,23 @@ int snapshot_compare(void *state1, void *state2)
 #endif
 
     /* Compare global variables */
-    is_diff =
-        compare_global_variables(k, s1->regions[k], s2->regions[k], s1, s2);
+#ifdef HAVE_SMPI
+    if (object_infos[k] == mc_binary_info && smpi_privatize_global_variables) {
+      // Compare the global variables separately for each simulates process:
+      for (int process_index = 0; process_index < smpi_process_count(); process_index++) {
+        is_diff =
+          compare_global_variables(object_infos[k], process_index,
+            s1->privatization_regions[process_index], s2->privatization_regions[process_index], s1, s2);
+        if (is_diff) break;
+      }
+    }
+    else
+#endif
+      is_diff =
+        compare_global_variables(object_infos[k], MC_NO_PROCESS_INDEX, s1->regions[k], s2->regions[k], s1, s2);
+
     if (is_diff != 0) {
+      XBT_TRACE3(mc, state_diff, num1, num2, "Different global variables");
 #ifdef MC_DEBUG
       xbt_os_walltimer_stop(timer);
       *times[k] = xbt_os_timer_elapsed(timer);
@@ -567,6 +601,7 @@ int snapshot_compare(void *state1, void *state2)
 
   /* Compare heap */
   if (mmalloc_compare_heap(s1, s2) > 0) {
+    XBT_TRACE3(mc, state_diff, num1, num2, "Different heap");
 
 #ifdef MC_DEBUG
     xbt_os_walltimer_stop(timer);
@@ -652,7 +687,7 @@ void print_comparison_times()
 /**************************** MC snapshot compare simcall **************************/
 /***********************************************************************************/
 
-int SIMIX_pre_mc_compare_snapshots(smx_simcall_t simcall,
+int simcall_HANDLER_mc_compare_snapshots(smx_simcall_t simcall,
                                    mc_snapshot_t s1, mc_snapshot_t s2)
 {
   return snapshot_compare(s1, s2);