diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-12-12 06:58:49 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-12-12 06:58:49 -0800 |
commit | 4f0c5f1273cb756b886f3a63930e8aa8698aa5c2 (patch) | |
tree | 569784ba2e3fcadca9f19cc6961bb5a12a3ad0f5 /gc.c | |
parent | d05841efc07ad0300dbfe2d3f3d67131434a8e3c (diff) | |
download | txr-4f0c5f1273cb756b886f3a63930e8aa8698aa5c2.tar.gz txr-4f0c5f1273cb756b886f3a63930e8aa8698aa5c2.tar.bz2 txr-4f0c5f1273cb756b886f3a63930e8aa8698aa5c2.zip |
Cancel in-progress gc if handling async signal.
If a signal goes off in the middle of gc that is
routed to an async lambda handler, we should cancel
gc, so the handler finds the heap in a good state.
Of course, the handler must not return in this
case, or else the interrupted gc will try to resume.
* gc.c (inprogress): New static flag.
(gc): Increment and decrement inprogress variable.
Abort if re-entered.
(gc_inprogress): New function.
(unmark): Do not clear FREE flags, only REACHABLE.
(gc_cancel): New function.
* gc.h (gc_inprogress, gc_cancel): Declared.
* signal.c (sig_handler): In the async lambda
case, check for an in-progress gc and cancel it.
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 25 |
1 files changed, 24 insertions, 1 deletions
@@ -82,6 +82,7 @@ static alloc_bytes_t prev_malloc_bytes; alloc_bytes_t opt_gc_delta = DFL_MALLOC_DELTA_THRESH; int gc_enabled = 1; +static int inprogress; static struct fin_reg { struct fin_reg *next; @@ -690,6 +691,9 @@ void gc(void) assert (gc_enabled); + if (inprogress++) + assert(0 && "gc re-entered"); + #if CONFIG_GEN_GC if (malloc_bytes - prev_malloc_bytes >= opt_gc_delta) full_gc = 1; @@ -730,6 +734,8 @@ void gc(void) call_finals(); gc_enabled = 1; prev_malloc_bytes = malloc_bytes; + + inprogress--; } int gc_state(int enabled) @@ -739,6 +745,11 @@ int gc_state(int enabled) return old; } +int gc_inprogress(void) +{ + return inprogress; +} + void gc_init(val *stack_bottom) { gc_stack_bottom = stack_bottom; @@ -910,11 +921,23 @@ void unmark(void) block < end; block++) { - block->t.type = convert(type_t, block->t.type & ~(FREE | REACHABLE)); + block->t.type = convert(type_t, block->t.type & ~REACHABLE); } } } +void gc_cancel(void) +{ + unmark(); +#if CONFIG_GEN_GC + checkobj_idx = 0; + mutobj_idx = 0; + freshobj_idx = 0; + full_gc = 1; +#endif + inprogress = 0; +} + void dheap(heap_t *heap, int start, int end); void dheap(heap_t *heap, int start, int end) |