Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch mc into mc-perf
authorGabriel Corona <gabriel.corona@loria.fr>
Fri, 7 Feb 2014 12:16:09 +0000 (13:16 +0100)
committerGabriel Corona <gabriel.corona@loria.fr>
Fri, 7 Feb 2014 13:27:47 +0000 (14:27 +0100)
1  2 
src/mc/mc_checkpoint.c
src/mc/mc_compare.c
src/mc/mc_dwarf.c
src/mc/mc_global.c
src/mc/mc_hash.c
src/mc/mc_private.h
src/xbt/mmalloc/mm_diff.c

Simple merge
@@@ -285,13 -283,14 +283,14 @@@ static int compare_global_variables(in
      // If the variable is not in this object, skip it:
      // We do not expect to find a pointer to something which is not reachable
      // by the global variables.
 -    if((char*) current_var->address.address < (char*) object_info->start_rw
 -      || (char*) current_var->address.address > (char*) object_info->end_rw)
 +    if((char*) current_var->address < (char*) object_info->start_rw
 +      || (char*) current_var->address > (char*) object_info->end_rw)
         continue;
  
 -    offset = (char *)current_var->address.address - (char *)object_info->start_rw;
 +    offset = (char *)current_var->address - (char *)object_info->start_rw;
  
-     res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, types, other_types, current_var->type_origin, r1->size, region_type, start_data, 0);
+     dw_type_t bvariable_type = xbt_dict_get_or_null(object_info->types, current_var->type_origin);
+     res = compare_areas_with_type((char *)r1->data + offset, (char *)r2->data + offset, object_info, other_object_info, bvariable_type, r1->size, region_type, start_data, 0);
      if(res == 1){
        XBT_VERB("Global variable %s (%p - %p) is different between snapshots", current_var->name, (char *)r1->data + offset, (char *)r2->data + offset);
        xbt_dynar_free(&compared_pointers);
Simple merge
Simple merge
index 0000000,5bba2ff..4f74676
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,371 +1,371 @@@
 -    const char* address = variable->address.address;
+ /* Copyright (c) 2014. The SimGrid Team.
+  * All rights reserved.                                                     */
+ /* 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 <stdint.h>
+ #include <stdbool.h>
+ #include "mc_private.h"
+ #include "mc/datatypes.h"
+ #include <mc/mc.h>
+ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_hash, mc,
+                                 "Logging specific to mc_hash");
+ // This is djb2:
+ typedef uint64_t mc_hash_t;
+ #define MC_HASH_INIT ((uint64_t)5381)
+ // #define MC_HASH(hash, value) hash = (((hash << 5) + hash) + (uint64_t) value)
+ #define MC_HASH(hash, value) \
+   { hash = (((hash << 5) + hash) + (uint64_t) value);\
+   XBT_DEBUG("%s:%i: %"PRIx64" -> %"PRIx64, __FILE__, __LINE__, (uint64_t) value, hash); }
+ // ***** Hash state
+ typedef struct s_mc_hashing_state {
+   // Set of pointers/addresses already processed (avoid loops):
+   mc_address_set_t handled_addresses;
+ } mc_hashing_state;
+ void mc_hash_state_init(mc_hashing_state* state);
+ void mc_hash_state_destroy(mc_hashing_state* state);
+ void mc_hash_state_init(mc_hashing_state* state) {
+   state->handled_addresses = mc_address_set_new();
+ }
+ void mc_hash_state_destroy(mc_hashing_state* state) {
+    mc_address_set_free(&state->handled_addresses);
+ }
+ // TODO, detect and avoid loops
+ static bool mc_ignored(const void* address, size_t size) {
+   mc_heap_ignore_region_t region;
+   unsigned int cursor = 0;
+   const void* end = (char*) address + size;
+   xbt_dynar_foreach(mc_heap_comparison_ignore, cursor, region) {
+    void* istart = region->address;
+    void* iend   = (char*) region->address + region->size;
+    if(address>=istart && address<iend && end>=istart && end<iend)
+      return true;
+   }
+   return false;
+ }
+ static void mc_hash_binary(mc_hash_t *hash, const void* s, size_t len) {
+   const char* p = (const void*) s;
+   int i;
+   for(i=0; i!=len; ++i) {
+     MC_HASH(*hash, p[i]);
+   }
+ }
+ /** \brief Compute a hash for a given value of a given type
+  *
+  *  We try to be very conservative (do not hash too ambiguous things).
+  *
+  *  \param address address of the variable
+  *  \param type type of the variable
+  * */
+ static void mc_hash_value(mc_hash_t* hash, mc_hashing_state* state, mc_object_info_t info, const void* address, dw_type_t type) {
+   top:
+   switch(type->type){
+   // Simple case, hash this has binary:
+   case DW_TAG_base_type:
+   case DW_TAG_enumeration_type:
+   {
+     if(mc_ignored(address, 1))
+       return;
+     mc_hash_binary(hash, address, type->byte_size);
+     return;
+   }
+   case DW_TAG_array_type:
+   {
+     if(mc_ignored(address, type->byte_size))
+       return;
+     long element_count = type->element_count;
+     dw_type_t subtype = type->subtype;
+     if(subtype==NULL) {
+       XBT_DEBUG("Hash array without subtype");
+       return;
+     }
+     int i;
+     for(i=0; i!=element_count; ++i) {
+       XBT_DEBUG("Hash array element %i", i);
+       void* subaddress = ((char*)address)+i*subtype->byte_size;
+       mc_hash_value(hash, state, info, subaddress, subtype);
+     }
+     return;
+   }
+   // Get the raw type:
+   case DW_TAG_typedef:
+   case DW_TAG_volatile_type:
+   case DW_TAG_const_type:
+   case DW_TAG_restrict_type:
+   {
+     type = type->subtype;
+     if(type==NULL)
+       return;
+     else
+       goto top;
+   }
+   case DW_TAG_structure_type:
+   case DW_TAG_class_type:
+   {
+     if(mc_ignored(address, type->byte_size))
+       return;
+     unsigned int cursor = 0;
+     dw_type_t member;
+     xbt_dynar_foreach(type->members, cursor, member){
+       XBT_DEBUG("Hash struct member %s", member->name);
+       if(type->subtype==NULL)
+         return;
+        mc_hash_value(hash, state, info, ((char*)address) + member->offset, type->subtype);
+     }
+     return;
+   }
+   // Pointer, we hash a single value but it might be an array.
+   case DW_TAG_pointer_type:
+   case DW_TAG_reference_type:
+   case DW_TAG_rvalue_reference_type:
+   {
+     if(mc_ignored(address, 1))
+       return;
+     void* pointed = *(void**)address;
+     if(pointed==NULL) {
+       XBT_DEBUG("Hashed pinter is NULL");
+       return;
+     }
+     // Avoid loops:
+     if(mc_address_test(state->handled_addresses, pointed)) {
+       XBT_DEBUG("Hashed pointed data %p already hashed", pointed);
+       return;
+     }
+     mc_address_add(state->handled_addresses, pointed);
+     // Anything outside the R/W segments and the heap is not hashed:
+     bool valid_pointer = (pointed >= (void*) mc_binary_info->start_rw && pointed <= (void*) mc_binary_info->end_rw)
+         || (pointed >= (void*) mc_libsimgrid_info->start_rw && pointed <= (void*) mc_libsimgrid_info->end_rw)
+         || (pointed >= std_heap && pointed < (void*) ((const char*)std_heap + STD_HEAP_SIZE));
+     if(!valid_pointer) {
+       XBT_DEBUG("Hashed pointed data %p is in an ignored range", pointed);
+       return;
+     }
+     if(type->subtype==NULL) {
+       XBT_DEBUG("Missing type for %p (type=%s)", pointed, type->dw_type_id);
+       return;
+     }
+     address = pointed;
+     type = type->subtype;
+     goto top;
+   }
+   // Skip this:
+   case DW_TAG_union_type:
+   case DW_TAG_subroutine_type:
+   default:
+     return;
+   }
+ }
+ static void mc_hash_object_globals(mc_hash_t *hash, mc_hashing_state* state, mc_object_info_t info) {
+   unsigned int cursor = 0;
+   dw_variable_t variable;
+   xbt_dynar_foreach(info->global_variables, cursor, variable) {
+     XBT_DEBUG("Hash global variable %s", variable->name);
+     if(variable->type_origin == NULL) {
+       // Nothing
+       continue;
+     }
+     dw_type_t type = xbt_dict_get_or_null(info->types, variable->type_origin);
+     if(type==NULL) {
+       // Nothing
+       continue;
+     }
 -    mc_hash_value(hash, state, info, variable->address.address, type);
++    const char* address = variable->address;
+     bool valid_pointer = (address >= mc_binary_info->start_rw && address <= mc_binary_info->end_rw)
+         || (address >= mc_libsimgrid_info->start_rw && address <= mc_libsimgrid_info->end_rw)
+         || (address >= (const char*) std_heap && address < (const char *)std_heap + STD_HEAP_SIZE);
+     if(!valid_pointer) continue;
 -    if(variable->address.location == NULL) {
++    mc_hash_value(hash, state, info, variable->address, type);
+   }
+ }
+ static void mc_hash_stack_frame(
+   mc_hash_t *hash,
+     mc_object_info_t info, unw_cursor_t* unw_cursor, dw_frame_t frame, char* frame_pointer, mc_hashing_state* state
+     ) {
+   // return; // TEMP
+   unsigned int cursor = 0;
+   dw_variable_t variable;
+   xbt_dynar_foreach(frame->variables, cursor, variable){
+     if(variable->type_origin==NULL) {
+       XBT_DEBUG("Hash local variable %s without type", variable->name);
+       continue;
+     }
 -    void* variable_address = (void*) MC_dwarf_resolve_location(unw_cursor, variable->address.location, frame_pointer);
++    if(variable->location == NULL) {
+       XBT_DEBUG("Hash local variable %s without location", variable->name);
+       continue;
+     }
+     XBT_DEBUG("Hash local variable %s", variable->name);
++    void* variable_address = (void*) MC_dwarf_resolve_location(unw_cursor, variable->location, frame_pointer);
+     dw_type_t type = xbt_dict_get_or_null(info->types, variable->type_origin);
+     if(type==NULL) {
+       XBT_DEBUG("Hash local variable %s without loctypeation", variable->name);
+       continue;
+     }
+     mc_hash_value(hash, state, info, variable_address, type);
+   }
+ }
+ /** \brief Find the frame base of a given frame
+  *
+  *  \param ip         Instruction pointer
+  *  \param frame
+  *  \param unw_cursor
+  */
+ void* mc_find_frame_base(unw_word_t ip, dw_frame_t frame, unw_cursor_t* unw_cursor) {
+   switch(frame->frame_base->type) {
+   case e_dw_loclist:
+   {
+     int loclist_cursor;
+     for(loclist_cursor=0; loclist_cursor < xbt_dynar_length(frame->frame_base->location.loclist); loclist_cursor++){
+       dw_location_entry_t entry = xbt_dynar_get_as(frame->frame_base->location.loclist, loclist_cursor, dw_location_entry_t);
+       if((ip >= entry->lowpc) && (ip < entry->highpc)){
+         return (void*) MC_dwarf_resolve_location(unw_cursor, entry->location, NULL);
+       }
+     }
+     return NULL;
+   }
+   // Not handled:
+   default:
+     return NULL;
+   }
+ }
+ static void mc_hash_stack(mc_hash_t *hash, stack_region_t stack, mc_hashing_state* state) {
+   unw_cursor_t cursor;
+   if(unw_init_local(&cursor, (unw_context_t *)stack->context)){
+     xbt_die("unw_init_local failed");
+   }
+   MC_HASH(*hash, (long)stack->address);
+   long count = 0;
+   int ret;
+   for(ret=1; ret >= 0; ret = unw_step(&cursor)) {
+     // Find the frame name:
+     unw_word_t off;
+     char frame_name[256];
+     if(unw_get_proc_name(&cursor, frame_name, sizeof (frame_name), &off)!=0) {
+       continue;
+     }
+     XBT_DEBUG("Frame #%i %s", (int) count, frame_name);
+     // Stop before context switch with maestro
+     if(!strcmp(frame_name, "smx_ctx_sysv_wrapper")) {
+       break;
+     }
+     ++count;
+     unw_word_t ip, sp;
+     if(unw_get_reg(&cursor, UNW_REG_IP, &ip))
+       continue;
+     if(unw_get_reg(&cursor, UNW_REG_SP, &sp))
+       continue;
+     MC_HASH(*hash, ip);
+     // Find the object info:
+     mc_object_info_t info;
+     if((long)ip >= (long) mc_libsimgrid_info->start_exec && (long)ip < (long) mc_libsimgrid_info->end_exec)
+       info = mc_libsimgrid_info;
+     else if((long)ip >= (long) mc_binary_info->start_exec && (long)ip < (long) mc_binary_info->end_exec)
+       info = mc_binary_info;
+     else
+       continue;
+     // Find the frame:
+     dw_frame_t frame = xbt_dict_get_or_null(info->local_variables, frame_name);
+     if(frame==NULL)
+       continue;
+     long true_ip = (long)frame->low_pc + (long)off;
+     // Find the fame base:
+     void* frame_base = mc_find_frame_base(true_ip, frame, &cursor);
+     if(frame_base==NULL)
+       continue;
+     mc_hash_stack_frame(hash, info, &cursor, frame, frame_base, state);
+   }
+   MC_HASH(*hash, count);
+ }
+ static void mc_hash_stacks(mc_hash_t *hash, mc_hashing_state* state) {
+   unsigned int cursor = 0;
+   stack_region_t current_stack;
+   MC_HASH(*hash, xbt_dynar_length(stacks_areas));
+   int i=0;
+   xbt_dynar_foreach(stacks_areas, cursor, current_stack){
+     XBT_DEBUG("Stack %i", i);
+     mc_hash_stack(hash, current_stack, state);
+     ++i;
+   }
+ }
+ uint64_t mc_hash_processes_state(int num_state) {
+   XBT_DEBUG("START hash %i", num_state);
+   mc_hashing_state state;
+   mc_hash_state_init(&state);
+   mc_hash_t hash = MC_HASH_INIT;
+   MC_HASH(hash, xbt_swag_size(simix_global->process_list)); // process count
+   mc_hash_object_globals(&hash, &state, mc_binary_info);
+   // mc_hash_object_globals(&hash, &state, mc_libsimgrid_info);
+   mc_hash_stacks(&hash, &state);
+   mc_hash_state_destroy(&state);
+   XBT_DEBUG("END hash %i", num_state);
+   return hash;
+ }
Simple merge
@@@ -1028,19 -1016,19 +1016,19 @@@ int compare_heap_area(void *area1, void
    real_addr_block2 = ((void*) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
  
    if(type_id){
-     type = xbt_dict_get_or_null(all_types, type_id);
+     type = xbt_dict_get_or_null(info->types, type_id);
      if(type->byte_size == 0){
-       if(type->dw_type_id == NULL){
-         type_desc = get_type_description(all_types, type->name);
-         if(type_desc)
-           type = xbt_dict_get_or_null(all_types, type_desc);
+       if(type->subtype == NULL){
+         dw_type_t full_type = xbt_dict_get_or_null(info->types_by_name, type->name);
+         if(full_type)
+           type = full_type;
          else
-           type = xbt_dict_get_or_null(other_types, get_type_description(other_types, type->name));
+           type = xbt_dict_get_or_null(other_info->types_by_name, type->name);
        }else{
-         type = xbt_dict_get_or_null(all_types, type->dw_type_id);
+         type = type->subtype;
        }
      }
 -    if((type->byte_size == DW_TAG_pointer_type) || ((type->type == DW_TAG_base_type) && (!strcmp(type->name, "char"))))
 +    if((type->byte_size == DW_TAG_pointer_type) || ((type->type == DW_TAG_base_type) && type->name!=NULL && (!strcmp(type->name, "char"))))
        type_size = -1;
      else
        type_size = type->byte_size;