summaryrefslogtreecommitdiffstats
path: root/gc.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-12-12 06:58:49 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-12-12 06:58:49 -0800
commit4f0c5f1273cb756b886f3a63930e8aa8698aa5c2 (patch)
tree569784ba2e3fcadca9f19cc6961bb5a12a3ad0f5 /gc.c
parentd05841efc07ad0300dbfe2d3f3d67131434a8e3c (diff)
downloadtxr-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.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/gc.c b/gc.c
index 2bffb65f..048163fb 100644
--- a/gc.c
+++ b/gc.c
@@ -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)