inline static void BTC_memory_account_mark(NewGC *gc, mpage *page, void *ptr) { GCDEBUG((DEBUGOUTF, "BTC_memory_account_mark: %p/%p\n", page, ptr)); if(page->size_class) { if(page->size_class > 1) { /* big page */ objhead *info = BIG_PAGE_TO_OBJHEAD(page); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(page->size)); push_ptr(gc, TAG_AS_BIG_PAGE_PTR(ptr)); } } else { /* medium page */ objhead *info = MED_OBJHEAD(ptr, page->size); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, info->size); ptr = OBJHEAD_TO_OBJPTR(info); push_ptr(gc, ptr); } } } else { objhead *info = OBJPTR_TO_OBJHEAD(ptr); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, info->size); push_ptr(gc, ptr); } } }
inline static void BTC_memory_account_mark(NewGC *gc, mpage *page, void *ptr, int is_a_master_page) { GCDEBUG((DEBUGOUTF, "BTC_memory_account_mark: %p/%p\n", page, ptr)); /* In the case of is_a_master_page, whether this place is charged is a little random: there's no guarantee that the btc_mark values are in sync, and there are races among places. Approximations are ok for accounting, though, as long as the probably for completely wrong accounting is very low. At the same time, we need to synchronize enough so that two places with different new_btc_mark values don't send each other into infinite loops (with the btc_mark value bouncing back and forth) or overcounting. We synchronize enough by having a single new_btc_mark value for master pages, and we stall if the value isn't what this place wants. */ if (is_a_master_page) check_master_btc_mark(gc, page); if(page->size_class) { if(page->size_class > 1) { /* big page */ objhead *info = BIG_PAGE_TO_OBJHEAD(page); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(page->size), is_a_master_page); push_ptr(gc, TAG_AS_BIG_PAGE_PTR(ptr)); } } else { /* medium page */ objhead *info = MED_OBJHEAD(ptr, page->size); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, info->size, is_a_master_page); ptr = OBJHEAD_TO_OBJPTR(info); push_ptr(gc, ptr); } } } else { objhead *info = OBJPTR_TO_OBJHEAD(ptr); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, info->size, 0); push_ptr(gc, ptr); } } }
inline static void BTC_memory_account_mark(NewGC *gc, mpage *page, void *ptr, int is_a_master_page) { GCDEBUG((DEBUGOUTF, "BTC_memory_account_mark: %p/%p\n", page, ptr)); /* In the case of is_a_master_page, whether this place is charged is a little random: there's no guarantee that the btc_mark values are in sync, and there are races among places. Approximations are ok for accounting, though, as long as the probably for completely wrong accounting is very low. */ if(page->size_class) { if(page->size_class > 1) { /* big page */ objhead *info = BIG_PAGE_TO_OBJHEAD(page); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(page->size), is_a_master_page); push_ptr(gc, TAG_AS_BIG_PAGE_PTR(ptr)); } } else { /* medium page */ objhead *info = MED_OBJHEAD(ptr, page->size); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, info->size, is_a_master_page); ptr = OBJHEAD_TO_OBJPTR(info); push_ptr(gc, ptr); } } } else { objhead *info = OBJPTR_TO_OBJHEAD(ptr); if(info->btc_mark == gc->old_btc_mark) { info->btc_mark = gc->new_btc_mark; account_memory(gc, gc->current_mark_owner, info->size, 0); push_ptr(gc, ptr); } } }
static void BTC_do_accounting(NewGC *gc) { const int table_size = gc->owner_table_size; OTEntry **owner_table = gc->owner_table; if(gc->really_doing_accounting) { Scheme_Custodian *cur = owner_table[current_owner(gc, NULL)]->originator, *last, *parent; Scheme_Custodian_Reference *box = cur->global_next; int i; GCDEBUG((DEBUGOUTF, "\nBEGINNING MEMORY ACCOUNTING\n")); gc->doing_memory_accounting = 1; gc->in_unsafe_allocation_mode = 1; gc->unsafe_allocation_abort = btc_overmem_abort; gc->master_page_btc_mark_checked = 0; /* clear the memory use numbers out */ for(i = 1; i < table_size; i++) if(owner_table[i]) { owner_table[i]->memory_use = 0; #ifdef MZ_USE_PLACES if (MASTERGC && MASTERGC->major_places_gc) owner_table[i]->master_memory_use = 0; #endif } /* start with root: */ while (cur->parent && SCHEME_PTR1_VAL(cur->parent)) { cur = SCHEME_PTR1_VAL(cur->parent); } /* walk forward for the order we want (blame parents instead of children) */ last = cur; while(cur) { int owner = custodian_to_owner_set(gc, cur); uintptr_t save_count = gc->phantom_count; gc->phantom_count = 0; gc->current_mark_owner = owner; GCDEBUG((DEBUGOUTF,"MARKING THREADS OF OWNER %i (CUST %p)\n", owner, cur)); gc->kill_propagation_loop = 0; mark_threads(gc, owner); mark_cust_boxes(gc, cur); GCDEBUG((DEBUGOUTF, "Propagating accounting marks\n")); propagate_accounting_marks(gc); last = cur; box = cur->global_next; cur = box ? SCHEME_PTR1_VAL(box) : NULL; owner_table = gc->owner_table; owner_table[owner]->memory_use = add_no_overflow(owner_table[owner]->memory_use, gcBYTES_TO_WORDS(gc->phantom_count)); gc->phantom_count = save_count; } release_master_btc_mark(gc); /* walk backward folding totals int parent */ cur = last; while (cur) { int owner = custodian_to_owner_set(gc, cur); box = cur->parent; parent = box ? SCHEME_PTR1_VAL(box) : NULL; if (parent) { int powner = custodian_to_owner_set(gc, parent); owner_table = gc->owner_table; owner_table[powner]->memory_use = add_no_overflow(owner_table[powner]->memory_use, owner_table[owner]->memory_use); owner_table[powner]->master_memory_use += owner_table[owner]->master_memory_use; } box = cur->global_prev; cur = box ? SCHEME_PTR1_VAL(box) : NULL; } gc->in_unsafe_allocation_mode = 0; gc->doing_memory_accounting = 0; gc->old_btc_mark = gc->new_btc_mark; gc->new_btc_mark = !gc->new_btc_mark; } clear_stack_pages(gc); }