region newsubregion(region parent) { // fprintf(stderr, "## newsubregion\n"); char *first; region r; first = (char *)alloc_single_page(NULL); preclear(first + PAGE_HEADER_SIZE, RPAGESIZE - PAGE_HEADER_SIZE); #ifdef STAGGER_RSTART /* stagger regions across cache lines a bit */ rstart += 64; #if RPAGESIZE < 1024 #error RPAGESIZE must be at least 1024, or change the next if. #endif if (rstart >= 16 * 64) rstart = 0; #endif r = (region)(first + rstart + PAGE_HEADER_SIZE); VALGRIND_MAKE_WRITABLE(r, sizeof(*r)); postclear(r, sizeof *r); initregion(r); if (parent) link_region(r, parent); // fprintf(stderr, "## create mempool %p\n", r); VALGRIND_CREATE_MEMPOOL(r, 0, 0); ++num_regions_active; ++num_regions_created; return r; }
// recursively propagate descendent count and max depth upwards // r->visit_counter is incremented each time we have an opportunity // to traverse to a parent. we only actually visit it once the visit // counter reaches adjacent_region_count - 1 i.e. that we have already // visited all of its other children // as we travel upwards we collect nodes with the constraints defined by // min_target_root_descendent_count, max_target_root_descendent_count, // min_depth and max_depth // we never traverse above a node which exceeds these constraints. we also // never traverse nodes which are saturated or fragmented because it is // ambiguous whether such a node has a parent, or if all it's children are // attched, and we can't determine this in a single pass (we could save a list // of these nodes for a later pass but we don't bother.) // during the calls to this function we store the maximum leaf-to-node depth // in r->depth, later this field has a different meaning static void propagate_descendent_count_and_max_depth_upwards( Segmenter *s, Region *r, FidtrackerX *ft) { int i; Region *parent = 0; assert( r->level == NOT_TRAVERSED ); assert( r->children_visited_count == (r->adjacent_region_count - 1) // has an untraversed parent || r->children_visited_count == r->adjacent_region_count ); // is adjacent to root region r->descendent_count = 0; r->depth = 0; r->level = TRAVERSING; for( i=0; i < r->adjacent_region_count; ++i ){ Region *adjacent = r->adjacent_regions[i]; assert( r1_adjacent_contains_r2( adjacent, r ) ); if( adjacent->level == TRAVERSED ){ r->descendent_count += (short)(adjacent->descendent_count + 1); r->depth = (short)MAX( r->depth, (adjacent->depth + 1) ); }else{ assert( parent == 0 ); parent = adjacent; } } r->level = TRAVERSED; if( r->descendent_count == ft->max_target_root_descendent_count && r->depth >= ft->min_depth && r->depth <= ft->max_depth ){ // found fiducial candidate link_region( &ft->root_regions_head, r ); }else{ if( r->descendent_count >= ft->min_target_root_descendent_count && r->descendent_count < ft->max_target_root_descendent_count && r->depth >= ft->min_depth && r->depth <= ft->max_depth ) { link_region( &ft->root_regions_head, r ); } else if( r->descendent_count >= ft->min_target_root_descendent_count-3 && r->descendent_count < ft->max_target_root_descendent_count+3 && r->depth >= ft->min_depth-1 && r->depth <= ft->max_depth+1 ) { r->flags |= LOST_SYMBOL_FLAG; link_region( &ft->root_regions_head, r ); } if( parent && !(r->flags & ( SATURATED_REGION_FLAG | ADJACENT_TO_ROOT_REGION_FLAG | FREE_REGION_FLAG ) ) ){ ++parent->children_visited_count; if( r->descendent_count < ft->max_target_root_descendent_count && r->depth < ft->max_depth ){ // continue propagating depth and descendent count upwards // so long as parent isn't a saturated node in which case it is // ambiguous whether parent has a parent or not so we skip it if( !(parent->flags & SATURATED_REGION_FLAG) && ( ( (!(parent->flags & (ADJACENT_TO_ROOT_REGION_FLAG | FRAGMENTED_REGION_FLAG) ) && parent->children_visited_count == (parent->adjacent_region_count - 1)) || ((parent->flags & (ADJACENT_TO_ROOT_REGION_FLAG | FRAGMENTED_REGION_FLAG) ) && parent->children_visited_count == parent->adjacent_region_count) ) ) ){ assert( r1_adjacent_contains_r2( r, parent ) ); assert( r1_adjacent_contains_r2( parent, r ) ); propagate_descendent_count_and_max_depth_upwards( s, parent, ft); } } } } }