#include <inttypes.h>
#include <boost/unordered_set.hpp>
+#include "internal_config.h"
+#include "mc_object_info.h"
+#include "mc_safety.h"
+#include "mc_liveness.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");
}
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)
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:
}
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);
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);
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;
&& 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);
}
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);
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.");
+
+#ifdef HAVE_SMPI
+ if (r1->storage_type == MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+ xbt_assert(process_index >= 0);
+ if (r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED) {
+ return 1;
+ }
+
+ size_t process_count = smpi_process_count();
+ xbt_assert(process_count == r1->privatized.regions_count
+ && process_count == r2->privatized.regions_count);
+
+ // 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],
+ snapshot1, snapshot2);
+ if (is_diff) return 1;
+ }
+ return 0;
+ }
+#else
+ xbt_assert(r1->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED);
+#endif
+ xbt_assert(r2->storage_type != MC_REGION_STORAGE_TYPE_PRIVATIZED);
+
struct mc_compare_state state;
xbt_dynar_t variables;
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) {
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;
}
-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)
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,
int snapshot_compare(void *state1, void *state2)
{
-
mc_snapshot_t s1, s2;
int num1, num2;
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
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;
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);
#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) {
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
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,
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);
};
#endif
- int k = 0;
- for (k = 2; k != 0; --k) {
+ size_t regions_count = s1->snapshot_regions_count;
+ // TODO, raise a difference instead?
+ xbt_assert(regions_count == s2->snapshot_regions_count);
+
+ for (size_t k = 0; k != regions_count; ++k) {
+ mc_mem_region_t region1 = s1->snapshot_regions[k];
+ mc_mem_region_t region2 = s2->snapshot_regions[k];
+
+ // Preconditions:
+ if (region1->region_type != MC_REGION_TYPE_DATA)
+ continue;
+
+ xbt_assert(region1->region_type == region2->region_type);
+ xbt_assert(region1->object_info == region2->object_info);
+
+ xbt_assert(region1->object_info);
#ifdef MC_DEBUG
if (is_diff == 0)
xbt_os_walltimer_stop(timer);
/* Compare global variables */
is_diff =
- compare_global_variables(k, s1->regions[k], s2->regions[k], s1, s2);
+ compare_global_variables(region1->object_info, MC_NO_PROCESS_INDEX,
+ region1, region2,
+ 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);
/* 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);
/**************************** 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);