Merge branch 'master' into boehm-demers-weiser-gc
authorLudovic Courtès <ludo@gnu.org>
Wed, 10 Sep 2008 21:09:30 +0000 (23:09 +0200)
committerLudovic Courtès <ludo@gnu.org>
Wed, 10 Sep 2008 21:09:30 +0000 (23:09 +0200)
Conflicts:
libguile/Makefile.am
libguile/coop-defs.h
libguile/gc-card.c
libguile/gc-freelist.c
libguile/gc-malloc.c
libguile/gc-mark.c
libguile/gc-segment.c
libguile/gc.c
libguile/gc.h
libguile/gc_os_dep.c
libguile/hashtab.c
libguile/hashtab.h
libguile/inline.h
libguile/private-gc.h
libguile/struct.c
libguile/struct.h
libguile/threads.c
libguile/threads.h
libguile/vectors.h
libguile/weaks.h
test-suite/tests/gc.test

32 files changed:
1  2 
configure.in
libguile/Makefile.am
libguile/continuations.c
libguile/coop-pthreads.h
libguile/environments.h
libguile/eval.c
libguile/fports.c
libguile/gc-malloc.c
libguile/gc.c
libguile/gc.h
libguile/goops.c
libguile/hashtab.c
libguile/hashtab.h
libguile/hooks.c
libguile/inline.h
libguile/modules.c
libguile/numbers.c
libguile/ports.c
libguile/private-gc.h
libguile/procs.h
libguile/root.h
libguile/srcprop.c
libguile/strings.c
libguile/struct.c
libguile/struct.h
libguile/threads.c
libguile/threads.h
libguile/vectors.h
libguile/weaks.c
libguile/weaks.h
test-suite/Makefile.am
test-suite/tests/gc.test

diff --cc configure.in
@@@ -1027,25 -1152,31 +1152,43 @@@ GUILE_STRUCT_UTIMBU
  #--------------------------------------------------------------------
  
  SCM_I_GSC_STACK_GROWS_UP=0
- AC_TRY_RUN(aux (l) unsigned long l;
-            { int x; exit (l >= ((unsigned long)&x)); }
-          main () { int q; aux((unsigned long)&q); },
-            [SCM_I_GSC_STACK_GROWS_UP=1],
-          [],
-            [AC_MSG_WARN(Guessing that stack grows down -- see scmconfig.h)])
+ AC_RUN_IFELSE([AC_LANG_SOURCE(
+ [AC_INCLUDES_DEFAULT
+ int
+ find_stack_direction ()
+ {
+   static char *addr = 0;
+   auto char dummy;
+   if (addr == 0)
+     {
+       addr = &dummy;
+       return find_stack_direction ();
+     }
+   else
+     return (&dummy > addr) ? 1 : -1;
+ }
+ int
+ main ()
+ {
+   return find_stack_direction () < 0;
+ }])],
+              [SCM_I_GSC_STACK_GROWS_UP=1],
+              [],
+              [AC_MSG_WARN(Guessing that stack grows down -- see scmconfig.h)])
  
 +#--------------------------------------------------------------------
 +#
 +# Boehm's GC library
 +#
 +#--------------------------------------------------------------------
 +AC_CHECK_LIB([gc], [GC_collect_a_little],
 +  [LIBS="-lgc $LIBS"],
 +  [AC_MSG_ERROR([`libgc' (Boehm's GC library) not found.])])
 +AC_CHECK_HEADER([gc/gc.h], [],
 +  [AC_MSG_ERROR([`libgc' (Boehm's GC library) header files not found.])])
 +
 +
  AC_CHECK_SIZEOF(float)
  if test "$ac_cv_sizeof_float" -le "$ac_cv_sizeof_long"; then
      AC_DEFINE(SCM_SINGLES, 1, 
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc libguile/eval.c
Simple merge
Simple merge
Simple merge
diff --cc libguile/gc.c
@@@ -327,27 -388,41 +327,26 @@@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0
                scm_cons (sym_cells_swept,
                          scm_from_double (local_scm_gc_cells_swept)),
                scm_cons (sym_malloc_yield,
-                         scm_from_long(local_scm_gc_malloc_yield_percentage)),
+                         scm_from_long (local_scm_gc_malloc_yield_percentage)),
                scm_cons (sym_cell_yield,
                          scm_from_long (local_scm_gc_cell_yield_percentage)),
 -              scm_cons (sym_protected_objects,
 -                        scm_from_ulong (local_protected_obj_count)),
                scm_cons (sym_heap_segments, heap_segs),
 +#endif
 +              scm_cons (sym_heap_size, scm_from_size_t (heap_size)),
 +              scm_cons (sym_heap_free_size, scm_from_size_t (free_bytes)),
 +              scm_cons (sym_heap_total_allocated,
 +                        scm_from_size_t (total_bytes)),
 +              scm_cons (sym_protected_objects,
 +                        scm_from_ulong (protected_obj_count)),
 +              scm_cons (sym_times, scm_from_size_t (gc_times)),
                SCM_UNDEFINED);
 -  SCM_CRITICAL_SECTION_END;
 -  
 -  free (bounds);
 +
    return answer;
  }
  #undef FUNC_NAME
  
 -/*
 -  Update nice-to-know-statistics.
 - */
 -static void
 -gc_end_stats ()
 -{
 -  /* CELLS SWEPT is another word for the number of cells that were examined
 -     during GC. YIELD is the number that we cleaned out. MARKED is the number
 -     that weren't cleaned.  */
 -  scm_gc_cell_yield_percentage = (scm_i_gc_sweep_stats.collected * 100) /
 -    (scm_i_master_freelist.heap_total_cells + scm_i_master_freelist2.heap_total_cells);
 -
 -  scm_gc_cells_allocated_acc +=
 -    (double) scm_i_gc_sweep_stats.collected;
 -  scm_gc_cells_marked_acc += (double) scm_cells_allocated;
 -  scm_gc_cells_marked_conservatively_acc += (double) scm_i_find_heap_calls;
 -  scm_gc_cells_swept_acc += (double) scm_i_gc_sweep_stats.swept;
 -
 -  ++scm_gc_times;
 -}
 +
  
  SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
              (SCM obj),
            "Return an integer that for the lifetime of @var{obj} is uniquely\n"
diff --cc libguile/gc.h
@@@ -3,7 -3,7 +3,7 @@@
  #ifndef SCM_GC_H
  #define SCM_GC_H
  
- /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
 -/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
++/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2002, 2003, 2004, 2006, 2007, 2008 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
Simple merge
@@@ -486,18 -451,11 +486,20 @@@ scm_hash_fn_create_handle_x (SCM table
    k = hash_fn (obj, SCM_SIMPLE_VECTOR_LENGTH (buckets), closure);
    if (k >= SCM_SIMPLE_VECTOR_LENGTH (buckets))
      scm_out_of_range ("hash_fn_create_handle_x", scm_from_ulong (k));
 -  it = assoc_fn (obj, SCM_SIMPLE_VECTOR_REF (buckets, k), closure);
 -  if (scm_is_pair (it))
 +
 +  weak = IS_WEAK_THING (table);
 +  alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
 +  if (weak)
 +    START_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
 +
 +  it = assoc_fn (obj, alist, closure);
 +  if (weak)
 +    END_WEAK_BUCKET_FIXUP (table, buckets, k, alist, hash_fn);
 +
 +  if (scm_is_true (it))
      return it;
+   else if (scm_is_true (it))
+     scm_wrong_type_arg_msg (NULL, 0, it, "a pair");
    else
      {
        /* When this is a weak hashtable, running the GC can change it.
@@@ -93,7 -96,9 +93,8 @@@ SCM_API SCM scm_weak_key_hash_table_p (
  SCM_API SCM scm_weak_value_hash_table_p (SCM h);
  SCM_API SCM scm_doubly_weak_hash_table_p (SCM h);
  
- SCM_API void scm_i_rehash (SCM table, unsigned long (*hash_fn)(), void *closure, const char*func_name);
+ SCM_INTERNAL void scm_i_rehash (SCM table, unsigned long (*hash_fn)(),
+                               void *closure, const char *func_name);
 -SCM_INTERNAL void scm_i_scan_weak_hashtables (void);
  
  SCM_API SCM scm_hash_fn_get_handle (SCM table, SCM obj, unsigned long (*hash_fn) (), SCM (*assoc_fn) (), void * closure);
  SCM_API SCM scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init, unsigned long (*hash_fn) (), SCM (*assoc_fn) (), void * closure);
Simple merge
  #include "libguile/gc.h"
  #include "libguile/threads.h"
  #include "libguile/unif.h"
- #include "libguile/pairs.h"
+ #include "libguile/ports.h"
+ #include "libguile/error.h"
+ #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
+ /* GCC has `__inline__' in all modes, including strict ansi.  GCC 4.3 and
+    above with `-std=c99' or `-std=gnu99' implements ISO C99 inline semantics,
+    unless `-fgnu89-inline' is used.  Here we want GNU "extern inline"
+    semantics, hence the `__gnu_inline__' attribute, in accordance with:
+    http://gcc.gnu.org/gcc-4.3/porting_to.html .
+    With GCC 4.2, `__GNUC_STDC_INLINE__' is never defined (because C99 inline
+    semantics are not supported), but a warning is issued in C99 mode if
+    `__gnu_inline__' is not used.
+    Apple's GCC build >5400 (since Xcode 3.0) doesn't support GNU inline in
+    C99 mode and doesn't define `__GNUC_STDC_INLINE__'.  Fall back to "static
+    inline" in that case.  */
+ # if (defined __GNUC__) && (!(__APPLE_CC__ > 5400 && __STDC_VERSION__ >= 199901L))
+ #  define SCM_C_USE_EXTERN_INLINE 1
+ #  if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2)
+ #   define SCM_C_EXTERN_INLINE                                        \
+            extern __inline__ __attribute__ ((__gnu_inline__))
+ #  else
+ #   define SCM_C_EXTERN_INLINE extern __inline__
+ #  endif
+ # elif (defined SCM_C_INLINE)
+ #  define SCM_C_EXTERN_INLINE static SCM_C_INLINE
+ # endif
+ #endif /* SCM_INLINE_C_INCLUDING_INLINE_H */
+ #if (!defined SCM_C_INLINE) || (defined SCM_INLINE_C_INCLUDING_INLINE_H) \
+     || (defined SCM_C_USE_EXTERN_INLINE)
  
+ /* The `extern' declarations.  They should only appear when used from
+    "inline.c", when `inline' is not supported at all or when "extern inline"
+    is used.  */
  
 +#include "libguile/boehm-gc.h"
 +
 +
  SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
  SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
                             scm_t_bits ccr, scm_t_bits cdr);
@@@ -58,39 -101,73 +104,28 @@@ SCM_API void scm_puts (const char *str_
  extern unsigned scm_newcell2_count;
  extern unsigned scm_newcell_count;
  
- #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
- /* definitely inlining */
- #ifdef __GNUC__
- extern
- #else
- static
- #endif
- SCM_C_INLINE
+ #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
+ SCM_C_EXTERN_INLINE
  #endif
 +
  SCM
  scm_cell (scm_t_bits car, scm_t_bits cdr)
  {
 -  SCM z;
 -  SCM *freelist = SCM_FREELIST_LOC (scm_i_freelist);
 -
 -  if (scm_is_null (*freelist))
 -    z = scm_gc_for_newcell (&scm_i_master_freelist, freelist);
 -  else
 -    {
 -      z = *freelist;
 -      *freelist = SCM_FREE_CELL_CDR (*freelist);
 -    }
 -
 -#if (SCM_DEBUG_CELL_ACCESSES == 1)
 -    if (scm_debug_cell_accesses_p)
 -      {
 -      if (SCM_GC_MARK_P (z))
 -        {
 -          fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
 -          abort();
 -        }
 -      else if (SCM_GC_CELL_WORD(z, 0) != scm_tc_free_cell)
 -        {
 -          fprintf(stderr, "cell from freelist is not a free cell.\n");
 -          abort();
 -        }
 -      }
 -
 -#if (SCM_DEBUG_MARKING_API == 0)
 -    /*
 -      Always set mark. Otherwise cells that are alloced before
 -      scm_debug_cell_accesses_p is toggled seem invalid.
 -    */
 -    SCM_SET_GC_MARK (z);
 -#endif /* SCM_DEBUG_MARKING_API */
 -    
 -    /*
 -      TODO: figure out if this use of mark bits is valid with
 -      threading. What if another thread is doing GC at this point
 -      ... ?
 -     */
 -#endif
 +  SCM cell = SCM_PACK ((scm_t_bits) (GC_MALLOC (sizeof (scm_t_cell))));
  
 -  
 -  /* Initialize the type slot last so that the cell is ignored by the
 -     GC until it is completely initialized.  This is only relevant
 -     when the GC can actually run during this code, which it can't
 -     since the GC only runs when all other threads are stopped.
 -  */
 -  SCM_GC_SET_CELL_WORD (z, 1, cdr);
 -  SCM_GC_SET_CELL_WORD (z, 0, car);
 +  /* Initialize the type slot last so that the cell is ignored by the GC
 +     until it is completely initialized.  This is only relevant when the GC
 +     can actually run during this code, which it can't since the GC only runs
 +     when all other threads are stopped.  */
 +  SCM_GC_SET_CELL_WORD (cell, 1, cdr);
 +  SCM_GC_SET_CELL_WORD (cell, 0, car);
  
 -#if (SCM_DEBUG_CELL_ACCESSES == 1)
 -  if (scm_expensive_debug_cell_accesses_p )
 -    scm_i_expensive_validation_check (z);
 -#endif
 -  
 -  return z;
 +  return cell;
  }
  
- #if defined SCM_C_INLINE && ! defined SCM_INLINE_C_INCLUDING_INLINE_H
- /* definitely inlining */
- #ifdef __GNUC__
- extern
- #else
- static
- #endif
- SCM_C_INLINE
+ #ifndef SCM_INLINE_C_INCLUDING_INLINE_H
+ SCM_C_EXTERN_INLINE
  #endif
  SCM
  scm_double_cell (scm_t_bits car, scm_t_bits cbr,
Simple merge
Simple merge
@@@ -1200,8 -1087,9 +1153,9 @@@ scm_c_write (SCM port, const void *ptr
    if (pt->rw_random)
      pt->rw_active = SCM_PORT_WRITE;
  }
+ #undef FUNC_NAME
  
 -void 
 +void
  scm_flush (SCM port)
  {
    long i = SCM_PTOBNUM (port);
@@@ -116,12 -170,111 +109,8 @@@ int scm_i_marking
  
  void scm_mark_all (void);
  
 -/*
 -gc-segment:
 -*/
--
- char const *scm_i_tag_name (scm_t_bits tag); /* MOVEME */
 -/*
 -
 - Cells are stored in a heap-segment: it is a contiguous chunk of
 - memory, that associated with one freelist. 
 -*/
 -typedef struct scm_t_heap_segment
 -{
 -  /*
 -    {lower, upper} bounds of the segment
 -
 -    The upper bound is also the start of the mark space.
 -  */
 -  scm_t_cell *bounds[2];
 -
 -  /*
 -    If we ever decide to give it back, we could do it with this ptr.
 -
 -    Note that giving back memory is not very useful; as long we don't
 -    touch a chunk of memory, the virtual memory system will keep it
 -    swapped out. We could simply forget about a block.
 -
 -    (not that we do that, but anyway.) 
 -   */
 -  void *malloced;
 -
 -  scm_t_cell *next_free_card;
 -  
 -  /* address of the head-of-freelist pointer for this segment's cells.
 -     All segments usually point to the same one, scm_i_freelist.  */
 -  scm_t_cell_type_statistics *freelist;
 -  
 -  /* number of cells per object in this segment */
 -  int span;
 -
 -  /*
 -    Is this the first time that the cells are accessed? 
 -   */
 -  int first_time;
 -} scm_t_heap_segment;
 -
 -/*
 -  A table of segment records is kept that records the upper and
 -  lower extents of the segment;  this is used during the conservative
 -  phase of gc to identify probably gc roots (because they point
 -  into valid segments at reasonable offsets).
 -*/
 -extern scm_t_heap_segment ** scm_i_heap_segment_table;
 -extern size_t scm_i_heap_segment_table_size;
 -
 -
 -SCM_INTERNAL int scm_i_init_card_freelist (scm_t_cell * card, SCM *free_list,
 -                                         scm_t_heap_segment*);
 -SCM_INTERNAL int scm_i_sweep_card (scm_t_cell *card, SCM *free_list,
 -                                 scm_t_heap_segment *);
 -SCM_INTERNAL int scm_i_card_marked_count (scm_t_cell *card, int span);
 -SCM_INTERNAL void scm_i_card_statistics (scm_t_cell *p, SCM hashtab,
 -                                       scm_t_heap_segment *seg);
 -SCM_INTERNAL char const *scm_i_tag_name (scm_t_bits tag); /* MOVEME */
 -
 -SCM_INTERNAL int scm_i_initialize_heap_segment_data (scm_t_heap_segment *seg,
 -                                                   size_t requested);
 -
 -SCM_INTERNAL int scm_i_segment_cells_per_card (scm_t_heap_segment *seg);
 -SCM_INTERNAL int scm_i_segment_card_number (scm_t_heap_segment *seg,
 -                                          scm_t_cell *card);
 -SCM_INTERNAL int scm_i_segment_card_count (scm_t_heap_segment *seg);
 -SCM_INTERNAL int scm_i_segment_cell_count (scm_t_heap_segment *seg);
 -SCM_INTERNAL int scm_i_heap_segment_marked_count (scm_t_heap_segment *seg);
 -  
 -SCM_INTERNAL void scm_i_clear_segment_mark_space (scm_t_heap_segment *seg);
 -SCM_INTERNAL scm_t_heap_segment *
 -scm_i_make_empty_heap_segment (scm_t_cell_type_statistics*);
 -SCM_INTERNAL SCM scm_i_sweep_for_freelist (scm_t_cell_type_statistics *seg);
 -SCM_INTERNAL SCM scm_i_sweep_some_cards (scm_t_heap_segment *seg,
 -                                       scm_t_sweep_statistics *sweep_stats,
 -                                       int threshold);
 -SCM_INTERNAL void scm_i_sweep_segment (scm_t_heap_segment *seg,
 -                                     scm_t_sweep_statistics *sweep_stats);
 -
 -SCM_INTERNAL void scm_i_heap_segment_statistics (scm_t_heap_segment *seg,
 -                                               SCM tab);
 -
--
 -SCM_INTERNAL int scm_i_insert_segment (scm_t_heap_segment *seg);
 -SCM_INTERNAL int scm_i_find_heap_segment_containing_object (SCM obj);
 -SCM_INTERNAL int scm_i_get_new_heap_segment (scm_t_cell_type_statistics *freelist,
 -                                           size_t length, 
 -                                           policy_on_error);
 -SCM_INTERNAL int scm_i_marked_count (void);
 -SCM_INTERNAL void scm_i_clear_mark_space (void);
 -SCM_INTERNAL void scm_i_sweep_segments (void);
 -SCM_INTERNAL SCM scm_i_sweep_some_segments (scm_t_cell_type_statistics *fl,
 -                                          scm_t_sweep_statistics *sweep_stats);
 -SCM_INTERNAL void scm_i_reset_segments (void);
 -SCM_INTERNAL void scm_i_sweep_all_segments (char const *reason,
 -                                          scm_t_sweep_statistics *sweep_stats);
 -SCM_INTERNAL SCM scm_i_all_segments_statistics (SCM hashtab);
 -SCM_INTERNAL unsigned long *scm_i_segment_table_info(int *size);
--
  extern long int scm_i_deprecated_memory_return;
+ extern long int scm_i_find_heap_calls;
  
  /*
    global init funcs.
Simple merge
diff --cc libguile/root.h
Simple merge
Simple merge
Simple merge
@@@ -1,4 -1,4 +1,4 @@@
--/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
++/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2003, 2004, 2006, 2007, 2008 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
Simple merge
@@@ -18,9 -18,6 +18,7 @@@
  
  \f
  
- #define _GNU_SOURCE
 +#include "libguile/boehm-gc.h"
  #include "libguile/_scm.h"
  
  #if HAVE_UNISTD_H
@@@ -424,10 -470,9 +458,11 @@@ guilify_self_1 (SCM_STACKITEM *base
    /* XXX - check for errors. */
    pipe (t->sleep_pipe);
    scm_i_pthread_mutex_init (&t->heap_mutex, NULL);
+   scm_i_pthread_mutex_init (&t->admin_mutex, NULL);
    t->clear_freelists_p = 0;
    t->gc_running_p = 0;
 +  t->current_mark_stack_ptr = NULL;
 +  t->current_mark_stack_limit = NULL;
    t->canceled = 0;
    t->exited = 0;
  
@@@ -1026,27 -1123,22 +1124,15 @@@ SCM_DEFINE (scm_join_thread_timed, "joi
  }
  #undef FUNC_NAME
  
\f
- /*** Fat mutexes */
- /* We implement our own mutex type since we want them to be 'fair', we
-    want to do fancy things while waiting for them (like running
-    asyncs) and we might want to add things that are nice for
-    debugging.
- */
- typedef struct {
-   scm_i_pthread_mutex_t lock;
-   SCM owner;
-   int level;      /* how much the owner owns us.  
-                    < 0 for non-recursive mutexes */
-   SCM waiting;    /* the threads waiting for this mutex. */
- } fat_mutex;
- #define SCM_MUTEXP(x)         SCM_SMOB_PREDICATE (scm_tc16_mutex, x)
- #define SCM_MUTEX_DATA(x)     ((fat_mutex *) SCM_SMOB_DATA (x))
+ SCM_DEFINE (scm_thread_p, "thread?", 1, 0, 0,
+           (SCM obj),
+           "Return @code{#t} if @var{obj} is a thread.")
+ #define FUNC_NAME s_scm_thread_p
+ {
+   return SCM_I_IS_THREAD(obj) ? SCM_BOOL_T : SCM_BOOL_F;
+ }
+ #undef FUNC_NAME
  
 -static SCM
 -fat_mutex_mark (SCM mx)
 -{
 -  fat_mutex *m = SCM_MUTEX_DATA (mx);
 -  scm_gc_mark (m->owner);
 -  return m->waiting;
 -}
  
  static size_t
  fat_mutex_free (SCM mx)
@@@ -1269,18 -1546,23 +1540,16 @@@ SCM_DEFINE (scm_mutex_level, "mutex-lev
  }
  #undef FUNC_NAME
  
- #endif
- /*** Fat condition variables */
- typedef struct {
-   scm_i_pthread_mutex_t lock;
-   SCM waiting;               /* the threads waiting for this condition. */
- } fat_cond;
- #define SCM_CONDVARP(x)       SCM_SMOB_PREDICATE (scm_tc16_condvar, x)
- #define SCM_CONDVAR_DATA(x)   ((fat_cond *) SCM_SMOB_DATA (x))
+ SCM_DEFINE (scm_mutex_locked_p, "mutex-locked?", 1, 0, 0,
+           (SCM mx),
+           "Returns @code{#t} if the mutex @var{mx} is locked.")
+ #define FUNC_NAME s_scm_mutex_locked_p
+ {
+   SCM_VALIDATE_MUTEX (1, mx);
+   return SCM_MUTEX_DATA (mx)->level > 0 ? SCM_BOOL_T : SCM_BOOL_F;
+ }
+ #undef FUNC_NAME
  
 -static SCM
 -fat_cond_mark (SCM cv)
 -{
 -  fat_cond *c = SCM_CONDVAR_DATA (cv);
 -  return c->waiting;
 -}
 -
  static size_t
  fat_cond_free (SCM mx)
  {
@@@ -139,17 -143,17 +148,17 @@@ SCM_INTERNAL void *scm_i_with_guile_and
  
  extern int scm_i_thread_go_to_sleep;
  
- void scm_i_thread_put_to_sleep (void);
- void scm_i_thread_wake_up (void);
- void scm_i_thread_invalidate_freelists (void);
SCM_INTERNAL void scm_i_thread_put_to_sleep (void);
SCM_INTERNAL void scm_i_thread_wake_up (void);
SCM_INTERNAL void scm_i_thread_invalidate_freelists (void);
  void scm_i_thread_sleep_for_gc (void);
  
 -SCM_INTERNAL void scm_threads_prehistory (SCM_STACKITEM *);
 -SCM_INTERNAL void scm_threads_init_first_thread (void);
 -SCM_INTERNAL void scm_threads_mark_stacks (void);
 +void scm_threads_prehistory (SCM_STACKITEM *);
 +void scm_threads_init_first_thread (void);
 +
- SCM_API void scm_init_threads (void);
- SCM_API void scm_init_thread_procs (void);
- SCM_API void scm_init_threads_default_dynamic_state (void);
+ SCM_INTERNAL void scm_init_threads (void);
+ SCM_INTERNAL void scm_init_thread_procs (void);
+ SCM_INTERNAL void scm_init_threads_default_dynamic_state (void);
  
  
  #define SCM_THREAD_SWITCHING_CODE \
@@@ -99,10 -99,9 +99,10 @@@ SCM_INTERNAL SCM  scm_i_vector_equal_p 
  #define SCM_I_WVECT_GC_CHAIN(x)         (SCM_CELL_OBJECT_3 (x))
  #define SCM_I_SET_WVECT_GC_CHAIN(x, o)  (SCM_SET_CELL_OBJECT_3 ((x), (o)))
  
- SCM_API SCM scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill);
- SCM_API SCM scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst);
 -SCM_INTERNAL SCM scm_i_allocate_weak_vector (scm_t_bits type, SCM size, SCM fill);
++SCM_INTERNAL SCM scm_i_make_weak_vector (scm_t_bits type, SCM size, SCM fill);
++SCM_INTERNAL SCM scm_i_make_weak_vector_from_list (scm_t_bits type, SCM lst);
  
- SCM_API void scm_init_vectors (void);
+ SCM_INTERNAL void scm_init_vectors (void);
  
  #endif  /* SCM_VECTORS_H */
  
Simple merge
@@@ -90,14 -62,13 +90,14 @@@ SCM_API SCM scm_make_doubly_weak_alist_
  SCM_API SCM scm_weak_key_alist_vector_p (SCM x);
  SCM_API SCM scm_weak_value_alist_vector_p (SCM x);
  SCM_API SCM scm_doubly_weak_alist_vector_p (SCM x);
- SCM_API SCM scm_init_weaks_builtins (void);
- SCM_API void scm_weaks_prehistory (void);
- SCM_API void scm_init_weaks (void);
- SCM_API void scm_i_init_weak_vectors_for_gc (void);
- SCM_API void scm_i_mark_weak_vector (SCM w);
- SCM_API int scm_i_mark_weak_vectors_non_weaks (void);
- SCM_API void scm_i_remove_weaks_from_weak_vectors (void);
+ SCM_INTERNAL SCM scm_init_weaks_builtins (void);
++SCM_INTERNAL void scm_weaks_prehistory (void);
+ SCM_INTERNAL void scm_init_weaks (void);
+ SCM_INTERNAL void scm_i_init_weak_vectors_for_gc (void);
+ SCM_INTERNAL void scm_i_mark_weak_vector (SCM w);
+ SCM_INTERNAL int scm_i_mark_weak_vectors_non_weaks (void);
+ SCM_INTERNAL void scm_i_remove_weaks_from_weak_vectors (void);
  
  
  #endif  /* SCM_WEAKS_H */
Simple merge
@@@ -1,5 -1,5 +1,5 @@@
  ;;;; gc.test --- test guile's garbage collection    -*- scheme -*-
- ;;;; Copyright (C) 2000, 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
 -;;;; Copyright (C) 2000, 2001, 2004, 2006, 2008 Free Software Foundation, Inc.
++;;;; Copyright (C) 2000, 2001, 2004, 2006, 2007, 2008 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
  
  (with-test-prefix "gc"
    (pass-if "Unused modules are removed"
 -         (let*
 -             ((dummy (gc))
 -              (last-count (cdr (assoc
 -                                "eval-closure" (gc-live-object-stats)))))
 +           ;; FIXME: This test fails because of the circular reference
 +           ;; created by `make-module' between the module itself and its
 +           ;; standard eval closure.
 +         (let* ((guard (make-guardian))
 +                  (total 1000))
  
 -           (for-each (lambda (x) (make-module)) (iota 1000))
 +           (for-each (lambda (x) (guard (make-module))) (iota total))
+            ;; XXX: This hack aims to clean up the stack to make sure we
+            ;; don't leave a reference to one of the modules we created.  It
+            ;; proved to be useful on SPARC:
+            ;; http://lists.gnu.org/archive/html/guile-devel/2008-02/msg00006.html .
+              (let cleanup ((i 10))
+                (and (> i 0)
+                     (begin (cleanup (1- i)) i)))
             (gc)
             (gc) ;; twice: have to kill the weak vectors.
 -           (= last-count (cdr (assoc "eval-closure" (gc-live-object-stats)))))
 -         ))
 +             (= (length (filter (lambda (x)
 +                                  (eq? x #t))
 +                                (map (lambda (x) (and (guard) #t))
 +                                     (iota total))))
 +                total))))