summaryrefslogtreecommitdiff
path: root/libguile/threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'libguile/threads.c')
-rw-r--r--libguile/threads.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/libguile/threads.c b/libguile/threads.c
index f39bcc39e..7902a9a0d 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -1,5 +1,5 @@
/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004,
- * 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
+ * 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
* Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -63,6 +63,7 @@
#include "libguile/fluids.h"
#include "libguile/continuations.h"
#include "libguile/gc.h"
+#include "libguile/gc-inline.h"
#include "libguile/init.h"
#include "libguile/scmsigs.h"
#include "libguile/strings.h"
@@ -95,6 +96,26 @@ thread_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
mark_stack_ptr, mark_stack_limit,
NULL);
+ /* The pointerless freelists are threaded through their first word,
+ but GC doesn't know to trace them (as they are pointerless), so we
+ need to do that here. See the comments at the top of libgc's
+ gc_inline.h. */
+ {
+ size_t n;
+ for (n = 0; n < SCM_INLINE_GC_FREELIST_COUNT; n++)
+ {
+ void *chain = t->pointerless_freelists[n];
+ if (chain)
+ {
+ /* The first link is already marked by the freelist vector,
+ so we just have to mark the tail. */
+ while ((chain = *(void **)chain))
+ mark_stack_ptr = GC_mark_and_push (chain, mark_stack_ptr,
+ mark_stack_limit, NULL);
+ }
+ }
+ }
+
if (t->vp)
mark_stack_ptr = scm_i_vm_mark_stack (t->vp, mark_stack_ptr,
mark_stack_limit);
@@ -389,6 +410,8 @@ guilify_self_1 (struct GC_stack_base *base)
t.mutexes = SCM_EOL;
t.held_mutex = NULL;
t.join_queue = SCM_EOL;
+ t.freelists = NULL;
+ t.pointerless_freelists = NULL;
t.dynamic_state = SCM_BOOL_F;
t.dynstack.base = NULL;
t.dynstack.top = NULL;
@@ -459,6 +482,12 @@ guilify_self_2 (SCM parent)
t->continuation_root = scm_cons (t->handle, SCM_EOL);
t->continuation_base = t->base;
+ {
+ size_t size = SCM_INLINE_GC_FREELIST_COUNT * sizeof (void *);
+ t->freelists = scm_gc_malloc (size, "freelists");
+ t->pointerless_freelists = scm_gc_malloc (size, "atomic freelists");
+ }
+
if (scm_is_true (parent))
t->dynamic_state = scm_make_dynamic_state (parent);
else