void push(const Value& v) { size_type index = data.size(); data.push_back(v); put(index_in_heap, v, index); preserve_heap_property_up(index); verify_heap(); }
static void test_insert_out_of_memory (void) { BinomialHeap* heap; int i; /* There are various memory allocations performed during the insert; * probe at different limit levels to catch them all. */ for (i = 0; i < 6; ++i) { heap = generate_heap(); /* Insert should fail */ alloc_test_set_limit (i); test_array[TEST_VALUE] = TEST_VALUE; assert (binomial_heap_insert (heap, &test_array[TEST_VALUE]) == 0); alloc_test_set_limit (-1); /* Check that the heap is unharmed */ verify_heap (heap); binomial_heap_free (heap); } }
void long_freelist() { Busy_Header* b[20]; for(int i = 0; i < 20; i++){ b[i] = malloc(i); assert_addr_equal(get_freelist(), find_next(b[i])); assert_addr_equal(get_freelist()->prev, NULL); } Free_Header *freelist0 = get_freelist(); for( int i = 0; i <20 ; i++){ free(b[i]); assert_addr_equal(get_freelist(), b[i]); if (i+1 < 20) assert_addr_equal(find_next(get_freelist()), b[i+1]); assert_addr_equal(get_freelist()->prev, NULL); } //last free causes a merge Heap_Info info = verify_heap(); assert_equal(info.busy, 0); assert_equal(info.free, 20); assert_equal(info.busy_size + info.free_size, get_heap_info().heap_size); // out of heap assert_addr_equal(get_freelist(), b[19]); assert_addr_equal(find_next(get_freelist()), get_heap_base() + info.heap_size); //out of heap assert_addr_equal(((Free_Header *)b[0])->next, NULL); //end }
//free the first chunk, then free last chunk to merge with the end of free list void merge_with_end() { three_malloc(); Busy_Header *b_1 = get_heap_base(); Busy_Header *b_2 = find_next(b_1); Busy_Header *b_3 = find_next(b_2); free(b_1); //free the first chunk Free_Header *freelist0 = get_freelist(); //get the new freelist assert_addr_equal(freelist0, b_1); assert_addr_equal(freelist0->next, find_next(b_3)); free(b_3); //free the last chunk, merge Free_Header *freelist1 = get_freelist(); assert_addr_equal(freelist1, b_3); assert_addr_equal(freelist1->next, b_1); assert_addr_equal(freelist1->prev, NULL); assert_addr_equal(freelist1->next->prev, freelist1); assert_addr_equal(freelist1->next->next, NULL); Heap_Info info = verify_heap(); assert_equal(info.busy, 1); assert_equal(info.free, 2); assert_equal(info.free_size, HEAP_SIZE - info.busy_size); assert_equal(freelist1->next->size, b_1->size); assert_equal(find_next(find_next(b_1)), freelist1); }
//five consecutive chunks allocated void five_malloc() { void *p = get_heap_base(); Busy_Header *b_1 = malloc(100); assert_addr_equal(b_1, p); //b_1 is at the start of heap assert_equal(chunksize(b_1), request2size(100)); Busy_Header *b_2 = malloc(200); Busy_Header *b1_next = find_next(b_1); assert_addr_equal(b1_next,b_2); //b_2 is after b_1 assert_equal(chunksize(b_2), request2size(200)); Busy_Header *b_3 = malloc(300); Busy_Header *b2_next = find_next(b_2); assert_addr_equal(find_next(b_2),b_3); //b_3 is after b_2 assert_equal(chunksize(b_3), request2size(300)); Busy_Header *b_4 = malloc(400); Busy_Header *b3_next = find_next(b_3); assert_addr_equal(find_next(b_3),b_4); //b_4 is after b_3 assert_equal(chunksize(b_4), request2size(400)); Busy_Header *b_5 = malloc(500); Busy_Header *b4_next = find_next(b_4); assert_addr_equal(find_next(b_4),b_5); //b_5 is after b_4 assert_equal(chunksize(b_5), request2size(500)); Heap_Info info = verify_heap(); assert_equal(info.busy, 5); assert_equal(info.free, 1); assert_equal(info.free_size, HEAP_SIZE - info.busy_size); }
//free the middle chunk, than the first chunk, leading to a merge with the head of the list void merge_with_head() { free_without_merging(); //free middle chunk first void *p = get_heap_base(); // the first allocated chunk on the heap Free_Header *freelist0 = get_freelist(); //get the head of freelist, which is the middle chunk assert_addr_not_equal(freelist0, p); Free_Header *next = freelist0->next; free(p); //free the chunk before head of the free list, need to merge Free_Header *freelist1 = get_freelist(); //get the new freelist assert_addr_equal(freelist1, p); // new head is at the base of heap assert_addr_not_equal(freelist1, freelist0); assert_addr_not_equal(freelist1->next, freelist0); assert_addr_equal(freelist1->next, next); assert_addr_equal(freelist1->prev, NULL); assert_addr_equal(next->next, NULL); assert_addr_equal(next->prev, freelist1); Heap_Info info = verify_heap(); assert_equal(info.busy, 1); assert_equal(info.free, 2); assert_equal(info.free_size, HEAP_SIZE - info.busy_size); assert_equal(freelist1->next->size, info.free_size-freelist1->size); assert_equal(find_next(find_next(freelist1)), freelist1->next); }
void push_or_update(const Value& v) { /* insert if not present, else update */ size_type index = get(index_in_heap, v); if (index == (size_type)(-1)) { index = data.size(); data.push_back(v); put(index_in_heap, v, index); } preserve_heap_property_up(index); verify_heap(); }
void pop() { put(index_in_heap, data[0], (size_type)(-1)); if (data.size() != 1) { data[0] = data.back(); put(index_in_heap, data[0], 0); data.pop_back(); preserve_heap_property_down(); verify_heap(); } else { data.pop_back(); } }
void pop() { BOOST_ASSERT (!this->empty()); put(index_in_heap, data[0], (size_type)(-1)); if (data.size() != 1) { data[0] = data.back(); put(index_in_heap, data[0], (size_type)(0)); data.pop_back(); preserve_heap_property_down(); verify_heap(); } else { data.pop_back(); } }
static void copy_heap() { /* with lock */ { verify_heap(); flip(); verify_heap(); root_descriptor_t *desc; for (desc = get_thread_roots(); desc; desc = desc->rd_next) { *desc->rd_root = move_obj(*desc->rd_root); verify_heap(); } while (next_scan < next_alloc) { next_scan = scan_obj(next_scan); verify_heap(); } assert(next_scan == next_alloc); if (debug_heap) alloc_end = next_alloc; else if (alloc_end - next_alloc < (tospace_end - tospace) / 2) fprintf(stderr, "increase heap size\n"); } }
//skip first free chunk, which is not big enough void search_along_list() { printf("after allocation:\n"); Busy_Header* b[4]; for(int i = 0; i < 4; i++){ b[i] = malloc(450); printf("b[%d]: %p\n", i, b[i]); } assert_equal(b[0]->size & SIZEMASK, request2size(450)); assert_equal(b[1]->size & SIZEMASK, request2size(450)); assert_equal(b[2]->size & SIZEMASK, request2size(450)); assert_equal(b[3]->size & SIZEMASK, request2size(450)); Free_Header* f4 = find_next(b[3]); printf("head: %p\n", f4); Heap_Info info = verify_heap(); assert_equal(info.busy, 4); assert_equal(info.free, 1); assert_equal(info.busy_size, 1824); assert_equal(info.free_size, 176); assert_addr_equal(get_freelist(), f4); assert_addr_equal(get_freelist()->next, NULL); assert_addr_equal(get_freelist()->prev, NULL); //after malloc, free b3, b0 free(b[3]); free(b[0]); Busy_Header *skip = malloc(600); printf("after malloc(600)\n"); Free_Header *head = get_freelist(); print_both_ways(head); info = verify_heap(); assert_equal(info.busy, 3); assert_equal(info.free, 2); assert_equal(info.busy_size + info.free_size, get_heap_info().heap_size); }
void malloc_then_free() { one_malloc(); void *p = get_heap_base(); // should be allocated chunk Free_Header *freelist0 = get_freelist(); free(p); Free_Header *freelist1 = get_freelist(); // allocated chunk is freed and becomes head of new freelist assert_addr_equal(freelist1, p); assert_addr_equal(freelist1, get_heap_base()); assert_addr_not_equal(freelist0, freelist1); assert_equal(chunksize(freelist1) + chunksize(freelist1->next), HEAP_SIZE); Heap_Info info = verify_heap(); assert_equal(info.busy, 0); assert_equal(info.busy_size, 0); assert_equal(info.free, 1); // 1 free chunk after merging assert_equal(info.free_size, HEAP_SIZE); }
obj_t *mem_alloc_obj(const mem_ops_t *ops, size_t size_bytes) { assert(heap_is_initialized); verify_heap(); remember_ops(ops); size_t alloc_size = aligned_size(size_bytes); if (next_alloc > alloc_end - alloc_size) { copy_heap(); assert(next_alloc <= tospace_end - alloc_size && "out of memory"); } const mem_ops_t **p; /* with lock */ { p = next_alloc; next_alloc += alloc_size; } *p = ops; return (obj_t *)p; }
void one_malloc() { void *p = malloc(100); assert_addr_not_equal(p, NULL); Free_Header *freelist = get_heap_freelist(); Busy_Header *heap = get_heap_base(); assert_addr_not_equal(freelist, heap); // check 1st chunk assert_equal(p, heap); assert_equal(chunksize(p), request2size(100)); // check 2nd chunk assert_equal(freelist->size, HEAP_SIZE-request2size(100)); assert_addr_equal(freelist->next, NULL); Heap_Info info = verify_heap(); assert_equal(info.busy, 1); assert_equal(info.busy_size, request2size(100)); assert_equal(info.free, 1); assert_equal(info.free_size, HEAP_SIZE - request2size(100)); }
//allocate 10 consecutive chunks, free from the back to the front //should fuse the heap to one free chunk void fuse_to_one() { Busy_Header* b[10]; for(int i = 0; i < 10; i++){ b[i] = malloc(100); assert_addr_equal(get_freelist(), find_next(b[i])); assert_addr_equal(get_freelist()->prev, NULL); } Free_Header *freelist0 = get_freelist(); for( int i = 9; i >= 0 ; i--){ free(b[i]); assert_addr_equal(get_freelist(), b[i]); assert_addr_equal(get_freelist()->prev, NULL); } Heap_Info info = verify_heap(); assert_equal(info.busy, 0); assert_equal(info.free, 1); assert_equal(info.busy_size + info.free_size, get_heap_info().heap_size); assert_addr_equal(find_next(get_freelist()), get_heap_base() + info.heap_size); assert_addr_equal(freelist0->next, NULL); }
//free the first chunk, then free last chunk to merge with the end of free list void merge_with_middle() { five_malloc(); Busy_Header *b_1 = get_heap_base(); Busy_Header *b_2 = find_next(b_1); Busy_Header *b_3 = find_next(b_2); Busy_Header *b_4 = find_next(b_3); Busy_Header *b_5 = find_next(b_4); size_t size_3 = b_3->size & SIZEMASK; size_t size_4 = b_4->size & SIZEMASK; free(b_4); free(b_2); Free_Header *freelist0 = get_freelist(); //get the new freelist at b_2->b_4->after b_5 Free_Header *last = find_next(b_5); assert_addr_equal(freelist0, b_2); assert_addr_equal(freelist0->next, b_4); assert_addr_equal(freelist0->prev, NULL); assert_addr_equal(((Free_Header*)b_4) ->next, last); assert_addr_equal(((Free_Header*)b_4) ->prev, b_2); assert_addr_equal(last->next, NULL); assert_addr_equal(last->prev, b_4); free(b_3); //merge with b_4 Free_Header *freelist1 = get_freelist(); //get new free list at b_3; assert_addr_equal(freelist1, b_3); assert_equal(freelist1->size & SIZEMASK, size_3 + size_4); assert_addr_equal(freelist1->next, b_2); //freelist1 ->freelist0->last assert_addr_equal(freelist1->prev, NULL); assert_addr_equal(freelist0->next, last); assert_addr_equal(freelist0->prev, freelist1); assert_addr_equal(last->next, NULL); assert_addr_equal(last->prev, freelist0); Heap_Info info = verify_heap(); assert_equal(info.busy, 2); assert_equal(info.free, 3); assert_equal(info.free_size, HEAP_SIZE - info.busy_size); assert_equal(freelist1->next->size + freelist0->next->size, info.free_size-freelist1->size); }
void two_malloc() { one_malloc(); void *p0 = get_heap_base(); Free_Header *freelist0 = get_heap_freelist(); Busy_Header *p = malloc(200); assert_addr_not_equal(p, NULL); // check 2nd alloc chunk assert_equal(p, freelist0); // should return previous free chunk assert_equal(chunksize(p), request2size(200)); // check remaining free chunk Free_Header *freelist1 = get_heap_freelist(); assert_addr_not_equal(freelist0, freelist1); assert_addr_not_equal(freelist0, get_heap_base()); assert_equal(chunksize(freelist1), HEAP_SIZE-request2size(100)-request2size(200)); assert_equal(chunksize(p0)+chunksize(p)+chunksize(freelist1), HEAP_SIZE); assert_addr_equal(freelist1->next, NULL); Heap_Info info = verify_heap(); assert_equal(info.busy, 2); assert_equal(info.busy_size, request2size(100) + request2size(200)); assert_equal(info.free, 1); assert_equal(info.free_size, HEAP_SIZE - request2size(100) - request2size(200)); }
//free the chunk in the middle of three busy chunks void free_without_merging() { three_malloc(); Busy_Header *b_1 = get_heap_base(); Busy_Header *b_2 = find_next(b_1); Busy_Header *b_3 = find_next(b_2); Free_Header *freelist0 = get_freelist(); //get the head of freelist, which is at the end of allocated chunks assert_addr_equal(freelist0, find_next(b_3)); free(b_2); //free the chunk in the middle, which becomes the head of the new freelist Free_Header *freelist1 = get_freelist(); //get the new freelist assert_addr_not_equal(freelist1, b_1); assert_addr_not_equal(freelist0, freelist1); assert_addr_equal(freelist1, b_2); assert_addr_equal(freelist1->next, freelist0); //two free chunks in the list assert_equal(chunksize(b_1) + chunksize(b_2) + chunksize(b_3) + chunksize(freelist0), HEAP_SIZE); assert_equal(chunksize(b_1) + chunksize(b_3) + chunksize(freelist1) + chunksize(freelist0), HEAP_SIZE); Heap_Info info = verify_heap(); assert_equal(info.busy, 2); assert_equal(info.busy_size, chunksize(b_1) + chunksize(b_3)); assert_equal(info.free, 2); // 2 free chunks not next to each other assert_equal(info.free_size, chunksize(freelist1) + chunksize(freelist1->next)); }
static void teardown() { verify_heap(); freelist_shutdown(); }
t_boolean try_route_net(t_net* net_to_route, int do_graphics) { t_boolean found_route = FALSE; t_boolean found_traceback = FALSE; float prev_cost = 0.; //Labels source, target //Initializes expansion list t_expansion_list* expansion_list = init_expansion_list(net_to_route); while(!is_empty_expansion_list(expansion_list)) { //Each current segment on expansion list with the lowest label // Note also removes from expansion list t_heap_node current_seg_node = get_min_expansion_list(expansion_list); t_wire* current_seg = current_seg_node.wire; //Each new segment reachable from the current segment // This is an expansion t_adjacent_segs* adjacent_segs = find_adjacent_segs(current_seg); DEBUG_PRINT("\tExpansion on wire %s\n", short_wire_name(current_seg)); double next_cost = 0.; int sb_index; for(sb_index = 0; sb_index < adjacent_segs->num_sb; sb_index++) { int adjacent_seg_index; for(adjacent_seg_index = 0; adjacent_seg_index < adjacent_segs->num_segs[sb_index]; adjacent_seg_index++) { t_wire* adjacent_seg = adjacent_segs->array_of_segs[sb_index][adjacent_seg_index]; //The cost at this adjacent_seg next_cost = current_seg_node.key + incr_wire_cost(adjacent_seg); assert(next_cost >= 0); //Found the target if(adjacent_seg->label_type == TARGET) { found_route = TRUE; if (adjacent_seg->label_value == -1) { DEBUG_PRINT("\t\tChecking wire %s \t Found first routing path!\n", short_wire_name(adjacent_seg)); //First route to find it, label it adjacent_seg->label_value = next_cost; } else if (next_cost < adjacent_seg->label_value) { DEBUG_PRINT("\t\tChecking wire %s \t Found better routing path!\n", short_wire_name(adjacent_seg)); adjacent_seg->label_value = next_cost; } else if (next_cost == adjacent_seg->label_value){ DEBUG_PRINT("\t\tChecking wire %s \t Found equivalent routing path\n", short_wire_name(adjacent_seg)); } else { DEBUG_PRINT("\t\tChecking wire %s \t Found worse routing path\n", short_wire_name(adjacent_seg)); } //Search for the best routing (i.e. the whole RR graph) // Since we are using variable costs, the best route may not be // the shortest (first found) // // This will increase CPU Time continue; /*break;*/ } //Segment already used/labeled if(adjacent_seg->label_type == CURRENT_EXPANSION) { DEBUG_PRINT("\t\tChecking wire %s \t Wire already in expansion\n", short_wire_name(adjacent_seg)); continue; } if(adjacent_seg->label_type == SOURCE) { DEBUG_PRINT("\t\tChecking wire %s \t Wire is source\n", short_wire_name(adjacent_seg)); continue; } //Label new segment adjacent_seg->label_type = CURRENT_EXPANSION; adjacent_seg->label_value = next_cost; //Add to expansion list at current cost insert_expansion_list(expansion_list, adjacent_seg, adjacent_seg->label_value); DEBUG_PRINT("\t\tChecking wire %s \t Adding wire to expansion at cost %f\n", short_wire_name(adjacent_seg), adjacent_seg->label_value); } } #if DEBUG verify_heap(expansion_list); #endif free_adjacent_segs(adjacent_segs); prev_cost = next_cost; }//while expansion_list if (found_route == TRUE) { found_traceback = commit_traceback(net_to_route, do_graphics); } //Remove expansion labels etc clean_rr_graph(); return (found_route && found_traceback); }
// This function assumes the key has been updated (using an external write // to the distance map or such) // See http://coding.derkeiler.com/Archive/General/comp.theory/2007-05/msg00043.html void update(const Value& v) { /* decrease-key */ size_type index = get(index_in_heap, v); preserve_heap_property_up(index); verify_heap(); }
//split chunk void split_chunk(){ printf("after allocation:\n"); Busy_Header* b[4]; for(int i = 0; i < 4; i++){ b[i] = malloc(450); printf("b[%d]: %p\n", i, b[i]); } assert_equal(b[0]->size & SIZEMASK, request2size(450)); assert_equal(b[1]->size & SIZEMASK, request2size(450)); assert_equal(b[2]->size & SIZEMASK, request2size(450)); assert_equal(b[3]->size & SIZEMASK, request2size(450)); Free_Header* f4 = find_next(b[3]); printf("head: %p\n", f4); Heap_Info info = verify_heap(); assert_equal(info.busy, 4); assert_equal(info.free, 1); assert_equal(info.busy_size, 1824); assert_equal(info.free_size, 176); assert_addr_equal(get_freelist(), f4); assert_addr_equal(get_freelist()->next, NULL); assert_addr_equal(get_freelist()->prev, NULL); free(b[2]); info = verify_heap(); assert_equal(info.busy, 3); assert_equal(info.free, 2); assert_equal(info.busy_size, 1368); assert_equal(info.free_size, 632); assert_addr_equal(get_freelist(), b[2]); assert_addr_equal(get_freelist()->next, f4); assert_addr_equal(get_freelist()->next->next, NULL); assert_addr_equal(f4->prev, b[2]); assert_addr_equal(f4->prev->prev, NULL); printf("after free b[2]\n"); Free_Header *head = get_freelist(); print_both_ways(head); free(b[0]); info = verify_heap(); assert_equal(info.busy, 2); assert_equal(info.free, 3); assert_equal(info.busy_size, 912); assert_equal(info.free_size, 1088); assert_addr_equal(get_freelist(), b[0]); assert_addr_equal(get_freelist()->next, b[2]); assert_addr_equal(get_freelist()->next->next, f4); assert_addr_equal(get_freelist()->next->next->next, NULL); assert_addr_equal(f4->prev, b[2]); assert_addr_equal(f4->prev->prev, b[0]); assert_addr_equal(f4->prev->prev->prev, NULL); printf("after free b[0]\n"); head = get_freelist(); print_both_ways(head); Busy_Header *split = malloc(200); printf("after malloc(200)\n"); head = get_freelist(); print_both_ways(head); assert_addr_equal(split, get_heap_base()); Free_Header *newhead = get_freelist(); assert_addr_equal(find_next(split),newhead); assert_addr_equal(get_freelist(), find_next(split)); assert_addr_equal(get_freelist()->next, b[2]); assert_addr_equal(get_freelist()->next->next, f4); assert_addr_equal(get_freelist()->next->next->next, NULL); assert_addr_equal(f4->prev, b[2]); assert_addr_equal(f4->prev->prev, newhead); assert_addr_equal(f4->prev->prev->prev, NULL); info = verify_heap(); assert_equal(info.busy, 3); assert_equal(info.free, 3); assert_equal(info.busy_size + info.free_size, get_heap_info().heap_size); // out of heap*/ }
static void teardown() { verify_heap(); heap_shutdown(); }