提交 c906b754 编写于 作者: J Jonathan Chambers

Initial work for concurrent Boehm with memory copy.

上级 f9fe25b7
...@@ -581,9 +581,13 @@ int n; ...@@ -581,9 +581,13 @@ int n;
register hdr * thishdr; /* Header corr. to hbp */ register hdr * thishdr; /* Header corr. to hbp */
size_t size_needed; /* number of bytes in requested objects */ size_t size_needed; /* number of bytes in requested objects */
size_t size_avail; /* bytes available in this block */ size_t size_avail; /* bytes available in this block */
size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz); size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz);
#ifdef DOPPELGANGER
if(kind != PTRFREE)
size_needed *= 2;
#endif
/* search for a big enough block in free list */ /* search for a big enough block in free list */
hbp = GC_hblkfreelist[n]; hbp = GC_hblkfreelist[n];
for(; 0 != hbp; hbp = hhdr -> hb_next) { for(; 0 != hbp; hbp = hhdr -> hb_next) {
...@@ -764,8 +768,9 @@ int n; ...@@ -764,8 +768,9 @@ int n;
} }
GC_large_free_bytes -= size_needed; GC_large_free_bytes -= size_needed;
GC_ASSERT(IS_MAPPED(hhdr)); GC_ASSERT(IS_MAPPED(hhdr));
return( hbp ); return( hbp );
} }
...@@ -791,6 +796,10 @@ signed_word size; ...@@ -791,6 +796,10 @@ signed_word size;
size = hhdr->hb_sz; size = hhdr->hb_sz;
size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size); size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size);
GC_remove_counts(hbp, (word)size); GC_remove_counts(hbp, (word)size);
#ifdef DOPPELGANGER
if(hhdr->hb_obj_kind != PTRFREE)
size *= 2;
#endif
hhdr->hb_sz = size; hhdr->hb_sz = size;
# ifdef USE_MUNMAP # ifdef USE_MUNMAP
hhdr -> hb_last_reclaimed = GC_gc_no; hhdr -> hb_last_reclaimed = GC_gc_no;
......
...@@ -391,14 +391,24 @@ static int set_realtime (int nanoseconds) ...@@ -391,14 +391,24 @@ static int set_realtime (int nanoseconds)
GC_bool GC_try_to_collect_inner(stop_func) GC_bool GC_try_to_collect_inner(stop_func)
GC_stop_func stop_func; GC_stop_func stop_func;
{ {
char buf[1024];
CLOCK_TYPE time1;
CLOCK_TYPE time2;
CLOCK_TYPE time3;
CLOCK_TYPE time4;
# ifdef CONDPRINT # ifdef CONDPRINT
CLOCK_TYPE start_time, current_time; CLOCK_TYPE start_time, current_time;
# endif # endif
if (GC_dont_gc) return FALSE; if (GC_dont_gc) return FALSE;
GET_TIME(time1);
if (GC_notify_event) if (GC_notify_event)
GC_notify_event (GC_EVENT_START); GC_notify_event (GC_EVENT_START);
#ifdef DOPPELGANGER_CONCURRENT
GC_complete_last();
#endif
GET_TIME(time2);
if (GC_incremental && GC_collection_in_progress()) { if (GC_incremental && GC_collection_in_progress()) {
# ifdef CONDPRINT # ifdef CONDPRINT
if (GC_print_stats) { if (GC_print_stats) {
...@@ -439,6 +449,7 @@ GC_stop_func stop_func; ...@@ -439,6 +449,7 @@ GC_stop_func stop_func;
} }
GC_invalidate_mark_state(); /* Flush mark stack. */ GC_invalidate_mark_state(); /* Flush mark stack. */
GC_clear_marks(); GC_clear_marks();
GET_TIME(time3);
# ifdef SAVE_CALL_CHAIN_IN_GC # ifdef SAVE_CALL_CHAIN_IN_GC
GC_save_callers(GC_last_stack); GC_save_callers(GC_last_stack);
# endif # endif
...@@ -454,7 +465,9 @@ GC_stop_func stop_func; ...@@ -454,7 +465,9 @@ GC_stop_func stop_func;
/* finish incrementally. */ /* finish incrementally. */
return(FALSE); return(FALSE);
} }
#ifndef DOPPELGANGER_CONCURRENT
GC_finish_collection(); GC_finish_collection();
#endif
# if defined(CONDPRINT) # if defined(CONDPRINT)
if (GC_print_stats) { if (GC_print_stats) {
GET_TIME(current_time); GET_TIME(current_time);
...@@ -464,6 +477,12 @@ GC_stop_func stop_func; ...@@ -464,6 +477,12 @@ GC_stop_func stop_func;
# endif # endif
if (GC_notify_event) if (GC_notify_event)
GC_notify_event (GC_EVENT_END); GC_notify_event (GC_EVENT_END);
GET_TIME(time4);
sprintf(buf, "Collection complete %lu us clear %lu us finish %lu us\n",
US_TIME_DIFF(time2,time1),
US_TIME_DIFF(time3,time2),
US_TIME_DIFF(time4,time3));
OutputDebugStringA(buf);
return(TRUE); return(TRUE);
} }
...@@ -539,6 +558,10 @@ int GC_collect_a_little GC_PROTO(()) ...@@ -539,6 +558,10 @@ int GC_collect_a_little GC_PROTO(())
return(result); return(result);
} }
#ifdef DOPPELGANGER_CONCURRENT
extern int GC_mark_state;
#endif
/* /*
* Assumes lock is held, signals are disabled. * Assumes lock is held, signals are disabled.
* We stop the world. * We stop the world.
...@@ -605,6 +628,13 @@ GC_stop_func stop_func; ...@@ -605,6 +628,13 @@ GC_stop_func stop_func;
return(FALSE); return(FALSE);
} }
if (GC_mark_some((ptr_t)(&dummy))) break; if (GC_mark_some((ptr_t)(&dummy))) break;
#ifdef DOPPELGANGER_CONCURRENT
if (GC_mark_state == 3)
{
GC_doppelgang_mark();
break;
}
#endif
} }
GC_gc_no++; GC_gc_no++;
......
...@@ -180,7 +180,7 @@ DCL_LOCK_STATE; ...@@ -180,7 +180,7 @@ DCL_LOCK_STATE;
*(void **)op = ptr_to_struct_containing_descr; *(void **)op = ptr_to_struct_containing_descr;
UNLOCK(); UNLOCK();
} }
return((GC_PTR) op); return(GC_premark((GC_PTR) op));
} }
/* Similar to GC_gcj_malloc, but add debug info. This is allocated */ /* Similar to GC_gcj_malloc, but add debug info. This is allocated */
...@@ -239,7 +239,7 @@ DCL_LOCK_STATE; ...@@ -239,7 +239,7 @@ DCL_LOCK_STATE;
} }
*(void **)op = ptr_to_struct_containing_descr; *(void **)op = ptr_to_struct_containing_descr;
UNLOCK(); UNLOCK();
return((GC_PTR) op); return(GC_premark((GC_PTR) op));
} }
/* And a debugging version of the above: */ /* And a debugging version of the above: */
...@@ -311,7 +311,7 @@ DCL_LOCK_STATE; ...@@ -311,7 +311,7 @@ DCL_LOCK_STATE;
} }
UNLOCK(); UNLOCK();
} }
return((GC_PTR) op); return(GC_premark((GC_PTR) op));
} }
#else #else
......
...@@ -212,6 +212,7 @@ register struct hblk * h; ...@@ -212,6 +212,7 @@ register struct hblk * h;
# ifdef USE_MUNMAP # ifdef USE_MUNMAP
result -> hb_last_reclaimed = GC_gc_no; result -> hb_last_reclaimed = GC_gc_no;
# endif # endif
result -> hb_obj_kind = PTRFREE;
return(result); return(result);
} }
......
...@@ -150,6 +150,12 @@ mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp)); ...@@ -150,6 +150,12 @@ mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp));
# define ADD_TO_COMPOSITE(sz) # define ADD_TO_COMPOSITE(sz)
# endif # endif
#ifdef DOPPELGANGER
word * GC_doppelganger_for(word *obj, hdr * hhdr);
#else
#define GC_doppelganger_for(obj,hhdr) (obj)
#endif
/* Push the object obj with corresponding heap block header hhdr onto */ /* Push the object obj with corresponding heap block header hhdr onto */
/* the mark stack. */ /* the mark stack. */
# define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \ # define PUSH_OBJ(obj, hhdr, mark_stack_top, mark_stack_limit) \
...@@ -164,7 +170,7 @@ mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp)); ...@@ -164,7 +170,7 @@ mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp));
if (mark_stack_top >= mark_stack_limit) { \ if (mark_stack_top >= mark_stack_limit) { \
mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top); \ mark_stack_top = GC_signal_mark_stack_overflow(mark_stack_top); \
} \ } \
mark_stack_top -> mse_start = (obj); \ mark_stack_top -> mse_start = GC_doppelganger_for(obj, hhdr); \
mark_stack_top -> mse_descr = _descr; \ mark_stack_top -> mse_descr = _descr; \
} \ } \
} }
......
...@@ -309,9 +309,30 @@ long GC_time_diff_ms(uint64_t a, uint64_t b); ...@@ -309,9 +309,30 @@ long GC_time_diff_ms(uint64_t a, uint64_t b);
# if defined(MSWIN32) || defined(MSWINCE) # if defined(MSWIN32) || defined(MSWINCE)
# include <windows.h> # include <windows.h>
# include <winbase.h> # include <winbase.h>
# define CLOCK_TYPE DWORD # define CLOCK_TYPE LONGLONG
# define GET_TIME(x) x = GetTickCount() # define GET_TIME(x) QueryPerformanceCounter((LARGE_INTEGER*)&x)
# define MS_TIME_DIFF(a,b) ((long)((a)-(b))) static long time_diff_ms(LONGLONG a, LONGLONG b)
{
static LARGE_INTEGER frequency = {0};
static double freq;
if (!frequency.QuadPart) {
QueryPerformanceFrequency (&frequency);
freq = frequency.QuadPart / 1000.0;
}
return (long)((((LARGE_INTEGER*)&a)->QuadPart - ((LARGE_INTEGER*)&b)->QuadPart) / freq);
}
static long time_diff_us(LONGLONG a, LONGLONG b)
{
static LARGE_INTEGER frequency = {0};
static double freq;
if (!frequency.QuadPart) {
QueryPerformanceFrequency (&frequency);
freq = frequency.QuadPart / 1000000.0;
}
return (long)((((LARGE_INTEGER*)&a)->QuadPart - ((LARGE_INTEGER*)&b)->QuadPart) / freq);
}
# define MS_TIME_DIFF(a,b) time_diff_ms(a,b)
# define US_TIME_DIFF(a,b) time_diff_us(a,b)
# else /* !MSWIN32, !MSWINCE, !BSD_TIME */ # else /* !MSWIN32, !MSWINCE, !BSD_TIME */
# include <time.h> # include <time.h>
# if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4) # if !defined(__STDC__) && defined(SPARC) && defined(SUNOS4)
...@@ -1299,6 +1320,10 @@ struct hblk * GC_prev_block GC_PROTO((struct hblk * h)); ...@@ -1299,6 +1320,10 @@ struct hblk * GC_prev_block GC_PROTO((struct hblk * h));
/* use. */ /* use. */
void GC_mark_init GC_PROTO((void)); void GC_mark_init GC_PROTO((void));
void GC_clear_marks GC_PROTO((void)); /* Clear mark bits for all heap objects. */ void GC_clear_marks GC_PROTO((void)); /* Clear mark bits for all heap objects. */
#ifdef DOPPELGANGER_CONCURRENT
void GC_doppelgang_mark GC_PROTO((void));
void GC_doppelganger_clear_roots GC_PROTO((void));
#endif
void GC_invalidate_mark_state GC_PROTO((void)); void GC_invalidate_mark_state GC_PROTO((void));
/* Tell the marker that marked */ /* Tell the marker that marked */
/* objects may point to unmarked */ /* objects may point to unmarked */
...@@ -1811,6 +1836,12 @@ void GC_dirty_init GC_PROTO((void)); ...@@ -1811,6 +1836,12 @@ void GC_dirty_init GC_PROTO((void));
GC_API GC_bool GC_is_marked GC_PROTO((ptr_t p)); GC_API GC_bool GC_is_marked GC_PROTO((ptr_t p));
void GC_clear_mark_bit GC_PROTO((ptr_t p)); void GC_clear_mark_bit GC_PROTO((ptr_t p));
void GC_set_mark_bit GC_PROTO((ptr_t p)); void GC_set_mark_bit GC_PROTO((ptr_t p));
#ifdef DOPPELGANGER_CONCURRENT
GC_PTR GC_premark(GC_PTR val);
#else
#define GC_premark(val) (val)
#endif
/* Stubborn objects: */ /* Stubborn objects: */
void GC_read_changed GC_PROTO((void)); /* Analogous to GC_read_dirty */ void GC_read_changed GC_PROTO((void)); /* Analogous to GC_read_dirty */
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
typedef struct GC_undefined_struct * ptr_t; typedef struct GC_undefined_struct * ptr_t;
# endif # endif
#define DOPPELGANGER 1
#define DOPPELGANGER_CONCURRENT 1
/* Machine dependent parameters. Some tuning parameters can be found */ /* Machine dependent parameters. Some tuning parameters can be found */
/* near the top of gc_private.h. */ /* near the top of gc_private.h. */
......
...@@ -91,7 +91,7 @@ unsigned flags; ...@@ -91,7 +91,7 @@ unsigned flags;
/* Clear the whole block, in case of GC_realloc call. */ /* Clear the whole block, in case of GC_realloc call. */
BZERO(result, n_blocks * HBLKSIZE); BZERO(result, n_blocks * HBLKSIZE);
} }
return result; return GC_premark(result);
} }
/* allocate lb bytes for an object of kind k. */ /* allocate lb bytes for an object of kind k. */
...@@ -156,7 +156,7 @@ register ptr_t *opp; ...@@ -156,7 +156,7 @@ register ptr_t *opp;
GC_words_allocd += lw; GC_words_allocd += lw;
out: out:
return op; return GC_premark(op);
} }
/* Allocate a composite object of size n bytes. The caller guarantees */ /* Allocate a composite object of size n bytes. The caller guarantees */
...@@ -226,7 +226,7 @@ register int k; ...@@ -226,7 +226,7 @@ register int k;
if (0 == result) { if (0 == result) {
return((*GC_oom_fn)(lb)); return((*GC_oom_fn)(lb));
} else { } else {
return(result); return(GC_premark(result));
} }
} }
...@@ -259,15 +259,15 @@ DCL_LOCK_STATE; ...@@ -259,15 +259,15 @@ DCL_LOCK_STATE;
FASTLOCK(); FASTLOCK();
if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) { if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
FASTUNLOCK(); FASTUNLOCK();
return(GENERAL_MALLOC((word)lb, PTRFREE)); return(GC_premark(GENERAL_MALLOC((word)lb, PTRFREE)));
} }
/* See above comment on signals. */ /* See above comment on signals. */
*opp = obj_link(op); *opp = obj_link(op);
GC_words_allocd += lw; GC_words_allocd += lw;
FASTUNLOCK(); FASTUNLOCK();
return((GC_PTR) op); return(GC_premark((GC_PTR) op));
} else { } else {
return(GENERAL_MALLOC((word)lb, PTRFREE)); return(GC_premark(GENERAL_MALLOC((word)lb, PTRFREE)));
} }
} }
...@@ -294,7 +294,7 @@ DCL_LOCK_STATE; ...@@ -294,7 +294,7 @@ DCL_LOCK_STATE;
FASTLOCK(); FASTLOCK();
if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) { if( EXPECT(!FASTLOCK_SUCCEEDED() || (op = *opp) == 0, 0) ) {
FASTUNLOCK(); FASTUNLOCK();
return(GENERAL_MALLOC((word)lb, NORMAL)); return(GC_premark(GENERAL_MALLOC((word)lb, NORMAL)));
} }
/* See above comment on signals. */ /* See above comment on signals. */
GC_ASSERT(0 == obj_link(op) GC_ASSERT(0 == obj_link(op)
...@@ -306,9 +306,9 @@ DCL_LOCK_STATE; ...@@ -306,9 +306,9 @@ DCL_LOCK_STATE;
obj_link(op) = 0; obj_link(op) = 0;
GC_words_allocd += lw; GC_words_allocd += lw;
FASTUNLOCK(); FASTUNLOCK();
return((GC_PTR) op); return(GC_premark((GC_PTR) op));
} else { } else {
return(GENERAL_MALLOC((word)lb, NORMAL)); return(GC_premark(GENERAL_MALLOC((word)lb, NORMAL)));
} }
} }
......
...@@ -170,6 +170,13 @@ register hdr * hhdr; ...@@ -170,6 +170,13 @@ register hdr * hhdr;
# endif # endif
{ {
register hdr * hhdr = HDR(h); register hdr * hhdr = HDR(h);
#ifdef DOPPELGANGER
if(hhdr->hb_obj_kind != PTRFREE) {
size_t size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr->hb_sz);
memcpy((((char*)h)+size_needed), h, size_needed);
}
#endif
if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) return; if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) return;
/* Mark bit for these is cleared only once the object is */ /* Mark bit for these is cleared only once the object is */
...@@ -209,6 +216,13 @@ ptr_t p; ...@@ -209,6 +216,13 @@ ptr_t p;
return(mark_bit_from_hdr(hhdr, word_no)); return(mark_bit_from_hdr(hhdr, word_no));
} }
#ifdef DOPPELGANGER_CONCURRENT
GC_PTR GC_premark(GC_PTR val)
{
GC_set_mark_bit(val);
return val;
}
#endif
/* /*
* Clear mark bits in all allocated heap blocks. This invalidates * Clear mark bits in all allocated heap blocks. This invalidates
...@@ -595,6 +609,19 @@ mse * msp; ...@@ -595,6 +609,19 @@ mse * msp;
return(msp - GC_MARK_STACK_DISCARDS); return(msp - GC_MARK_STACK_DISCARDS);
} }
#ifdef DOPPELGANGER
word * GC_doppelganger_for(word *obj, hdr * hhdr)
{
word * my_current = obj;
if (hhdr->hb_obj_kind != PTRFREE) {
size_t offset = OBJ_SZ_TO_BLOCKS(hhdr->hb_sz) * HBLKSIZE;
my_current = (word*)(((ptr_t)obj) + offset);
}
return my_current;
}
#endif
/* /*
* Mark objects pointed to by the regions described by * Mark objects pointed to by the regions described by
* mark stack entries between GC_mark_stack and GC_mark_stack_top, * mark stack entries between GC_mark_stack and GC_mark_stack_top,
...@@ -669,6 +696,7 @@ mse * mark_stack_limit; ...@@ -669,6 +696,7 @@ mse * mark_stack_limit;
# endif /* PARALLEL_MARK */ # endif /* PARALLEL_MARK */
mark_stack_top -> mse_start = mark_stack_top -> mse_start =
limit = current_p + SPLIT_RANGE_WORDS-1; limit = current_p + SPLIT_RANGE_WORDS-1;
// TODO, do we need doppelganger lookup here?
mark_stack_top -> mse_descr = mark_stack_top -> mse_descr =
descr - WORDS_TO_BYTES(SPLIT_RANGE_WORDS-1); descr - WORDS_TO_BYTES(SPLIT_RANGE_WORDS-1);
/* Make sure that pointers overlapping the two ranges are */ /* Make sure that pointers overlapping the two ranges are */
...@@ -1184,6 +1212,28 @@ void GC_mark_init() ...@@ -1184,6 +1212,28 @@ void GC_mark_init()
alloc_mark_stack(INITIAL_MARK_STACK_SIZE); alloc_mark_stack(INITIAL_MARK_STACK_SIZE);
} }
#ifdef DOPPELGANGER
static HANDLE doppelganger_handle = 0;
static char* doppelganger_buffer = 0;
static int doppelganger_buffer_length = 1024*1024*10;
static int doppelganger_buffer_offset = 0;
static int doppelganger_roots_index = 0;
static char* doppelganger_roots[1024];
void GC_doppelganger_clear_roots()
{
int i;
for (i = 0; i < doppelganger_roots_index; i++)
{
//HeapFree(doppelganger_handle, 0, doppelganger_roots[i]);
//free(doppelganger_roots[i]);
doppelganger_roots[i] = NULL;
}
doppelganger_roots_index = 0;
doppelganger_buffer_offset = 0;
}
#endif
/* /*
* Push all locations between b and t onto the mark stack. * Push all locations between b and t onto the mark stack.
* b is the first location to be checked. t is one past the last * b is the first location to be checked. t is one past the last
...@@ -1209,8 +1259,22 @@ ptr_t top; ...@@ -1209,8 +1259,22 @@ ptr_t top;
length += GC_DS_TAGS; length += GC_DS_TAGS;
length &= ~GC_DS_TAGS; length &= ~GC_DS_TAGS;
# endif # endif
#ifdef DOPPELGANGER
if (!doppelganger_handle) {
doppelganger_handle = HeapCreate(0, GC_page_size*10, 0);
doppelganger_buffer = HeapAlloc(doppelganger_handle, 0, doppelganger_buffer_length);
}
doppelganger_roots[doppelganger_roots_index] = doppelganger_buffer + doppelganger_buffer_offset;
memcpy(doppelganger_roots[doppelganger_roots_index], bottom, length);
GC_mark_stack_top -> mse_start = (word *)doppelganger_roots[doppelganger_roots_index];
GC_mark_stack_top -> mse_descr = length;
doppelganger_roots_index++;
doppelganger_buffer_offset += length;
GC_ASSERT(doppelganger_buffer_offset < doppelganger_buffer_length);
#else
GC_mark_stack_top -> mse_start = (word *)bottom; GC_mark_stack_top -> mse_start = (word *)bottom;
GC_mark_stack_top -> mse_descr = length; GC_mark_stack_top -> mse_descr = length;
#endif
} }
/* /*
......
...@@ -576,6 +576,14 @@ ptr_t cold_gc_frame; ...@@ -576,6 +576,14 @@ ptr_t cold_gc_frame;
{ {
int i; int i;
int kind; int kind;
CLOCK_TYPE time1;
CLOCK_TYPE time2;
char buf[1024];
GET_TIME(time1);
#ifdef DOPPELGANGER
GC_doppelganger_clear_roots();
#endif
/* /*
* Next push static data. This must happen early on, since it's * Next push static data. This must happen early on, since it's
...@@ -650,5 +658,9 @@ ptr_t cold_gc_frame; ...@@ -650,5 +658,9 @@ ptr_t cold_gc_frame;
/* Note that without interior pointer recognition lots */ /* Note that without interior pointer recognition lots */
/* of stuff may have been pushed already, and this */ /* of stuff may have been pushed already, and this */
/* should be careful about mark stack overflows. */ /* should be careful about mark stack overflows. */
GET_TIME(time2);
//sprintf(buf, "push_roots %lu us\n", US_TIME_DIFF(time2,time1));
//OutputDebugStringA(buf);
} }
...@@ -967,7 +967,9 @@ int report_if_found; /* Abort if a GC_reclaimable object is found */ ...@@ -967,7 +967,9 @@ int report_if_found; /* Abort if a GC_reclaimable object is found */
/* Go through all heap blocks (in hblklist) and reclaim unmarked objects */ /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
/* or enqueue the block for later processing. */ /* or enqueue the block for later processing. */
GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found); GC_apply_to_all_blocks(GC_reclaim_block, (word)report_if_found);
#ifdef DOPPELGANGER_CONCURRENT
#define EAGER_SWEEP 1
#endif
# ifdef EAGER_SWEEP # ifdef EAGER_SWEEP
/* This is a very stupid thing to do. We make it possible anyway, */ /* This is a very stupid thing to do. We make it possible anyway, */
/* so that you can convince yourself that it really is very stupid. */ /* so that you can convince yourself that it really is very stupid. */
......
...@@ -668,7 +668,7 @@ DCL_LOCK_STATE; ...@@ -668,7 +668,7 @@ DCL_LOCK_STATE;
} }
if (op != NULL) if (op != NULL)
((word *)op)[lw - 1] = d; ((word *)op)[lw - 1] = d;
return((GC_PTR) op); return(GC_premark((GC_PTR) op));
} }
#if defined(__STDC__) || defined(__cplusplus) #if defined(__STDC__) || defined(__cplusplus)
......
...@@ -36,6 +36,9 @@ typedef LONG * IE_t; ...@@ -36,6 +36,9 @@ typedef LONG * IE_t;
GC_bool GC_thr_initialized = FALSE; GC_bool GC_thr_initialized = FALSE;
DWORD GC_main_thread = 0; DWORD GC_main_thread = 0;
#ifdef DOPPELGANGER_CONCURRENT
DWORD GC_background_thread = 0;
#endif
extern GC_bool GC_use_dll_main; extern GC_bool GC_use_dll_main;
...@@ -495,6 +498,11 @@ void GC_push_all_stacks() ...@@ -495,6 +498,11 @@ void GC_push_all_stacks()
GC_push_all_stack(stack_min, thread->stack_base); GC_push_all_stack(stack_min, thread->stack_base);
} }
} }
#ifdef DOPPELGANGER_CONCURRENT
else if (thread -> id == thread_id && thread -> id == GC_background_thread) {
found_me = TRUE;
}
#endif
} }
if (!found_me) ABORT("Collecting from unknown thread."); if (!found_me) ABORT("Collecting from unknown thread.");
} }
...@@ -664,8 +672,57 @@ DWORD WINAPI main_thread_start(LPVOID arg) ...@@ -664,8 +672,57 @@ DWORD WINAPI main_thread_start(LPVOID arg)
# else /* !MSWINCE */ # else /* !MSWINCE */
#ifdef DOPPELGANGER_CONCURRENT
HANDLE start_mark_event;
HANDLE start_clean_event;
HANDLE finish_mark_event;
DWORD WINAPI BackgroundThread(LPVOID arg)
{
GC_thread me;
me = GC_new_thread();
GC_background_thread = GetCurrentThreadId();
me->should_scan = FALSE;
while(TRUE)
{
WaitForSingleObject(start_mark_event, INFINITE);
while(TRUE) {
int dummy = 0;
if (GC_mark_some((ptr_t)(&dummy))) break;
}
//if (!GC_stopped_mark(GC_never_stop_func)) {
// abort();
//}
WaitForSingleObject(start_clean_event, INFINITE);
GC_finish_collection();
SetEvent(finish_mark_event);
}
}
void GC_complete_last (void)
{
static int intialized = 0;
if (intialized) {
SetEvent(start_clean_event);
WaitForSingleObject(finish_mark_event, INFINITE);
}
intialized = 1;
}
void GC_doppelgang_mark (void)
{
//WaitForSingleObject(finish_mark_event, INFINITE);
SetEvent(start_mark_event);
}
#endif
/* Called by GC_init() - we hold the allocation lock. */ /* Called by GC_init() - we hold the allocation lock. */
void GC_thr_init() { void GC_thr_init() {
#ifdef DOPPELGANGER_CONCURRENT
DWORD thread_id = 0;
#endif
GC_thread me; GC_thread me;
if (GC_thr_initialized) return; if (GC_thr_initialized) return;
GC_main_thread = GetCurrentThreadId(); GC_main_thread = GetCurrentThreadId();
...@@ -674,6 +731,13 @@ void GC_thr_init() { ...@@ -674,6 +731,13 @@ void GC_thr_init() {
/* Add the initial thread, so we can stop it. */ /* Add the initial thread, so we can stop it. */
me = GC_new_thread(); me = GC_new_thread();
me->should_scan = TRUE; me->should_scan = TRUE;
#ifdef DOPPELGANGER_CONCURRENT
start_mark_event = CreateEvent(NULL, FALSE, FALSE, NULL);
start_clean_event = CreateEvent(NULL, FALSE, FALSE, NULL);
finish_mark_event = CreateEvent(NULL, FALSE, FALSE, NULL);
CreateThread(NULL, 0, &BackgroundThread, NULL, 0, &thread_id);
#endif
} }
#ifdef CYGWIN32 #ifdef CYGWIN32
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册