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); } } }
int BTC_bi_chan_mark(void *p, struct NewGC *gc) { if (gc->doing_memory_accounting) { Scheme_Place_Bi_Channel *bc = (Scheme_Place_Bi_Channel *)p; /* Race conditions here on `mem_size', and likely double counting when the same async channels are accessible from paired bi channels --- but those approximations are ok for accounting. */ account_memory(gc, gc->current_mark_owner, bc->sendch->mem_size, 0); account_memory(gc, gc->current_mark_owner, bc->recvch->mem_size, 0); } return gc->mark_table[btc_redirect_bi_chan](p, gc); }
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 mark_threads(NewGC *gc, int owner) { GC_Thread_Info *work; Mark2_Proc thread_mark = gc->mark_table[btc_redirect_thread]; for(work = gc->thread_infos; work; work = work->next) { if (work->owner == owner) { if (((Scheme_Object *)work->thread)->type == scheme_thread_type) { /* thread */ if (((Scheme_Thread *)work->thread)->running) { thread_mark(work->thread, gc); if (work->thread == scheme_current_thread) { GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(gc), NULL); } } } else { /* place */ #ifdef MZ_USE_PLACES /* add in the memory used by the place's GC */ intptr_t sz; Scheme_Place_Object *place_obj = ((Scheme_Place *)work->thread)->place_obj; if (place_obj) { mzrt_mutex_lock(place_obj->lock); sz = place_obj->memory_use; mzrt_mutex_unlock(place_obj->lock); account_memory(gc, owner, gcBYTES_TO_WORDS(sz), 0); } #endif } } } }
int BTC_bi_chan_mark(void *p, struct NewGC *gc) { if (gc->doing_memory_accounting) { Scheme_Place_Bi_Channel *bc = (Scheme_Place_Bi_Channel *)p; /* The `link` field can be NULL if the channel is still being set up: */ if (bc->link) { /* Race conditions here on `mem_size', and likely double counting when the same async channels are accessible from paired bi channels --- but those approximations are ok for accounting. */ if (bc->link->sendch) account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(bc->link->sendch->mem_size), 0); if (bc->link->recvch) account_memory(gc, gc->current_mark_owner, gcBYTES_TO_WORDS(bc->link->recvch->mem_size), 0); } } return gc->mark_table[btc_redirect_bi_chan](p, gc); }
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); } } }