2006-03-09 Hans Boehm <Hans.Boehm@hp.com>
authorhboehm <hboehm>
Fri, 10 Mar 2006 05:24:07 +0000 (05:24 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:36 +0000 (21:06 +0400)
Merge various gc6.7 changes (see doc/README.changes for contributors):
* configure.ac, pthread_stop_world.c, pthread_support.c,
threadlibs.c, include/gc_config_macros.h,
include/gc_pthread_redirects.h, include/leak_detector.h,
include/private/gcconfig.h, include/private/thread_local_alloc.h:
Add NetBSD threads support.
* dbg_mlc.c, malloc.c, include/gc.h: add GC_debug_str_dup, GC_str_dup.
* os_dep.c (GC_init_win32),
dyn_load.c (win32 GC_register_dynamic_libraries): accept
MEM_PRIVATE for Windows 98 etc.
* doc/gcinterface.html: Add warnings about thread locals and
in-flight exceptions.
* tests/tests.am: Add EXE extensions.
* Makefile.in, configure: rebuild

19 files changed:
Makefile.in
configure
configure.ac
dbg_mlc.c
doc/README.changes
doc/gcinterface.html
dyn_load.c
include/gc.h
include/gc_config_macros.h
include/gc_pthread_redirects.h
include/leak_detector.h
include/private/gcconfig.h
include/private/thread_local_alloc.h
malloc.c
os_dep.c
pthread_stop_world.c
pthread_support.c
tests/tests.am
threadlibs.c

index 68708ef..08b02ab 100644 (file)
@@ -109,13 +109,13 @@ DIST_COMMON = $(am__configure_deps) $(am__pkginclude_HEADERS_DIST) \
        config.guess config.sub depcomp install-sh ltmain.sh missing \
        mkinstalldirs
 
-#TESTS += tracetest
+#TESTS += tracetest$(EXEEXT)
 #check_PROGRAMS += tracetest
 #tracetest_SOURCES = tests/trace_test.c
 #tracetest_LDADD = $(test_ldadd)
-@THREADS_TRUE@am__append_1 = threadleaktest
+@THREADS_TRUE@am__append_1 = threadleaktest$(EXEEXT)
 @THREADS_TRUE@am__append_2 = threadleaktest
-@CPLUSPLUS_TRUE@am__append_3 = test_cpp
+@CPLUSPLUS_TRUE@am__append_3 = test_cpp$(EXEEXT)
 @CPLUSPLUS_TRUE@am__append_4 = test_cpp
 
 # C Library: Architecture Dependent
@@ -471,7 +471,8 @@ dist_noinst_HEADERS = include/private/gc_hdrs.h \
        include/private/darwin_stop_world.h \
        include/private/thread_local_alloc.h include/cord.h \
        include/ec.h include/javaxfc.h version.h
-TESTS = gctest leaktest middletest $(am__append_1) $(am__append_3)
+TESTS = gctest$(EXEEXT) leaktest$(EXEEXT) middletest$(EXEEXT) \
+       $(am__append_1) $(am__append_3)
 pkgconfigdir = $(libdir)/pkgconfig
 dist_pkgconfig_DATA = bdw-gc.pc
 libcord_la_SOURCES = \
index b4e9b80..d0c8d50 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 1.2 .
+# From configure.ac Revision: 1.3 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59 for gc 7.0alpha6.
 #
@@ -4156,6 +4156,23 @@ _ACEOF
        INCLUDES="$INCLUDES -pthread"
        THREADDLLIBS=-pthread
        ;;
+     *-*-netbsd*)
+       { echo "$as_me:$LINENO: WARNING: \"Only on NetBSD 2.0 or later.\"" >&5
+echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;}
+       cat >>confdefs.h <<\_ACEOF
+#define GC_NETBSD_THREADS 1
+_ACEOF
+
+       cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+       cat >>confdefs.h <<\_ACEOF
+#define _PTHREADS 1
+_ACEOF
+
+       THREADDLLIBS="-lpthread -lrt"
+       ;;
      *-*-solaris*)
        cat >>confdefs.h <<\_ACEOF
 #define GC_SOLARIS_THREADS 1
@@ -6217,7 +6234,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
 case $host in
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6220 "configure"' > conftest.$ac_ext
+  echo '#line 6237 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -6790,7 +6807,7 @@ chmod -w .
 save_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
 compiler_c_o=no
-if { (eval echo configure:6793: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+if { (eval echo configure:6810: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
   # The compiler can only warn and ignore the option if not recognized
   # So say no if there are warnings
   if test -s out/conftest.err; then
@@ -8717,7 +8734,7 @@ else
     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8720 "configure"
+#line 8737 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -8815,7 +8832,7 @@ else
     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 8818 "configure"
+#line 8835 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
index a897683..e0684c5 100644 (file)
@@ -22,7 +22,7 @@ AC_INIT(gc,7.0alpha6,Hans.Boehm@hp.com)
 AC_CONFIG_SRCDIR(gcj_mlc.c)
 AC_CANONICAL_TARGET 
 AC_PREREQ(2.53)
-AC_REVISION($Revision: 1.3 $)
+AC_REVISION($Revision: 1.4 $)
 GC_SET_VERSION
 AM_INIT_AUTOMAKE([foreign dist-bzip2 subdir-objects nostdinc])
 AM_MAINTAINER_MODE
@@ -113,6 +113,13 @@ case "$THREADS" in
        INCLUDES="$INCLUDES -pthread"
        THREADDLLIBS=-pthread
        ;;
+     *-*-netbsd*)
+       AC_MSG_WARN("Only on NetBSD 2.0 or later.")
+       AC_DEFINE(GC_NETBSD_THREADS)
+       AC_DEFINE(_REENTRANT)
+       AC_DEFINE(_PTHREADS)
+       THREADDLLIBS="-lpthread -lrt"
+       ;;
      *-*-solaris*)
        AC_DEFINE(GC_SOLARIS_THREADS)
        AC_DEFINE(GC_SOLARIS_PTHREADS)
index 881fa7f..bffa933 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -14,6 +14,8 @@
  * modified is included with the above copyright notice.
  */
 
+#include <errno.h>
+#include <string.h>
 #include "private/dbg_mlc.h"
 
 void GC_default_print_heap_obj_proc();
@@ -636,6 +638,19 @@ void * GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
     return (GC_store_debug_info(result, (word)lb, s, (word)i));
 }
 
+char *GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
+{
+    char *copy;
+    if (str == NULL) return NULL;
+    copy = GC_debug_malloc_atomic(strlen(str) + 1, OPT_RA s, i);
+    if (copy == NULL) {
+      errno = ENOMEM;
+      return NULL;
+    }
+    strcpy(copy, str);
+    return copy;
+}
+
 void * GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
 {
     void * result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES);
index bf26df4..a396cd8 100644 (file)
@@ -2263,6 +2263,17 @@ Since 6.6:
    developers.)
  - Merge in some recent gcc fixes.  Add ppc64 asm code.  (Thanks to Bryce
    McKinley and other gcj developers.)
+ - Scan MEM_PRIVATE sections under Windows ME and predecessors.
+ - Interior pointers with some largish offsets into large objects could
+   be ignored, if GC_all_interior_pointers was set.  (Oddly this worked
+   correctly for stack references if it was not set.  Otherwise it failed
+   for both stack and heap references.)  Thanks to Andrew McKinlay for the
+   critical test case.
+ - Integrated Tatsuya Bizenn's NETBSD threads support, with some
+   untested changes.
+ - Added GC_strdup and friends to make leak detection work correctly
+   for strdup clients.  (Thanks to Jon Moore.)  Fixed the existing strdup
+   with malloc redirection to handle a null malloc return correctly.
 
 Since gc6.7:
  - Remove GC_PROTO, VOLATILE, GC_PTR, and GC_CONST.  Assume ANSI C compiler
@@ -2459,6 +2470,8 @@ Since gc7.0alpha5
  - Fix typo in DARWIN section of gcconfig.h.
  - Fix Darwin thread memory leak.  (Thanks to Bruce Mitchener.)
  - Update x86 AO_test_and_set implementation to use "=q".
+ - Add $(EXEEXT) to many tests in tests/tests.am.  (Corresponds to a
+   6.7 fix, which no longer applied.)
   
 To do:
  - REDIRECT_MALLOC and threads combination is getting closer, but currently
index d8b378b..74230aa 100644 (file)
@@ -34,6 +34,12 @@ after defining the appropriate <TT>GC_</tt><I>XXXX</i><TT>_THREADS</tt> macro.
 The header file <TT>gc.h</tt> must be included
 in files that use either GC or threads primitives, since threads primitives
 will be redefined to cooperate with the GC on many platforms.
+<P>
+Thread users should also be aware that on many platforms objects reachable
+only from thread-local variables may be prematurely reclaimed.
+Thus objects pointed to by thread-local variables should also be pointed to
+by a globally visible data structure.  (This is viewed as a bug, but as
+one that is exceedingly hard to fix without some libc hooks.)
 <DL>
 <DT> <B>void * GC_MALLOC(size_t <I>nbytes</i>)</b>
 <DD>
@@ -192,6 +198,11 @@ but are scanned for pointers to collectable objects.
 They are usually allocated by <TT>GC_MALLOC_UNCOLLECTABLE</tt>, as described
 above, and through some interfaces described below.
 <P>
+(On most platforms, the collector may not trace correctly from in-flight
+exception objects.  Thus objects thrown as exceptions should only
+point to otherwise reachable memory.  This is another bug whose
+proper repair requires platform hooks.)
+<P>
 The easiest way to ensure that collectable objects are properly referenced
 is to allocate only collectable objects.  This requires that every
 allocation go through one of the following interfaces, each one of
index 3007774..8de30b7 100644 (file)
@@ -701,6 +701,9 @@ void GC_register_dynamic_libraries()
   }
 # endif /* DEBUG_VIRTUALQUERY */
 
+  extern GC_bool GC_wnt;  /* Is Windows NT derivative.         */
+                         /* Defined and set in os_dep.c.       */
+
   void GC_register_dynamic_libraries()
   {
     MEMORY_BASIC_INFORMATION buf;
@@ -738,7 +741,12 @@ void GC_register_dynamic_libraries()
                && (protect == PAGE_EXECUTE_READWRITE
                    || protect == PAGE_READWRITE)
                && !GC_is_heap_base(buf.AllocationBase)
-               && buf.Type == MEM_IMAGE) {  
+               /* There is some evidence that we cannot always
+                * ignore MEM_PRIVATE sections under Windows ME
+                * and predecessors.  Hence we now also check for
+                * that case.   */
+               && (buf.Type == MEM_IMAGE ||
+                   !GC_wnt && buf.Type == MEM_PRIVATE)) {
 #              ifdef DEBUG_VIRTUALQUERY
                  GC_dump_meminfo(&buf);
 #              endif
index 7f380f1..6ad52e3 100644 (file)
@@ -253,6 +253,7 @@ GC_API void GC_init(void);
  */
 GC_API void * GC_malloc(size_t size_in_bytes);
 GC_API void * GC_malloc_atomic(size_t size_in_bytes);
+GC_API char * GC_strdup (const char *str);
 GC_API void * GC_malloc_uncollectable(size_t size_in_bytes);
 GC_API void * GC_malloc_stubborn(size_t size_in_bytes);
 
@@ -505,6 +506,7 @@ GC_API void * GC_malloc_atomic_ignore_off_page(size_t lb);
 /* objects allocated in this way for overwrites, etc.                  */
 GC_API void * GC_debug_malloc(size_t size_in_bytes, GC_EXTRA_PARAMS);
 GC_API void * GC_debug_malloc_atomic(size_t size_in_bytes, GC_EXTRA_PARAMS);
+GC_API char * GC_debug_strdup(const char *str, GC_EXTRA_PARAMS);
 GC_API void * GC_debug_malloc_uncollectable
        (size_t size_in_bytes, GC_EXTRA_PARAMS);
 GC_API void * GC_debug_malloc_stubborn
@@ -538,6 +540,7 @@ GC_API void * GC_debug_realloc_replacement
 # ifdef GC_DEBUG
 #   define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
 #   define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
+#   define GC_STRDUP(s) GC_debug_strdup((s), GC_EXTRAS)
 #   define GC_MALLOC_UNCOLLECTABLE(sz) \
                        GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
 #   define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
@@ -561,6 +564,7 @@ GC_API void * GC_debug_realloc_replacement
 # else
 #   define GC_MALLOC(sz) GC_malloc(sz)
 #   define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
+#   define GC_STRDUP(s) GC_strdup(s)
 #   define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
 #   define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
                        GC_malloc_ignore_off_page(sz)
index 2b8ced7..487848e 100644 (file)
 #if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \
                             || defined(GC_HPUX_THREADS) \
                             || defined(GC_AIX_THREADS) \
-                            || defined(GC_LINUX_THREADS))
+                            || defined(GC_LINUX_THREADS) \
+                            || defined(GC_NETBSD_THREADS))
 # define _REENTRANT
        /* Better late than never.  This fails if system headers that   */
        /* depend on this were previously included.                     */
 #endif
 
+#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
+# define _PTHREADS
+#endif
+
 #if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
 # define _POSIX4A_DRAFT10_SOURCE 1
 #endif
@@ -55,7 +60,7 @@
        defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
        defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
        defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
-       defined(GC_AIX_THREADS) || \
+        defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
         (defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
 #   define GC_PTHREADS
 # endif
 #   define GC_FREEBSD_THREADS
 #   define GC_PTHREADS
 # endif
+# if !defined(GC_PTHREADS) && defined(__NetBSD__)
+#   define GC_NETBSD_THREADS
+#   define GC_PTHREADS
+# endif
 # if defined(DGUX) && (defined(i386) || defined(__i386__))
 #   define GC_DGUX386_THREADS
 #   define GC_PTHREADS
index 842518c..21e9c9f 100644 (file)
@@ -73,6 +73,9 @@
 # define pthread_detach GC_pthread_detach
 
 #ifndef GC_DARWIN_THREADS
+# ifdef pthread_sigmask
+#  undef pthread_sigmask
+# endif         /* pthread_sigmask */
 # define pthread_sigmask GC_pthread_sigmask
 # define dlopen GC_dlopen
 #endif
index 0674ab4..1d02f40 100644 (file)
@@ -4,4 +4,6 @@
 #define calloc(m,n) GC_MALLOC((m)*(n))
 #define free(p) GC_FREE(p)
 #define realloc(p,n) GC_REALLOC((p),(n))
+#undef strdup
+#define strdup(s) GC_STRDUP((s))
 #define CHECK_LEAKS() GC_gcollect()
index efa364c..4c246a5 100644 (file)
 #   define SUNOS5SIGS
 # endif
 
+# ifdef GC_NETBSD_THREADS
+#   define SIGRTMIN 33
+#   define SIGRTMAX 63
+# endif
+
 # if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
            || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
            || defined(DGUX) || defined(BSD) \
 # if defined(GC_LINUX_THREADS) && !defined(LINUX)
        --> inconsistent configuration
 # endif
+# if defined(GC_NETBSD_THREADS) && !defined(NETBSD)
+       --> inconsistent configuration
+# endif
 # if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5)
        --> inconsistent configuration
 # endif
index 3416931..b74e5cb 100644 (file)
@@ -42,7 +42,8 @@
 #   elif defined(LINUX) && defined(__GNUC__)
 #     define USE_COMPILER_TLS
 #   elif (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
-         defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS))
+         defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) || \
+        defined(GC_NETBSD_THREADS)
 #     define USE_PTHREAD_SPECIFIC
 #   elif defined(GC_HPUX_THREADS)
 #     ifdef __GNUC__
index 1513735..47319f8 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -14,6 +14,8 @@
  */
  
 #include <stdio.h>
+#include <string.h>
+#include <errno.h>
 #include "private/gc_priv.h"
 
 extern void * GC_clear_stack(void *);  /* in misc.c, behaves like identity */
@@ -229,6 +231,26 @@ void * GC_generic_malloc(size_t lb, int k)
    }
 }
 
+/* provide a version of strdup() that uses the collector to allocate the
+   copy of the string */
+# ifdef __STDC__
+    char *GC_strdup(const char *s)
+# else
+    char *GC_strdup(s)
+    char *s;
+#endif
+{
+  char *copy;
+
+  if (s == NULL) return NULL;
+  if ((copy = GC_malloc_atomic(strlen(s) + 1)) == NULL) {
+    errno = ENOMEM;
+    return NULL;
+  }
+  strcpy(copy, s);
+  return copy;
+}
+
 /* Allocate lb bytes of composite (pointerful) data */
 #ifdef THREAD_LOCAL_ALLOC
   void * GC_core_malloc(size_t lb)
@@ -308,6 +330,10 @@ void * calloc(size_t n, size_t lb)
   {
     size_t len = strlen(s) + 1;
     char * result = ((char *)REDIRECT_MALLOC(len+1));
+    if (result == 0) {
+      errno = ENOMEM;
+      return 0;
+    }
     BCOPY(s, result, len+1);
     return result;
   }
index d233694..f2da9de 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -1240,12 +1240,18 @@ void GC_register_data_segments(void)
     }
 
 # endif
+
+  GC_bool GC_wnt = FALSE;
+         /* This is a Windows NT derivative, i.e. NT, W2K, XP or later.  */
   
   void GC_init_win32(void)
   {
-    /* if we're running under win32s, assume that no DLLs will be loaded */
+    /* Set GC_wnt.                                                      */
+    /* If we're running under win32s, assume that no DLLs will be loaded */
+    /* I doubt anyone still runs win32s, but ...                        */
     DWORD v = GetVersion();
-    GC_no_win32_dlls |= ((v & 0x80000000) && (v & 0xff) <= 3);
+    GC_wnt = !(v & 0x80000000);
+    GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
   }
 
   /* Return the smallest address a such that VirtualQuery              */
index 33cc9e0..301c97b 100644 (file)
@@ -93,7 +93,7 @@ volatile AO_t GC_world_is_stopped = FALSE;
  */
 
 #ifndef SIG_THR_RESTART
-#  if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
+#  if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || defined(GC_NETBSD_THREADS)
 #    ifdef _SIGRTMIN
 #      define SIG_THR_RESTART _SIGRTMIN + 5
 #    else
@@ -106,6 +106,13 @@ volatile AO_t GC_world_is_stopped = FALSE;
 
 sem_t GC_suspend_ack_sem;
 
+#ifdef GC_NETBSD_THREADS
+# define GC_NETBSD_THREADS_WORKAROUND
+  /* It seems to be necessary to wait until threads have restarted.    */
+  /* But it is unclear why that is the case.                           */
+  sem_t GC_restart_ack_sem;
+#endif
+
 void GC_suspend_handler_inner(ptr_t sig_arg, void *context);
 
 #if defined(IA64) || defined(HP_PA)
@@ -208,6 +215,10 @@ void GC_restart_handler(int sig)
 
     if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
 
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+    sem_post(&GC_restart_ack_sem);
+#endif
+
     /*
     ** Note: even if we don't do anything useful here,
     ** it would still be necessary to have a signal handler,
@@ -424,6 +435,9 @@ void GC_start_world()
     register GC_thread p;
     register int n_live_threads = 0;
     register int result;
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+    int code;
+#endif
 
 #   if DEBUG_THREADS
       GC_printf("World starting\n");
@@ -455,6 +469,14 @@ void GC_start_world()
         }
       }
     }
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+    for (i = 0; i < n_live_threads; i++)
+       while (0 != (code = sem_wait(&GC_restart_ack_sem)))
+           if (errno != EINTR) {
+               GC_err_printf1("sem_wait() returned %ld\n", (unsigned long)code);
+               ABORT("sem_wait() for restart handler failed");
+           }
+#endif
     #if DEBUG_THREADS
       GC_printf("World started\n");
     #endif
@@ -465,6 +487,10 @@ void GC_stop_init() {
     
     if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
         ABORT("sem_init failed");
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+    if (sem_init(&GC_restart_ack_sem, 0, 0) != 0)
+       ABORT("sem_init failed");
+#endif
 
     act.sa_flags = SA_RESTART | SA_SIGINFO;
     if (sigfillset(&act.sa_mask) != 0) {
index a8c3c6b..4a283fb 100644 (file)
 # include <sys/sysctl.h>
 #endif /* GC_DARWIN_THREADS */
 
+#if defined(GC_NETBSD_THREADS)
+# include <sys/param.h>
+# include <sys/sysctl.h>
+#endif        /* GC_NETBSD_THREADS */
+
 /* Allocator lock definitions.         */
 #if defined(USE_SPIN_LOCK)
   pthread_t GC_lock_holder = NO_THREAD;
@@ -652,6 +657,18 @@ int GC_get_nprocs(void)
 }
 #endif /* GC_DGUX386_THREADS */
 
+#if defined(GC_NETBSD_THREADS)
+static int get_ncpu(void)
+{
+    int mib[] = {CTL_HW,HW_NCPU};
+    int res;
+    size_t len = sizeof(res);
+
+    sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0);
+    return res;
+}
+#endif /* GC_NETBSD_THREADS */
+
 /* We hold the allocation lock.        */
 void GC_thr_init(void)
 {
@@ -698,6 +715,9 @@ void GC_thr_init(void)
          GC_nprocs = sysconf(_SC_NPROC_ONLN);
          if (GC_nprocs <= 0) GC_nprocs = 1;
 #       endif
+#       if defined(GC_NETBSD_THREADS)
+         GC_nprocs = get_ncpu();
+#       endif
 #       if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
          int ncpus = 1;
          size_t len = sizeof(ncpus);
index defd592..ab62485 100644 (file)
@@ -23,36 +23,36 @@ test_ldadd = \
 
 
 
-TESTS += gctest
+TESTS += gctest$(EXEEXT)
 check_PROGRAMS += gctest
 gctest_SOURCES = tests/test.c
 gctest_LDADD = $(test_ldadd)
 gctest_DEPENDENCIES = $(top_builddir)/libgc.la
 
-TESTS += leaktest
+TESTS += leaktest$(EXEEXT)
 check_PROGRAMS += leaktest
 leaktest_SOURCES = tests/leak_test.c
 leaktest_LDADD = $(test_ldadd)
 
-TESTS += middletest
+TESTS += middletest$(EXEEXT)
 check_PROGRAMS += middletest
 middletest_SOURCES = tests/middle.c
 middletest_LDADD = $(test_ldadd)
 
-#TESTS += tracetest
+#TESTS += tracetest$(EXEEXT)
 #check_PROGRAMS += tracetest
 #tracetest_SOURCES = tests/trace_test.c
 #tracetest_LDADD = $(test_ldadd)
 
 if THREADS
-TESTS += threadleaktest
+TESTS += threadleaktest$(EXEEXT)
 check_PROGRAMS += threadleaktest
 threadleaktest_SOURCES = tests/thread_leak_test.c
 threadleaktest_LDADD = $(test_ldadd)
 endif
 
 if CPLUSPLUS
-TESTS += test_cpp
+TESTS += test_cpp$(EXEEXT)
 check_PROGRAMS += test_cpp
 test_cpp_SOURCES = tests/test_cpp.cc
 test_cpp_LDADD = libgccpp.la $(test_ldadd)
index 1309694..ab2118b 100644 (file)
@@ -27,6 +27,10 @@ int main()
           printf("-pthread\n");
 #       endif
 #   endif
+#   if defined(GC_NETBSD_THREADS)
+         printf("-lpthread -lrt\n");
+#   endif
+
 #   if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
        printf("-lpthread -lrt\n");
 #   endif