Allow the SMOB mark procedures to be called when libgc uses parallel markers.
authorLudovic Courtès <ludo@gnu.org>
Fri, 1 Mar 2013 16:45:17 +0000 (17:45 +0100)
committerLudovic Courtès <ludo@gnu.org>
Fri, 1 Mar 2013 16:50:05 +0000 (17:50 +0100)
Fixes <http://bugs.gnu.org/13611>.
Reported by Mike Gran <spk121@yahoo.com>.

* libguile/smob.c (current_mark_stack_pointer,
  current_mark_stack_limit): New variables.
  (smob_mark): Use CURRENT_MARK_STACK_POINTER and
  CURRENT_MARK_STACK_LIMIT instead of the same-named fields of
  `SCM_I_CURRENT_THREAD'.
  (scm_gc_mark): Likewise.
  (scm_smob_prehistory): Initialize CURRENT_MARK_STACK_LIMIT and
  CURRENT_MARK_STACK_POINTER.
* libguile/threads.h (scm_i_thread): Add comment that
  `current_mark_stack_ptr' and `current_mark_stack_limit' are no longer
  used.

libguile/smob.c
libguile/threads.h

index c2e8f24..90849a8 100644 (file)
@@ -1,5 +1,6 @@
-/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
- * 
+/* Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2004, 2006,
+ *   2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
  * as published by the Free Software Foundation; either version 3 of
@@ -284,6 +285,10 @@ scm_make_smob (scm_t_bits tc)
 /* The GC kind used for SMOB types that provide a custom mark procedure.  */
 static int smob_gc_kind;
 
+/* Mark stack pointer and limit, used by `scm_gc_mark'.  */
+static scm_i_pthread_key_t current_mark_stack_pointer;
+static scm_i_pthread_key_t current_mark_stack_limit;
+
 
 /* The generic SMOB mark procedure that gets called for SMOBs allocated
    with smob_gc_kind.  */
@@ -322,14 +327,14 @@ smob_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
     {
       SCM obj;
 
-      SCM_I_CURRENT_THREAD->current_mark_stack_ptr = mark_stack_ptr;
-      SCM_I_CURRENT_THREAD->current_mark_stack_limit = mark_stack_limit;
+      scm_i_pthread_setspecific (current_mark_stack_pointer, mark_stack_ptr);
+      scm_i_pthread_setspecific (current_mark_stack_limit, mark_stack_limit);
 
       /* Invoke the SMOB's mark procedure, which will in turn invoke
-        `scm_gc_mark ()', which may modify `current_mark_stack_ptr'.  */
+        `scm_gc_mark', which may modify `current_mark_stack_pointer'.  */
       obj = scm_smobs[smobnum].mark (cell);
 
-      mark_stack_ptr = SCM_I_CURRENT_THREAD->current_mark_stack_ptr;
+      mark_stack_ptr = scm_i_pthread_getspecific (current_mark_stack_pointer);
 
       if (SCM_NIMP (obj))
        /* Mark the returned object.  */
@@ -337,42 +342,35 @@ smob_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
                                           mark_stack_ptr,
                                           mark_stack_limit, NULL);
 
-      SCM_I_CURRENT_THREAD->current_mark_stack_limit = NULL;
-      SCM_I_CURRENT_THREAD->current_mark_stack_ptr = NULL;
+      scm_i_pthread_setspecific (current_mark_stack_pointer, NULL);
+      scm_i_pthread_setspecific (current_mark_stack_limit, NULL);
     }
 
   return mark_stack_ptr;
 
 }
 
-/* Mark object O.  We assume that this function is only called during the
-   mark phase, i.e., from within `smob_mark ()' or one of its
-   descendents.  */
+/* Mark object O.  We assume that this function is only called during the mark
+   phase, i.e., from within `smob_mark' or one of its descendants.  */
 void
 scm_gc_mark (SCM o)
 {
-#define CURRENT_MARK_PTR                                                \
-  ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_ptr))
-#define CURRENT_MARK_LIMIT                                                \
-  ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_limit))
-
   if (SCM_NIMP (o))
     {
-      /* At this point, the `current_mark_*' fields of the current thread
-        must be defined (they are set in `smob_mark ()').  */
-      register struct GC_ms_entry *mark_stack_ptr;
+      void *mark_stack_ptr, *mark_stack_limit;
 
-      if (!CURRENT_MARK_PTR)
+      mark_stack_ptr = scm_i_pthread_getspecific (current_mark_stack_pointer);
+      mark_stack_limit = scm_i_pthread_getspecific (current_mark_stack_limit);
+
+      if (mark_stack_ptr == NULL)
        /* The function was not called from a mark procedure.  */
        abort ();
 
       mark_stack_ptr = GC_MARK_AND_PUSH (SCM2PTR (o),
-                                        CURRENT_MARK_PTR, CURRENT_MARK_LIMIT,
+                                        mark_stack_ptr, mark_stack_limit,
                                         NULL);
-      SCM_I_CURRENT_THREAD->current_mark_stack_ptr = mark_stack_ptr;
+      scm_i_pthread_setspecific (current_mark_stack_pointer, mark_stack_ptr);
     }
-#undef CURRENT_MARK_PTR
-#undef CURRENT_MARK_LIMIT
 }
 
 \f
@@ -473,6 +471,9 @@ scm_smob_prehistory ()
 {
   long i;
 
+  scm_i_pthread_key_create (&current_mark_stack_pointer, NULL);
+  scm_i_pthread_key_create (&current_mark_stack_limit, NULL);
+
   smob_gc_kind = GC_new_kind (GC_new_free_list (),
                              GC_MAKE_PROC (GC_new_proc (smob_mark), 0),
                              0,
index ec129bc..901c37b 100644 (file)
@@ -3,7 +3,8 @@
 #ifndef SCM_THREADS_H
 #define SCM_THREADS_H
 
-/* Copyright (C) 1996,1997,1998,2000,2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2006,
+ *   2007, 2008, 2009, 2011, 2013 Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -71,8 +72,8 @@ typedef struct scm_i_thread {
   scm_i_pthread_cond_t sleep_cond;
   int sleep_fd, sleep_pipe[2];
 
-  /* Information about the Boehm-GC mark stack during the mark phase.  This
-     is used by `scm_gc_mark ()'.  */
+  /* XXX: These two fields used to hold information about the BDW-GC
+     mark stack during the mark phase.  They are no longer used.  */
   void *current_mark_stack_ptr;
   void *current_mark_stack_limit;