GC2 builds with and without blame the child, blame the child is more cleanly separated
svn: r12298
This commit is contained in:
parent
03548173f1
commit
af34446ec3
|
@ -3,6 +3,75 @@
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
#ifdef NEWGC_BTC_ACCOUNT
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
|
||||||
|
#include "../src/schpriv.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* thread list */
|
||||||
|
/*****************************************************************************/
|
||||||
|
inline static int current_owner(Scheme_Custodian *c);
|
||||||
|
|
||||||
|
inline static void BTC_register_new_thread(void *t, void *c)
|
||||||
|
{
|
||||||
|
GC_Thread_Info *work;
|
||||||
|
|
||||||
|
work = (GC_Thread_Info *)malloc(sizeof(GC_Thread_Info));
|
||||||
|
((Scheme_Thread *)t)->gc_info = work;
|
||||||
|
work->owner = current_owner((Scheme_Custodian *)c);
|
||||||
|
work->thread = t;
|
||||||
|
|
||||||
|
work->next = GC->thread_infos;
|
||||||
|
GC->thread_infos = work;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void BTC_register_thread(void *t, void *c)
|
||||||
|
{
|
||||||
|
GC_Thread_Info *work;
|
||||||
|
|
||||||
|
work = ((Scheme_Thread *)t)->gc_info;
|
||||||
|
work->owner = current_owner((Scheme_Custodian *)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void mark_threads(int owner)
|
||||||
|
{
|
||||||
|
GC_Thread_Info *work;
|
||||||
|
|
||||||
|
for(work = GC->thread_infos; work; work = work->next)
|
||||||
|
if(work->owner == owner) {
|
||||||
|
if (((Scheme_Thread *)work->thread)->running) {
|
||||||
|
GC->normal_thread_mark(work->thread);
|
||||||
|
if (work->thread == scheme_current_thread) {
|
||||||
|
GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void clean_up_thread_list(void)
|
||||||
|
{
|
||||||
|
GC_Thread_Info *work = GC->thread_infos;
|
||||||
|
GC_Thread_Info *prev = NULL;
|
||||||
|
|
||||||
|
while(work) {
|
||||||
|
if(!pagemap_find_page(GC->page_maps, work->thread) || marked(work->thread)) {
|
||||||
|
work->thread = GC_resolve(work->thread);
|
||||||
|
prev = work;
|
||||||
|
work = work->next;
|
||||||
|
} else {
|
||||||
|
GC_Thread_Info *next = work->next;
|
||||||
|
|
||||||
|
if(prev) prev->next = next;
|
||||||
|
if(!prev) GC->thread_infos = next;
|
||||||
|
free(work);
|
||||||
|
work = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static int thread_get_owner(void *p)
|
||||||
|
{
|
||||||
|
return ((Scheme_Thread *)p)->gc_info->owner;
|
||||||
|
}
|
||||||
|
|
||||||
#define OWNER_TABLE_INIT_AMT 10
|
#define OWNER_TABLE_INIT_AMT 10
|
||||||
|
|
||||||
struct ot_entry {
|
struct ot_entry {
|
||||||
|
@ -13,7 +82,7 @@ struct ot_entry {
|
||||||
char limit_set, required_set;
|
char limit_set, required_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ot_entry **owner_table = NULL;
|
static THREAD_LOCAL struct ot_entry **owner_table = NULL;
|
||||||
static unsigned int owner_table_top = 0;
|
static unsigned int owner_table_top = 0;
|
||||||
|
|
||||||
inline static int create_blank_owner_set(void)
|
inline static int create_blank_owner_set(void)
|
||||||
|
@ -69,7 +138,7 @@ inline static int current_owner(Scheme_Custodian *c)
|
||||||
return custodian_to_owner_set(c);
|
return custodian_to_owner_set(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_register_root_custodian(void *_c)
|
void BTC_register_root_custodian(void *_c)
|
||||||
{
|
{
|
||||||
Scheme_Custodian *c = (Scheme_Custodian *)_c;
|
Scheme_Custodian *c = (Scheme_Custodian *)_c;
|
||||||
|
|
||||||
|
@ -152,9 +221,9 @@ inline static unsigned long custodian_usage(void *custodian)
|
||||||
return gcWORDS_TO_BYTES(retval);
|
return gcWORDS_TO_BYTES(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void memory_account_mark(struct mpage *page, void *ptr)
|
inline static void BTC_memory_account_mark(struct mpage *page, void *ptr)
|
||||||
{
|
{
|
||||||
GCDEBUG((DEBUGOUTF, "memory_account_mark: %p/%p\n", page, ptr));
|
GCDEBUG((DEBUGOUTF, "BTC_memory_account_mark: %p/%p\n", page, ptr));
|
||||||
if(page->big_page) {
|
if(page->big_page) {
|
||||||
struct objhead *info = (struct objhead *)(NUM(page->addr) + PREFIX_SIZE);
|
struct objhead *info = (struct objhead *)(NUM(page->addr) + PREFIX_SIZE);
|
||||||
|
|
||||||
|
@ -302,7 +371,7 @@ static void propagate_accounting_marks(void)
|
||||||
reset_pointer_stack();
|
reset_pointer_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_btc_accounting(void)
|
static void BTC_do_accounting(void)
|
||||||
{
|
{
|
||||||
if(GC->really_doing_accounting) {
|
if(GC->really_doing_accounting) {
|
||||||
Scheme_Custodian *cur = owner_table[current_owner(NULL)]->originator;
|
Scheme_Custodian *cur = owner_table[current_owner(NULL)]->originator;
|
||||||
|
@ -365,25 +434,17 @@ static void do_btc_accounting(void)
|
||||||
clear_stack_pages();
|
clear_stack_pages();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct account_hook {
|
inline static void BTC_add_account_hook(int type,void *c1,void *c2,unsigned long b)
|
||||||
int type;
|
|
||||||
void *c1, *c2;
|
|
||||||
unsigned long amount;
|
|
||||||
struct account_hook *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct account_hook *hooks = NULL;
|
|
||||||
|
|
||||||
inline static void add_account_hook(int type,void *c1,void *c2,unsigned long b)
|
|
||||||
{
|
{
|
||||||
struct account_hook *work;
|
AccountHook *work;
|
||||||
|
|
||||||
if(!GC->really_doing_accounting) {
|
if(!GC->really_doing_accounting) {
|
||||||
GC->park[0] = c1; GC->park[1] = c2;
|
GC->park[0] = c1;
|
||||||
|
GC->park[1] = c2;
|
||||||
GC->really_doing_accounting = 1;
|
GC->really_doing_accounting = 1;
|
||||||
garbage_collect(1);
|
garbage_collect(1);
|
||||||
c1 = GC->park[0]; c2 = GC->park[1];
|
c1 = GC->park[0]; GC->park[0] = NULL;
|
||||||
GC->park[0] = GC->park[1] = NULL;
|
c2 = GC->park[1]; GC->park[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == MZACCT_LIMIT)
|
if (type == MZACCT_LIMIT)
|
||||||
|
@ -391,7 +452,7 @@ inline static void add_account_hook(int type,void *c1,void *c2,unsigned long b)
|
||||||
if (type == MZACCT_REQUIRE)
|
if (type == MZACCT_REQUIRE)
|
||||||
GC->reset_required = 1;
|
GC->reset_required = 1;
|
||||||
|
|
||||||
for(work = hooks; work; work = work->next) {
|
for(work = GC->hooks; work; work = work->next) {
|
||||||
if((work->type == type) && (work->c2 == c2) && (work->c1 == c1)) {
|
if((work->type == type) && (work->c2 == c2) && (work->c1 == c1)) {
|
||||||
if(type == MZACCT_REQUIRE) {
|
if(type == MZACCT_REQUIRE) {
|
||||||
if(b > work->amount) work->amount = b;
|
if(b > work->amount) work->amount = b;
|
||||||
|
@ -403,26 +464,35 @@ inline static void add_account_hook(int type,void *c1,void *c2,unsigned long b)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!work) {
|
if(!work) {
|
||||||
work = malloc(sizeof(struct account_hook));
|
work = malloc(sizeof(AccountHook));
|
||||||
work->type = type; work->c1 = c1; work->c2 = c2; work->amount = b;
|
work->type = type;
|
||||||
work->next = hooks; hooks = work;
|
work->c1 = c1;
|
||||||
|
work->c2 = c2;
|
||||||
|
work->amount = b;
|
||||||
|
|
||||||
|
/* push work onto hooks */
|
||||||
|
work->next = GC->hooks;
|
||||||
|
GC->hooks = work;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void clean_up_account_hooks()
|
inline static void clean_up_account_hooks()
|
||||||
{
|
{
|
||||||
struct account_hook *work = hooks, *prev = NULL;
|
AccountHook *work = GC->hooks;
|
||||||
|
AccountHook *prev = NULL;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if((!work->c1 || marked(work->c1)) && marked(work->c2)) {
|
if((!work->c1 || marked(work->c1)) && marked(work->c2)) {
|
||||||
work->c1 = GC_resolve(work->c1);
|
work->c1 = GC_resolve(work->c1);
|
||||||
work->c2 = GC_resolve(work->c2);
|
work->c2 = GC_resolve(work->c2);
|
||||||
prev = work; work = work->next;
|
prev = work;
|
||||||
|
work = work->next;
|
||||||
} else {
|
} else {
|
||||||
struct account_hook *next = work->next;
|
/* remove work hook */
|
||||||
|
AccountHook *next = work->next;
|
||||||
|
|
||||||
if(prev) prev->next = next;
|
if(prev) prev->next = next;
|
||||||
if(!prev) hooks = next;
|
if(!prev) GC->hooks = next;
|
||||||
free(work);
|
free(work);
|
||||||
work = next;
|
work = next;
|
||||||
}
|
}
|
||||||
|
@ -443,7 +513,7 @@ static unsigned long custodian_super_require(void *c)
|
||||||
|
|
||||||
if (!owner_table[set]->required_set) {
|
if (!owner_table[set]->required_set) {
|
||||||
unsigned long req = 0, r;
|
unsigned long req = 0, r;
|
||||||
struct account_hook *work = hooks;
|
AccountHook *work = GC->hooks;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if ((work->type == MZACCT_REQUIRE) && (c == work->c2)) {
|
if ((work->type == MZACCT_REQUIRE) && (c == work->c2)) {
|
||||||
|
@ -460,9 +530,10 @@ static unsigned long custodian_super_require(void *c)
|
||||||
return owner_table[set]->super_required;
|
return owner_table[set]->super_required;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void run_account_hooks()
|
inline static void BTC_run_account_hooks()
|
||||||
{
|
{
|
||||||
struct account_hook *work = hooks, *prev = NULL;
|
AccountHook *work = GC->hooks;
|
||||||
|
AccountHook *prev = NULL;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if( ((work->type == MZACCT_REQUIRE) &&
|
if( ((work->type == MZACCT_REQUIRE) &&
|
||||||
|
@ -472,15 +543,16 @@ inline static void run_account_hooks()
|
||||||
||
|
||
|
||||||
((work->type == MZACCT_LIMIT) &&
|
((work->type == MZACCT_LIMIT) &&
|
||||||
(GC_get_memory_use(work->c1) > work->amount))) {
|
(GC_get_memory_use(work->c1) > work->amount))) {
|
||||||
struct account_hook *next = work->next;
|
AccountHook *next = work->next;
|
||||||
|
|
||||||
if(prev) prev->next = next;
|
if(prev) prev->next = next;
|
||||||
if(!prev) hooks = next;
|
if(!prev) GC->hooks = next;
|
||||||
scheme_schedule_custodian_close(work->c2);
|
scheme_schedule_custodian_close(work->c2);
|
||||||
free(work);
|
free(work);
|
||||||
work = next;
|
work = next;
|
||||||
} else {
|
} else {
|
||||||
prev = work; work = work->next;
|
prev = work;
|
||||||
|
work = work->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,7 +574,7 @@ static unsigned long custodian_single_time_limit(int set)
|
||||||
/* Check for limits on this custodian or one of its ancestors: */
|
/* Check for limits on this custodian or one of its ancestors: */
|
||||||
unsigned long limit = (unsigned long)(long)-1;
|
unsigned long limit = (unsigned long)(long)-1;
|
||||||
Scheme_Custodian *orig = owner_table[set]->originator, *c;
|
Scheme_Custodian *orig = owner_table[set]->originator, *c;
|
||||||
struct account_hook *work = hooks;
|
AccountHook *work = GC->hooks;
|
||||||
|
|
||||||
while(work) {
|
while(work) {
|
||||||
if ((work->type == MZACCT_LIMIT) && (work->c1 == work->c2)) {
|
if ((work->type == MZACCT_LIMIT) && (work->c1 == work->c2)) {
|
||||||
|
@ -529,23 +601,32 @@ static unsigned long custodian_single_time_limit(int set)
|
||||||
return owner_table[set]->single_time_limit;
|
return owner_table[set]->single_time_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long BTC_get_memory_use(void *o)
|
||||||
# define set_account_hook(a,b,c,d) { add_account_hook(a,b,c,d); return 1; }
|
|
||||||
# define set_btc_mark(x) (((struct objhead *)(x))->btc_mark = GC->old_btc_mark)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NEWGC_BTC_ACCOUNT
|
|
||||||
# define clean_up_owner_table() /* */
|
|
||||||
# define do_btc_accounting() /* */
|
|
||||||
# define doing_memory_accounting 0
|
|
||||||
# define memory_account_mark(p,o) /* */
|
|
||||||
# define set_account_hook(a,b,c,d) return 0
|
|
||||||
# define clean_up_account_hooks() /* */
|
|
||||||
# define run_account_hooks() /* */
|
|
||||||
# define custodian_usage(cust) 0
|
|
||||||
# define set_btc_mark(x) /* */
|
|
||||||
static unsigned long custodian_single_time_limit(int set)
|
|
||||||
{
|
{
|
||||||
return (unsigned long)(long)-1;
|
Scheme_Object *arg = (Scheme_Object*)o;
|
||||||
|
if(SAME_TYPE(SCHEME_TYPE(arg), scheme_custodian_type)) {
|
||||||
|
return custodian_usage(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BTC_single_allocation_limit(size_t sizeb) {
|
||||||
|
/* We're allowed to fail. Check for allocations that exceed a single-time
|
||||||
|
* limit. Otherwise, the limit doesn't work as intended, because
|
||||||
|
* a program can allocate a large block that nearly exhausts memory,
|
||||||
|
* and then a subsequent allocation can fail. As long as the limit
|
||||||
|
* is much smaller than the actual available memory, and as long as
|
||||||
|
* GC_out_of_memory protects any user-requested allocation whose size
|
||||||
|
* is independent of any existing object, then we can enforce the limit. */
|
||||||
|
return (custodian_single_time_limit(thread_get_owner(scheme_current_thread)) < sizeb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void BTC_clean_up() {
|
||||||
|
clean_up_thread_list();
|
||||||
|
clean_up_owner_table();
|
||||||
|
clean_up_account_hooks();
|
||||||
|
}
|
||||||
|
|
||||||
|
# define BTC_set_btc_mark(x) (((struct objhead *)(x))->btc_mark = GC->old_btc_mark)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "../src/schpriv.h"
|
||||||
|
|
||||||
#if defined(MZ_PRECISE_GC) && !defined(USE_COMPACT_3M_GC)
|
#if defined(MZ_PRECISE_GC) && !defined(USE_COMPACT_3M_GC)
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "platforms.h"
|
#include "platforms.h"
|
||||||
#include "gc2.h"
|
#include "gc2.h"
|
||||||
#include "gc2_dump.h"
|
#include "gc2_dump.h"
|
||||||
#include "../src/schpriv.h"
|
|
||||||
|
|
||||||
/* the number of tags to use for tagged objects */
|
/* the number of tags to use for tagged objects */
|
||||||
#define NUMBER_OF_TAGS 512
|
#define NUMBER_OF_TAGS 512
|
||||||
|
@ -85,6 +84,7 @@ static THREAD_LOCAL NewGC *GC;
|
||||||
|
|
||||||
/* This turns on blame-the-child automatic memory accounting */
|
/* This turns on blame-the-child automatic memory accounting */
|
||||||
/* #define NEWGC_BTC_ACCOUNT */
|
/* #define NEWGC_BTC_ACCOUNT */
|
||||||
|
/* #undef NEWGC_BTC_ACCOUNT */
|
||||||
|
|
||||||
/* This turns on memory tracing */
|
/* This turns on memory tracing */
|
||||||
/* #define NEWGC_MEMORY_TRACE */
|
/* #define NEWGC_MEMORY_TRACE */
|
||||||
|
@ -383,8 +383,9 @@ static void free_mpage(struct mpage *page)
|
||||||
free(page);
|
free(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long custodian_single_time_limit(int set);
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
inline static int thread_get_owner(void *p);
|
static inline int BTC_single_allocation_limit(size_t sizeb);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* the core allocation functions */
|
/* the core allocation functions */
|
||||||
static void *allocate_big(size_t sizeb, int type)
|
static void *allocate_big(size_t sizeb, int type)
|
||||||
|
@ -392,7 +393,9 @@ static void *allocate_big(size_t sizeb, int type)
|
||||||
mpage *bpage;
|
mpage *bpage;
|
||||||
void *addr;
|
void *addr;
|
||||||
|
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
if(GC_out_of_memory) {
|
if(GC_out_of_memory) {
|
||||||
|
if (BTC_single_allocation_limit(sizeb)) {
|
||||||
/* We're allowed to fail. Check for allocations that exceed a single-time
|
/* We're allowed to fail. Check for allocations that exceed a single-time
|
||||||
limit. Otherwise, the limit doesn't work as intended, because
|
limit. Otherwise, the limit doesn't work as intended, because
|
||||||
a program can allocate a large block that nearly exhausts memory,
|
a program can allocate a large block that nearly exhausts memory,
|
||||||
|
@ -400,10 +403,10 @@ static void *allocate_big(size_t sizeb, int type)
|
||||||
is much smaller than the actual available memory, and as long as
|
is much smaller than the actual available memory, and as long as
|
||||||
GC_out_of_memory protects any user-requested allocation whose size
|
GC_out_of_memory protects any user-requested allocation whose size
|
||||||
is independent of any existing object, then we can enforce the limit. */
|
is independent of any existing object, then we can enforce the limit. */
|
||||||
if (custodian_single_time_limit(thread_get_owner(scheme_current_thread)) < sizeb) {
|
|
||||||
GC_out_of_memory();
|
GC_out_of_memory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* the actual size of this is the size, ceilinged to the next largest word,
|
/* the actual size of this is the size, ceilinged to the next largest word,
|
||||||
plus one word for the object header.
|
plus one word for the object header.
|
||||||
|
@ -1238,94 +1241,43 @@ inline static void reset_pointer_stack(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* thread list */
|
/* BLAME THE CHILD */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#ifdef NEWGC_BTC_ACCOUNT
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
inline static int current_owner(Scheme_Custodian *c);
|
# include "blame_the_child.c"
|
||||||
|
#else
|
||||||
inline static void register_new_thread(void *t, void *c)
|
|
||||||
{
|
|
||||||
GC_Thread_Info *work;
|
|
||||||
|
|
||||||
work = (GC_Thread_Info *)malloc(sizeof(GC_Thread_Info));
|
|
||||||
((Scheme_Thread *)t)->gc_info = work;
|
|
||||||
work->owner = current_owner((Scheme_Custodian *)c);
|
|
||||||
work->thread = t;
|
|
||||||
|
|
||||||
work->next = GC->thread_infos;
|
|
||||||
GC->thread_infos = work;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void register_thread(void *t, void *c)
|
|
||||||
{
|
|
||||||
GC_Thread_Info *work;
|
|
||||||
|
|
||||||
work = ((Scheme_Thread *)t)->gc_info;
|
|
||||||
work->owner = current_owner((Scheme_Custodian *)c);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void mark_threads(int owner)
|
|
||||||
{
|
|
||||||
GC_Thread_Info *work;
|
|
||||||
|
|
||||||
for(work = GC->thread_infos; work; work = work->next)
|
|
||||||
if(work->owner == owner) {
|
|
||||||
if (((Scheme_Thread *)work->thread)->running) {
|
|
||||||
GC->normal_thread_mark(work->thread);
|
|
||||||
if (work->thread == scheme_current_thread) {
|
|
||||||
GC_mark_variable_stack(GC_variable_stack, 0, get_stack_base(), NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void clean_up_thread_list(void)
|
|
||||||
{
|
|
||||||
GC_Thread_Info *work = GC->thread_infos;
|
|
||||||
GC_Thread_Info *prev = NULL;
|
|
||||||
|
|
||||||
while(work) {
|
|
||||||
if(!pagemap_find_page(GC->page_maps, work->thread) || marked(work->thread)) {
|
|
||||||
work->thread = GC_resolve(work->thread);
|
|
||||||
prev = work;
|
|
||||||
work = work->next;
|
|
||||||
} else {
|
|
||||||
GC_Thread_Info *next = work->next;
|
|
||||||
|
|
||||||
if(prev) prev->next = next;
|
|
||||||
if(!prev) GC->thread_infos = next;
|
|
||||||
free(work);
|
|
||||||
work = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int thread_get_owner(void *p)
|
|
||||||
{
|
|
||||||
return ((Scheme_Thread *)p)->gc_info->owner;
|
|
||||||
}
|
|
||||||
#include "blame_the_child.c"
|
|
||||||
|
|
||||||
int GC_set_account_hook(int type, void *c1, unsigned long b, void *c2)
|
|
||||||
{
|
|
||||||
set_account_hook(type, c1, c2, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NEWGC_BTC_ACCOUNT
|
|
||||||
# define register_thread(t,c) /* */
|
|
||||||
# define register_new_thread(t,c) /* */
|
|
||||||
# define clean_up_thread_list() /* */
|
# define clean_up_thread_list() /* */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void GC_register_root_custodian(void *c)
|
||||||
|
{
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_register_root_custodian(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int GC_set_account_hook(int type, void *c1, unsigned long b, void *c2)
|
||||||
|
{
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_add_account_hook(type, c1, c2, b);
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GC_register_thread(void *t, void *c)
|
void GC_register_thread(void *t, void *c)
|
||||||
{
|
{
|
||||||
register_thread(t, c);
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_register_thread(t, c);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
void GC_register_new_thread(void *t, void *c)
|
void GC_register_new_thread(void *t, void *c)
|
||||||
{
|
{
|
||||||
register_new_thread(t, c);
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_register_new_thread(t, c);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -1417,20 +1369,12 @@ void GC_register_traversers(short tag, Size_Proc size, Mark_Proc mark,
|
||||||
|
|
||||||
long GC_get_memory_use(void *o)
|
long GC_get_memory_use(void *o)
|
||||||
{
|
{
|
||||||
Scheme_Object *arg = (Scheme_Object*)o;
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
unsigned long retval = 0;
|
if(o) {
|
||||||
|
return BTC_get_memory_use(o);
|
||||||
if(arg) {
|
|
||||||
if(SCHEME_PROCP(arg)) {
|
|
||||||
retval = 0;
|
|
||||||
} else if(SAME_TYPE(SCHEME_TYPE(arg), scheme_custodian_type)) {
|
|
||||||
retval = custodian_usage(arg);
|
|
||||||
}
|
}
|
||||||
} else {
|
#endif
|
||||||
retval = gen0_size_in_use() + GC->memory_in_use;
|
return gen0_size_in_use() + GC->memory_in_use;
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -1459,7 +1403,11 @@ void GC_mark(const void *const_p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* toss this over to the BTC mark routine if we're doing accounting */
|
/* toss this over to the BTC mark routine if we're doing accounting */
|
||||||
if(GC->doing_memory_accounting) { memory_account_mark(page,p); return; }
|
if(GC->doing_memory_accounting) {
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_memory_account_mark(page, p); return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if(page->big_page) {
|
if(page->big_page) {
|
||||||
/* This is a bigpage. The first thing we do is see if its been marked
|
/* This is a bigpage. The first thing we do is see if its been marked
|
||||||
|
@ -1490,7 +1438,9 @@ void GC_mark(const void *const_p)
|
||||||
|
|
||||||
/* if we're doing memory accounting, then we need to make sure the
|
/* if we're doing memory accounting, then we need to make sure the
|
||||||
btc_mark is right */
|
btc_mark is right */
|
||||||
set_btc_mark(NUM(page->addr) + PREFIX_SIZE);
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_set_btc_mark(NUM(page->addr) + PREFIX_SIZE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
page->marked_on = 1;
|
page->marked_on = 1;
|
||||||
|
@ -1589,7 +1539,9 @@ void GC_mark(const void *const_p)
|
||||||
((struct objhead *)newplace)->mark = 1;
|
((struct objhead *)newplace)->mark = 1;
|
||||||
/* if we're doing memory accounting, then we need the btc_mark
|
/* if we're doing memory accounting, then we need the btc_mark
|
||||||
to be set properly */
|
to be set properly */
|
||||||
set_btc_mark(newplace);
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_set_btc_mark(newplace);
|
||||||
|
#endif
|
||||||
/* drop the new location of the object into the forwarding space
|
/* drop the new location of the object into the forwarding space
|
||||||
and into the mark queue */
|
and into the mark queue */
|
||||||
newplace = PTR(NUM(newplace) + WORD_SIZE);
|
newplace = PTR(NUM(newplace) + WORD_SIZE);
|
||||||
|
@ -2421,9 +2373,9 @@ static void garbage_collect(int force_full)
|
||||||
/* do some cleanup structures that either change state based on the
|
/* do some cleanup structures that either change state based on the
|
||||||
heap state after collection or that become useless based on changes
|
heap state after collection or that become useless based on changes
|
||||||
in state after collection */
|
in state after collection */
|
||||||
clean_up_thread_list();
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
clean_up_owner_table();
|
BTC_clean_up();
|
||||||
clean_up_account_hooks();
|
#endif
|
||||||
TIME_STEP("cleaned");
|
TIME_STEP("cleaned");
|
||||||
repair_finalizer_structs();
|
repair_finalizer_structs();
|
||||||
repair_weak_finalizer_structs();
|
repair_weak_finalizer_structs();
|
||||||
|
@ -2437,8 +2389,10 @@ static void garbage_collect(int force_full)
|
||||||
TIME_STEP("cleaned heap");
|
TIME_STEP("cleaned heap");
|
||||||
reset_nursery();
|
reset_nursery();
|
||||||
TIME_STEP("reset nursurey");
|
TIME_STEP("reset nursurey");
|
||||||
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
if (gc->gc_full)
|
if (gc->gc_full)
|
||||||
do_btc_accounting();
|
BTC_do_accounting();
|
||||||
|
#endif
|
||||||
TIME_STEP("accounted");
|
TIME_STEP("accounted");
|
||||||
if (gc->generations_available)
|
if (gc->generations_available)
|
||||||
protect_old_pages();
|
protect_old_pages();
|
||||||
|
@ -2513,7 +2467,9 @@ static void garbage_collect(int force_full)
|
||||||
f->f(f->p, f->data);
|
f->f(f->p, f->data);
|
||||||
GC_variable_stack = saved_gc_variable_stack;
|
GC_variable_stack = saved_gc_variable_stack;
|
||||||
}
|
}
|
||||||
run_account_hooks();
|
#ifdef NEWGC_BTC_ACCOUNT
|
||||||
|
BTC_run_account_hooks();
|
||||||
|
#endif
|
||||||
gc->running_finalizers = 0;
|
gc->running_finalizers = 0;
|
||||||
|
|
||||||
gc->park[0] = gc->park_save[0];
|
gc->park[0] = gc->park_save[0];
|
||||||
|
|
|
@ -1,41 +1,5 @@
|
||||||
#include "commongc_internal.h"
|
#include "commongc_internal.h"
|
||||||
|
#include "gc2_obj.h"
|
||||||
#if defined(MZ_PRECISE_GC) && !defined(USE_COMPACT_3M_GC)
|
|
||||||
|
|
||||||
/* This is the log base 2 of the standard memory page size. 14 means 2^14,
|
|
||||||
which is 16k. This seems to be a good size for most platforms.
|
|
||||||
Under Windows as of 2008, however, the allocation granularity is 64k. */
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define LOG_APAGE_SIZE 16
|
|
||||||
#else
|
|
||||||
# define LOG_APAGE_SIZE 14
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
|
||||||
# define OBJH_WORD_SIZE 8
|
|
||||||
#else
|
|
||||||
# define OBJH_WORD_SIZE 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct objhead {
|
|
||||||
unsigned long hash : ((8*OBJH_WORD_SIZE) - (4+3+LOG_APAGE_SIZE));
|
|
||||||
/* the type and size of the object */
|
|
||||||
unsigned long type : 3;
|
|
||||||
/* these are the various mark bits we use */
|
|
||||||
unsigned long mark : 1;
|
|
||||||
unsigned long btc_mark : 1;
|
|
||||||
/* these are used for compaction et al*/
|
|
||||||
unsigned long moved : 1;
|
|
||||||
unsigned long dead : 1;
|
|
||||||
unsigned long size : LOG_APAGE_SIZE;
|
|
||||||
};
|
|
||||||
|
|
||||||
XFORM_NONGCING extern int GC_is_allocated(void *p);
|
|
||||||
|
|
||||||
#define OBJHEAD_HAS_HASH_BITS
|
|
||||||
#define OBJHEAD_HASH_BITS(p) ((struct objhead *)((void **)p - 1))->hash
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct mpage {
|
typedef struct mpage {
|
||||||
struct mpage *next;
|
struct mpage *next;
|
||||||
|
@ -83,6 +47,26 @@ typedef struct GC_Thread_Info {
|
||||||
struct GC_Thread_Info *next;
|
struct GC_Thread_Info *next;
|
||||||
} GC_Thread_Info;
|
} GC_Thread_Info;
|
||||||
|
|
||||||
|
typedef struct AccountHook {
|
||||||
|
int type;
|
||||||
|
void *c1;
|
||||||
|
void *c2;
|
||||||
|
unsigned long amount;
|
||||||
|
struct AccountHook *next;
|
||||||
|
} AccountHook;
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct ot_entry {
|
||||||
|
Scheme_Custodian *originator;
|
||||||
|
Scheme_Custodian **members;
|
||||||
|
unsigned long memory_use;
|
||||||
|
unsigned long single_time_limit;
|
||||||
|
unsigned long super_required;
|
||||||
|
char limit_set;
|
||||||
|
char required_set;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
#ifdef SIXTY_FOUR_BIT_INTEGERS
|
||||||
typedef mpage ****PageMap;
|
typedef mpage ****PageMap;
|
||||||
#else
|
#else
|
||||||
|
@ -138,8 +122,11 @@ typedef struct NewGC {
|
||||||
unsigned int reset_required :1;
|
unsigned int reset_required :1;
|
||||||
unsigned int kill_propagation_loop :1;
|
unsigned int kill_propagation_loop :1;
|
||||||
unsigned int current_mark_owner;
|
unsigned int current_mark_owner;
|
||||||
//static struct ot_entry **owner_table = NULL;
|
/* ot_entry **owner_table; */
|
||||||
unsigned int owner_table_top;
|
unsigned int owner_table_top;
|
||||||
|
AccountHook *hooks;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long number_of_gc_runs;
|
unsigned long number_of_gc_runs;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user