Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Commit [4eac79] Maximize Restore History

Preliminary support for POSIX threads.

jjgarcia jjgarcia 2003-11-18

1 2 3 .. 7 > >> (Page 1 of 7)
added src/c/threads.d
added src/clx/load.lsp.in
added src/cmp/cmpcond.lsp
added src/cmp/cmplet2.lsp
added src/doc/amop.txt
added src/doc/types-and-classes
added src/gc/aix_irix_threads.c
added src/gc/darwin_stop_world.c
added src/gc/doc/Makefile.am
added src/gc/doc/Makefile.in
added src/gc/doc/README.darwin
added src/gc/doc/gcinterface.html
added src/gc/doc/scale.html
added src/gc/include/Makefile.am
added src/gc/include/Makefile.in
added src/gc/include/gc_config_macros.h
added src/gc/include/private/darwin_semaphore.h
added src/gc/include/private/darwin_stop_world.h
added src/gc/include/private/pthread_stop_world.h
added src/gc/include/private/pthread_support.h
added src/gc/pthread_stop_world.c
changed src
changed src/CHANGELOG
changed src/Makefile.in
changed src/aclocal.m4
changed src/c
changed src/c/all_symbols.d
changed src/c/alloc.d
changed src/c/alloc_2.d
changed src/c/assignment.d
changed src/c/backq.d
changed src/c/big.d
changed src/c/character.d
changed src/c/cinit.d
changed src/c/cmpaux.d
changed src/c/compiler.d
changed src/c/disassembler.d
changed src/c/dpp.c
changed src/c/error.d
changed src/c/eval.d
changed src/c/file.d
changed src/c/format.d
changed src/c/gbc.d
changed src/c/hash.d
changed src/c/instance.d
changed src/c/interpreter.d
changed src/c/list.d
changed src/c/load.d
changed src/c/macros.d
changed src/c/main.d
changed src/c/mapfun.d
changed src/c/multival.d
changed src/c/num_co.d
changed src/c/num_rand.d
changed src/c/num_sfun.d
changed src/c/number.d
changed src/c/package.d
changed src/c/pathname.d
changed src/c/predicate.d
changed src/c/print.d
changed src/c/read.d
changed src/c/stacks.d
changed src/c/symbol.d
changed src/c/symbols_list.h
changed src/c/time.d
changed src/c/typespec.d
changed src/c/unixint.d
changed src/clx
changed src/cmp
changed src/cmp/cmpcall.lsp
changed src/cmp/cmpcatch.lsp
changed src/cmp/cmpexit.lsp
changed src/cmp/cmplam.lsp
changed src/cmp/cmploc.lsp
changed src/cmp/cmpmain.lsp
changed src/cmp/cmpmulti.lsp
changed src/cmp/cmptop.lsp
changed src/cmp/cmpvar.lsp
changed src/cmp/sysfun.lsp
changed src/configure
changed src/configure.in
changed src/doc
changed src/doc/todo.txt
changed src/gc
changed src/gc/BCC_MAKEFILE
changed src/gc/Makefile
changed src/gc/Makefile.am
changed src/gc/Makefile.direct
changed src/gc/Makefile.dj
changed src/gc/Makefile.in
changed src/gc/acinclude.m4
changed src/gc/aclocal.m4
changed src/gc/alloc.c
changed src/gc/backgraph.c
changed src/gc/config.guess
changed src/gc/config.sub
changed src/gc/configure
changed src/gc/configure.host
changed src/gc/configure.in
changed src/gc/cord
changed src/gc/cord/cordbscs.c
changed src/gc/cord/de_win.c
changed src/gc/dbg_mlc.c
changed src/gc/doc
changed src/gc/doc/README
changed src/gc/doc/README.MacOSX
changed src/gc/doc/README.changes
changed src/gc/doc/README.macros
changed src/gc/doc/README.win32
changed src/gc/doc/gcdescr.html
changed src/gc/doc/tree.html
changed src/gc/dyn_load.c
changed src/gc/finalize.c
changed src/gc/gc_dlopen.c
changed src/gc/if_mach.c
changed src/gc/include
changed src/gc/include/gc.h
changed src/gc/include/gc_cpp.h
changed src/gc/include/gc_mark.h
changed src/gc/include/gc_pthread_redirects.h
changed src/gc/include/gc_typed.h
changed src/gc/include/private
changed src/gc/include/private/gc_locks.h
changed src/gc/include/private/gc_pmark.h
changed src/gc/include/private/gc_priv.h
changed src/gc/include/private/gcconfig.h
changed src/gc/include/private/specific.h
changed src/gc/mach_dep.c
changed src/gc/mark.c
changed src/gc/mark_rts.c
changed src/gc/misc.c
changed src/gc/os_dep.c
changed src/gc/ptr_chck.c
changed src/gc/reclaim.c
changed src/gc/tests
changed src/gc/tests/test.c
changed src/gc/tests/test_cpp.cc
changed src/gc/threadlibs.c
changed src/gc/typd_mlc.c
changed src/gc/version.h
changed src/gc/win32_threads.c
changed src/h
changed src/h/config.h.in
changed src/h/external.h
changed src/h/internal.h
changed src/h/object.h
changed src/h/stacks.h
changed src/lsp
changed src/lsp/autoload.lsp
changed src/lsp/load.lsp.in
changed src/util
changed src/util/emacs.el
copied src/gc/linux_threads.c -> src/gc/pthread_support.c
copied src/gc/mips_sgi_mach_dep.S -> src/gc/mips_sgi_mach_dep.s
copied src/gc/powerpc_macosx_mach_dep.s -> src/gc/powerpc_darwin_mach_dep.s
src/c/threads.d Diff Switch to side-by-side view
Loading...
src/clx/load.lsp.in Diff Switch to side-by-side view
Loading...
src/cmp/cmpcond.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmplet2.lsp Diff Switch to side-by-side view
Loading...
src/doc/amop.txt Diff Switch to side-by-side view
Loading...
src/doc/types-and-classes Diff Switch to side-by-side view
Loading...
src/gc/aix_irix_threads.c Diff Switch to side-by-side view
Loading...
src/gc/darwin_stop_world.c Diff Switch to side-by-side view
Loading...
src/gc/doc/Makefile.am Diff Switch to side-by-side view
Loading...
src/gc/doc/Makefile.in Diff Switch to side-by-side view
Loading...
src/gc/doc/README.darwin Diff Switch to side-by-side view
Loading...
src/gc/doc/gcinterface.html Diff Switch to side-by-side view
Loading...
src/gc/doc/scale.html Diff Switch to side-by-side view
Loading...
src/gc/include/Makefile.am Diff Switch to side-by-side view
Loading...
src/gc/include/Makefile.in Diff Switch to side-by-side view
Loading...
src/gc/include/gc_config_macros.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/darwin_semaphore.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/darwin_stop_world.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/pthread_stop_world.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/pthread_support.h Diff Switch to side-by-side view
Loading...
src/gc/pthread_stop_world.c Diff Switch to side-by-side view
Loading...
src
Directory.
src/CHANGELOG Diff Switch to side-by-side view
Loading...
src/Makefile.in Diff Switch to side-by-side view
Loading...
src/aclocal.m4 Diff Switch to side-by-side view
Loading...
src/c
Directory.
src/c/all_symbols.d Diff Switch to side-by-side view
Loading...
src/c/alloc.d Diff Switch to side-by-side view
Loading...
src/c/alloc_2.d Diff Switch to side-by-side view
Loading...
src/c/assignment.d Diff Switch to side-by-side view
Loading...
src/c/backq.d Diff Switch to side-by-side view
Loading...
src/c/big.d Diff Switch to side-by-side view
Loading...
src/c/character.d Diff Switch to side-by-side view
Loading...
src/c/cinit.d Diff Switch to side-by-side view
Loading...
src/c/cmpaux.d Diff Switch to side-by-side view
Loading...
src/c/compiler.d Diff Switch to side-by-side view
Loading...
src/c/disassembler.d Diff Switch to side-by-side view
Loading...
src/c/dpp.c Diff Switch to side-by-side view
Loading...
src/c/error.d Diff Switch to side-by-side view
Loading...
src/c/eval.d Diff Switch to side-by-side view
Loading...
src/c/file.d Diff Switch to side-by-side view
Loading...
src/c/format.d Diff Switch to side-by-side view
Loading...
src/c/gbc.d Diff Switch to side-by-side view
Loading...
src/c/hash.d Diff Switch to side-by-side view
Loading...
src/c/instance.d Diff Switch to side-by-side view
Loading...
src/c/interpreter.d Diff Switch to side-by-side view
Loading...
src/c/list.d Diff Switch to side-by-side view
Loading...
src/c/load.d Diff Switch to side-by-side view
Loading...
src/c/macros.d Diff Switch to side-by-side view
Loading...
src/c/main.d Diff Switch to side-by-side view
Loading...
src/c/mapfun.d Diff Switch to side-by-side view
Loading...
src/c/multival.d Diff Switch to side-by-side view
Loading...
src/c/num_co.d Diff Switch to side-by-side view
Loading...
src/c/num_rand.d Diff Switch to side-by-side view
Loading...
src/c/num_sfun.d Diff Switch to side-by-side view
Loading...
src/c/number.d Diff Switch to side-by-side view
Loading...
src/c/package.d Diff Switch to side-by-side view
Loading...
src/c/pathname.d Diff Switch to side-by-side view
Loading...
src/c/predicate.d Diff Switch to side-by-side view
Loading...
src/c/print.d Diff Switch to side-by-side view
Loading...
src/c/read.d Diff Switch to side-by-side view
Loading...
src/c/stacks.d Diff Switch to side-by-side view
Loading...
src/c/symbol.d Diff Switch to side-by-side view
Loading...
src/c/symbols_list.h Diff Switch to side-by-side view
Loading...
src/c/time.d Diff Switch to side-by-side view
Loading...
src/c/typespec.d Diff Switch to side-by-side view
Loading...
src/c/unixint.d Diff Switch to side-by-side view
Loading...
src/clx
Directory.
src/cmp
Directory.
src/cmp/cmpcall.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmpcatch.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmpexit.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmplam.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmploc.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmpmain.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmpmulti.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmptop.lsp Diff Switch to side-by-side view
Loading...
src/cmp/cmpvar.lsp Diff Switch to side-by-side view
Loading...
src/cmp/sysfun.lsp Diff Switch to side-by-side view
Loading...
src/configure Diff Switch to side-by-side view
Loading...
src/configure.in Diff Switch to side-by-side view
Loading...
src/doc
Directory.
src/doc/todo.txt Diff Switch to side-by-side view
Loading...
src/gc
Directory.
src/gc/BCC_MAKEFILE Diff Switch to side-by-side view
Loading...
src/gc/Makefile Diff Switch to side-by-side view
Loading...
src/gc/Makefile.am Diff Switch to side-by-side view
Loading...
src/gc/Makefile.direct Diff Switch to side-by-side view
Loading...
src/gc/Makefile.dj Diff Switch to side-by-side view
Loading...
src/gc/Makefile.in Diff Switch to side-by-side view
Loading...
src/gc/acinclude.m4 Diff Switch to side-by-side view
Loading...
src/gc/aclocal.m4 Diff Switch to side-by-side view
Loading...
src/gc/alloc.c Diff Switch to side-by-side view
Loading...
src/gc/backgraph.c Diff Switch to side-by-side view
Loading...
src/gc/config.guess Diff Switch to side-by-side view
Loading...
src/gc/config.sub Diff Switch to side-by-side view
Loading...
src/gc/configure Diff Switch to side-by-side view
Loading...
src/gc/configure.host Diff Switch to side-by-side view
Loading...
src/gc/configure.in Diff Switch to side-by-side view
Loading...
src/gc/cord
Directory.
src/gc/cord/cordbscs.c Diff Switch to side-by-side view
Loading...
src/gc/cord/de_win.c Diff Switch to side-by-side view
Loading...
src/gc/dbg_mlc.c Diff Switch to side-by-side view
Loading...
src/gc/doc
Directory.
src/gc/doc/README Diff Switch to side-by-side view
Loading...
src/gc/doc/README.MacOSX Diff Switch to side-by-side view
Loading...
src/gc/doc/README.changes Diff Switch to side-by-side view
Loading...
src/gc/doc/README.macros Diff Switch to side-by-side view
Loading...
src/gc/doc/README.win32 Diff Switch to side-by-side view
Loading...
src/gc/doc/gcdescr.html Diff Switch to side-by-side view
Loading...
src/gc/doc/tree.html Diff Switch to side-by-side view
Loading...
src/gc/dyn_load.c Diff Switch to side-by-side view
Loading...
src/gc/finalize.c Diff Switch to side-by-side view
Loading...
src/gc/gc_dlopen.c Diff Switch to side-by-side view
Loading...
src/gc/if_mach.c Diff Switch to side-by-side view
Loading...
src/gc/include
Directory.
src/gc/include/gc.h Diff Switch to side-by-side view
Loading...
src/gc/include/gc_cpp.h Diff Switch to side-by-side view
Loading...
src/gc/include/gc_mark.h Diff Switch to side-by-side view
Loading...
src/gc/include/gc_pthread_redirects.h Diff Switch to side-by-side view
Loading...
src/gc/include/gc_typed.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/gc_locks.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/gc_pmark.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/gc_priv.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/gcconfig.h Diff Switch to side-by-side view
Loading...
src/gc/include/private/specific.h Diff Switch to side-by-side view
Loading...
src/gc/mach_dep.c Diff Switch to side-by-side view
Loading...
src/gc/mark.c Diff Switch to side-by-side view
Loading...
src/gc/mark_rts.c Diff Switch to side-by-side view
Loading...
src/gc/misc.c Diff Switch to side-by-side view
Loading...
src/gc/os_dep.c Diff Switch to side-by-side view
Loading...
src/gc/ptr_chck.c Diff Switch to side-by-side view
Loading...
src/gc/reclaim.c Diff Switch to side-by-side view
Loading...
src/gc/tests
Directory.
src/gc/tests/test.c Diff Switch to side-by-side view
Loading...
src/gc/tests/test_cpp.cc Diff Switch to side-by-side view
Loading...
src/gc/threadlibs.c Diff Switch to side-by-side view
Loading...
src/gc/typd_mlc.c Diff Switch to side-by-side view
Loading...
src/gc/version.h Diff Switch to side-by-side view
Loading...
src/gc/win32_threads.c Diff Switch to side-by-side view
Loading...
src/h
Directory.
src/h/config.h.in Diff Switch to side-by-side view
Loading...
src/h/external.h Diff Switch to side-by-side view
Loading...
src/h/internal.h Diff Switch to side-by-side view
Loading...
src/h/object.h Diff Switch to side-by-side view
Loading...
src/h/stacks.h Diff Switch to side-by-side view
Loading...
src/lsp
Directory.
src/lsp/autoload.lsp Diff Switch to side-by-side view
Loading...
src/lsp/load.lsp.in Diff Switch to side-by-side view
Loading...
src/util
Directory.
src/util/emacs.el Diff Switch to side-by-side view
Loading...
src/gc/linux_threads.c to src/gc/pthread_support.c
--- a/src/gc/linux_threads.c
+++ b/src/gc/pthread_support.c
@@ -29,11 +29,8 @@
  /* DG/UX ix86 support <takis@xfree86.org> */
 /*
  * Linux_threads.c now also includes some code to support HPUX and
- * OSF1 (Compaq Tru64 Unix, really).  The OSF1 support is not yet
- * functional.  The OSF1 code is based on Eric Benson's
- * patch, though that was originally against hpux_irix_threads.  The code
- * here is completely untested.  With 0.0000001% probability, it might
- * actually work.
+ * OSF1 (Compaq Tru64 Unix, really).  The OSF1 support is based on Eric Benson's
+ * patch.
  *
  * Eric also suggested an alternate basis for a lock implementation in
  * his code:
@@ -47,24 +44,22 @@
  * + #  define GC_LOCK_TAKEN GC_allocate_lock
  */
 
-/* #define DEBUG_THREADS 1 */
-
-/* ANSI C requires that a compilation unit contains something */
-
-# include "gc.h"
+/*#define DEBUG_THREADS 1*/
+/*#define GC_ASSERTIONS*/
+
+# include "private/pthread_support.h"
 
 # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
-     && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
-
-# include "private/gc_priv.h"
+     && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \
+     && !defined(GC_AIX_THREADS)
 
 # if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \
      && !defined(USE_HPUX_TLS)
 #   define USE_HPUX_TLS
 # endif
 
-# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS)) \
-      && !defined(USE_PTHREAD_SPECIFIC)
+# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
+      defined(GC_DARWIN_THREADS)) && !defined(USE_PTHREAD_SPECIFIC)
 #   define USE_PTHREAD_SPECIFIC
 # endif
 
@@ -101,11 +96,21 @@
 # include <unistd.h>
 # include <sys/mman.h>
 # include <sys/time.h>
-# include <semaphore.h>
-# include <signal.h>
 # include <sys/types.h>
 # include <sys/stat.h>
 # include <fcntl.h>
+
+#if defined(GC_DARWIN_THREADS)
+# include "private/darwin_semaphore.h"
+#else
+# include <semaphore.h>
+#endif /* !GC_DARWIN_THREADS */
+
+#if defined(GC_DARWIN_THREADS)
+# include <sys/sysctl.h>
+#endif /* GC_DARWIN_THREADS */
+
+
 
 #if defined(GC_DGUX386_THREADS)
 # include <sys/dg_sys_info.h>
@@ -129,126 +134,14 @@
 #     define REAL_FUNC(f) __d10_##f
 #   endif /* GC_DGUX386_THREADS */
 #   undef pthread_create
+#   if !defined(GC_DARWIN_THREADS)
 #   undef pthread_sigmask
+#   endif
 #   undef pthread_join
 #   undef pthread_detach
 #endif
 
-
 void GC_thr_init();
-
-#if DEBUG_THREADS
-
-#ifndef NSIG
-# if defined(MAXSIG)
-#  define NSIG (MAXSIG+1)
-# elif defined(_NSIG)
-#  define NSIG _NSIG
-# elif defined(__SIGRTMAX)
-#  define NSIG (__SIGRTMAX+1)
-# else
-  --> please fix it
-# endif
-#endif
-
-void GC_print_sig_mask()
-{
-    sigset_t blocked;
-    int i;
-
-    if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0)
-    	ABORT("pthread_sigmask");
-    GC_printf0("Blocked: ");
-    for (i = 1; i < NSIG; i++) {
-        if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); }
-    }
-    GC_printf0("\n");
-}
-#endif
-
-word GC_stop_count;	/* Incremented at the beginning of GC_stop_world. */
-
-#ifdef GC_OSF1_THREADS
-  GC_bool GC_retry_signals = TRUE;
-#else
-  GC_bool GC_retry_signals = FALSE;
-#endif
-
-/* We use the allocation lock to protect thread-related data structures. */
-
-/* The set of all known threads.  We intercept thread creation and 	*/
-/* joins.								*/
-/* Protected by allocation/GC lock.					*/
-/* Some of this should be declared volatile, but that's inconsistent	*/
-/* with some library routine declarations.  		 		*/
-typedef struct GC_Thread_Rep {
-    struct GC_Thread_Rep * next;  /* More recently allocated threads	*/
-				  /* with a given pthread id come 	*/
-				  /* first.  (All but the first are	*/
-				  /* guaranteed to be dead, but we may  */
-				  /* not yet have registered the join.) */
-    pthread_t id;
-    short flags;
-#	define FINISHED 1   	/* Thread has exited.	*/
-#	define DETACHED 2	/* Thread is intended to be detached.	*/
-#	define MAIN_THREAD 4	/* True for the original thread only.	*/
-    short thread_blocked;	/* Protected by GC lock.		*/
-    				/* Treated as a boolean value.  If set,	*/
-    				/* thread will acquire GC lock before	*/
-    				/* doing any pointer manipulations, and	*/
-    				/* has set its sp value.  Thus it does	*/
-    				/* not need to be sent a signal to stop	*/
-    				/* it.					*/
-    ptr_t stack_end;		/* Cold end of the stack.		*/
-    ptr_t stack_ptr;  		/* Valid only when stopped.      	*/
-#   ifdef IA64
-	ptr_t backing_store_end;
-	ptr_t backing_store_ptr;
-#   endif
-    int	signal;
-    void * status;		/* The value returned from the thread.  */
-    				/* Used only to avoid premature 	*/
-				/* reclamation of any data it might 	*/
-				/* reference.				*/
-    word last_stop_count;	/* GC_last_stop_count value when thread	*/
-    				/* last successfully handled a suspend	*/
-    				/* signal.				*/
-#   ifdef THREAD_LOCAL_ALLOC
-#	if CPP_WORDSZ == 64 && defined(ALIGN_DOUBLE)
-#	    define GRANULARITY 16
-#	    define NFREELISTS 49
-#	else
-#	    define GRANULARITY 8
-#	    define NFREELISTS 65
-#	endif
-	/* The ith free list corresponds to size i*GRANULARITY */
-#	define INDEX_FROM_BYTES(n) ((ADD_SLOP(n) + GRANULARITY - 1)/GRANULARITY)
-#	define BYTES_FROM_INDEX(i) ((i) * GRANULARITY - EXTRA_BYTES)
-#	define SMALL_ENOUGH(bytes) (ADD_SLOP(bytes) <= \
-				    (NFREELISTS-1)*GRANULARITY)
-	ptr_t ptrfree_freelists[NFREELISTS];
-	ptr_t normal_freelists[NFREELISTS];
-#	ifdef GC_GCJ_SUPPORT
-	  ptr_t gcj_freelists[NFREELISTS];
-#	endif
-		/* Free lists contain either a pointer or a small count */
-		/* reflecting the number of granules allocated at that	*/
-		/* size.						*/
-		/* 0 ==> thread-local allocation in use, free list	*/
-		/*       empty.						*/
-		/* > 0, <= DIRECT_GRANULES ==> Using global allocation,	*/
-		/*       too few objects of this size have been		*/
-		/* 	 allocated by this thread.			*/
-		/* >= HBLKSIZE  => pointer to nonempty free list.	*/
-		/* > DIRECT_GRANULES, < HBLKSIZE ==> transition to	*/
-		/*    local alloc, equivalent to 0.			*/
-#	define DIRECT_GRANULES (HBLKSIZE/GRANULARITY)
-		/* Don't use local free lists for up to this much 	*/
-		/* allocation.						*/
-#   endif
-} * GC_thread;
-
-GC_thread GC_lookup_thread(pthread_t id);
 
 static GC_bool parallel_initialized = FALSE;
 
@@ -362,7 +255,9 @@
 	int index = INDEX_FROM_BYTES(bytes);
 	ptr_t * my_fl;
 	ptr_t my_entry;
+#	if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
 	GC_key_t k = GC_thread_key;
+#	endif
 	void * tsd;
 
 #	if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
@@ -409,13 +304,14 @@
 	ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
 		        -> ptrfree_freelists + index;
 	ptr_t my_entry = *my_fl;
+    
 	if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
 	    GC_PTR result = (GC_PTR)my_entry;
 	    *my_fl = obj_link(my_entry);
 	    return result;
 	} else if ((word)my_entry - 1 < DIRECT_GRANULES) {
 	    *my_fl = my_entry + index + 1;
-            return GC_malloc_atomic(bytes);
+        return GC_malloc_atomic(bytes);
 	} else {
 	    GC_generic_malloc_many(BYTES_FROM_INDEX(index), PTRFREE, my_fl);
 	    /* *my_fl is updated while the collector is excluded;	*/
@@ -487,32 +383,6 @@
 
 # endif /* !THREAD_LOCAL_ALLOC */
 
-/*
- * We use signals to stop threads during GC.
- * 
- * Suspended threads wait in signal handler for SIG_THR_RESTART.
- * That's more portable than semaphores or condition variables.
- * (We do use sem_post from a signal handler, but that should be portable.)
- *
- * The thread suspension signal SIG_SUSPEND is now defined in gc_priv.h.
- * Note that we can't just stop a thread; we need it to save its stack
- * pointer(s) and acknowledge.
- */
-
-#ifndef SIG_THR_RESTART
-#  if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
-#    ifdef _SIGRTMIN
-#      define SIG_THR_RESTART _SIGRTMIN + 5
-#    else
-#      define SIG_THR_RESTART SIGRTMIN + 5
-#    endif
-#  else
-#   define SIG_THR_RESTART SIGXCPU
-#  endif
-#endif
-
-sem_t GC_suspend_ack_sem;
-
 #if 0
 /*
 To make sure that we're using LinuxThreads and not some other thread
@@ -526,10 +396,6 @@
 */
 void (*dummy_var_to_force_linux_threads)() = pthread_kill_other_threads_np;
 #endif /* 0 */
-
-#if defined(SPARC) || defined(IA64)
-  extern word GC_save_regs_in_stack();
-#endif
 
 long GC_nprocs = 1;	/* Number of processors.  We may not have	*/
 			/* access to all of them, but this is as good	*/
@@ -627,112 +493,6 @@
 
 #endif /* !PARALLEL_MARK */
 
-void GC_suspend_handler(int sig)
-{
-    int dummy;
-    pthread_t my_thread = pthread_self();
-    GC_thread me;
-    sigset_t all_sigs;
-    sigset_t old_sigs;
-    int i;
-    sigset_t mask;
-#   ifdef PARALLEL_MARK
-	word my_mark_no = GC_mark_no;
-	/* Marker can't proceed until we acknowledge.  Thus this is	*/
-	/* guaranteed to be the mark_no correspending to our 		*/
-	/* suspension, i.e. the marker can't have incremented it yet.	*/
-#   endif
-    word my_stop_count = GC_stop_count;
-
-    if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler");
-
-#if DEBUG_THREADS
-    GC_printf1("Suspending 0x%lx\n", my_thread);
-#endif
-
-    me = GC_lookup_thread(my_thread);
-    /* The lookup here is safe, since I'm doing this on behalf  */
-    /* of a thread which holds the allocation lock in order	*/
-    /* to stop the world.  Thus concurrent modification of the	*/
-    /* data structure is impossible.				*/
-    if (me -> last_stop_count == my_stop_count) {
-	/* Duplicate signal.  OK if we are retrying.	*/
-	if (!GC_retry_signals) {
-	    WARN("Duplicate suspend signal in thread %lx\n",
-		 pthread_self());
-	}
-	return;
-    }
-#   ifdef SPARC
-	me -> stack_ptr = (ptr_t)GC_save_regs_in_stack();
-#   else
-	me -> stack_ptr = (ptr_t)(&dummy);
-#   endif
-#   ifdef IA64
-	me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack();
-#   endif
-
-    /* Tell the thread that wants to stop the world that this   */
-    /* thread has been stopped.  Note that sem_post() is  	*/
-    /* the only async-signal-safe primitive in LinuxThreads.    */
-    sem_post(&GC_suspend_ack_sem);
-    me -> last_stop_count = my_stop_count;
-
-    /* Wait until that thread tells us to restart by sending    */
-    /* this thread a SIG_THR_RESTART signal.			*/
-    /* SIG_THR_RESTART should be masked at this point.  Thus there	*/
-    /* is no race.						*/
-    if (sigfillset(&mask) != 0) ABORT("sigfillset() failed");
-    if (sigdelset(&mask, SIG_THR_RESTART) != 0) ABORT("sigdelset() failed");
-#   ifdef NO_SIGNALS
-      if (sigdelset(&mask, SIGINT) != 0) ABORT("sigdelset() failed");
-      if (sigdelset(&mask, SIGQUIT) != 0) ABORT("sigdelset() failed");
-      if (sigdelset(&mask, SIGTERM) != 0) ABORT("sigdelset() failed");
-      if (sigdelset(&mask, SIGABRT) != 0) ABORT("sigdelset() failed");
-#   endif
-    do {
-	    me->signal = 0;
-	    sigsuspend(&mask);             /* Wait for signal */
-    } while (me->signal != SIG_THR_RESTART);
-    /* If the RESTART signal gets lost, we can still lose.  That should be  */
-    /* less likely than losing the SUSPEND signal, since we don't do much   */
-    /* between the sem_post and sigsuspend.	   			    */
-    /* We'd need more handshaking to work around that, since we don't want  */
-    /* to accidentally leave a RESTART signal pending, thus causing us to   */
-    /* continue prematurely in a future round.				    */ 
-
-#if DEBUG_THREADS
-    GC_printf1("Continuing 0x%lx\n", my_thread);
-#endif
-}
-
-void GC_restart_handler(int sig)
-{
-    GC_thread me;
-
-    if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
-
-    /* Let the GC_suspend_handler() know that we got a SIG_THR_RESTART. */
-    /* The lookup here is safe, since I'm doing this on behalf  */
-    /* of a thread which holds the allocation lock in order	*/
-    /* to stop the world.  Thus concurrent modification of the	*/
-    /* data structure is impossible.				*/
-    me = GC_lookup_thread(pthread_self());
-    me->signal = SIG_THR_RESTART;
-
-    /*
-    ** Note: even if we didn't do anything useful here,
-    ** it would still be necessary to have a signal handler,
-    ** rather than ignoring the signals, otherwise
-    ** the signals will not be delivered at all, and
-    ** will thus not interrupt the sigsuspend() above.
-    */
-
-#if DEBUG_THREADS
-    GC_printf1("In GC_restart_handler for 0x%lx\n", pthread_self());
-#endif
-}
-
 /* Defining INSTALL_LOOPING_SEGV_HANDLER causes SIGSEGV and SIGBUS to 	*/
 /* result in an infinite loop in a signal handler.  This can be very	*/
 /* useful for debugging, since (as of RH7) gdb still seems to have	*/
@@ -748,12 +508,15 @@
 
 GC_bool GC_thr_initialized = FALSE;
 
-# define THREAD_TABLE_SZ 128	/* Must be power of 2	*/
 volatile GC_thread GC_threads[THREAD_TABLE_SZ];
 
 void GC_push_thread_structures GC_PROTO((void))
 {
     GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
+#   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
+      GC_push_all((ptr_t)(&GC_thread_key),
+	  (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key));
+#   endif
 }
 
 #ifdef THREAD_LOCAL_ALLOC
@@ -899,218 +662,6 @@
 }
 #endif /* HANDLE_FORK */
 
-/* There seems to be a very rare thread stopping problem.  To help us  */
-/* debug that, we save the ids of the stopping thread. */
-pthread_t GC_stopping_thread;
-int GC_stopping_pid;
-
-/* We hold the allocation lock.  Suspend all threads that might	*/
-/* still be running.  Return the number of suspend signals that	*/
-/* were sent.							*/
-int GC_suspend_all()
-{
-    int n_live_threads = 0;
-    int i;
-    GC_thread p;
-    int result;
-    pthread_t my_thread = pthread_self();
-
-    GC_stopping_thread = my_thread;    /* debugging only.      */
-    GC_stopping_pid = getpid();                /* debugging only.      */
-    for (i = 0; i < THREAD_TABLE_SZ; i++) {
-      for (p = GC_threads[i]; p != 0; p = p -> next) {
-        if (p -> id != my_thread) {
-            if (p -> flags & FINISHED) continue;
-	    if (p -> last_stop_count == GC_stop_count) continue;
-	    if (p -> thread_blocked) /* Will wait */ continue;
-            n_live_threads++;
-	    #if DEBUG_THREADS
-	      GC_printf1("Sending suspend signal to 0x%lx\n", p -> id);
-	    #endif
-            result = pthread_kill(p -> id, SIG_SUSPEND);
-	    switch(result) {
-                case ESRCH:
-                    /* Not really there anymore.  Possible? */
-                    n_live_threads--;
-                    break;
-                case 0:
-                    break;
-                default:
-                    ABORT("pthread_kill failed");
-            }
-        }
-      }
-    }
-    return n_live_threads;
-}
-
-/* Caller holds allocation lock.	*/
-void GC_stop_world()
-{
-    register int i;
-    register int n_live_threads;
-
-    /* Make sure all free list construction has stopped before we start. */
-    /* No new construction can start, since free list construction is	*/
-    /* required to acquire and release the GC lock before it starts,	*/
-    /* and we have the lock.						*/
-#   ifdef PARALLEL_MARK
-      GC_acquire_mark_lock();
-      GC_ASSERT(GC_fl_builder_count == 0);
-      /* We should have previously waited for it to become zero. */
-#   endif /* PARALLEL_MARK */
-    ++GC_stop_count;
-    n_live_threads = GC_suspend_all();
-    if (GC_retry_signals) {
-	unsigned long wait_usecs = 0;  /* Total wait since retry.	*/
-#	define WAIT_UNIT 3000
-#	define RETRY_INTERVAL 100000
-	for (;;) {
-	    int ack_count;
-
-	    sem_getvalue(&GC_suspend_ack_sem, &ack_count);
-	    if (ack_count == n_live_threads) break;
-	    if (wait_usecs > RETRY_INTERVAL) {
-		int newly_sent = GC_suspend_all();
-
-#               ifdef CONDPRINT
-                  if (GC_print_stats) {
-		    GC_printf1("Resent %ld signals after timeout\n",
-		               newly_sent);
-	          }
-#               endif
-	        sem_getvalue(&GC_suspend_ack_sem, &ack_count);
-		if (newly_sent < n_live_threads - ack_count) {
-		    WARN("Lost some threads during GC_stop_world?!\n",0);
-		    n_live_threads = ack_count + newly_sent;
-		}
-		wait_usecs = 0;
-	    }
-	    usleep(WAIT_UNIT);
-	    wait_usecs += WAIT_UNIT;
-	}
-    }
-    for (i = 0; i < n_live_threads; i++) {
-    	if (0 != sem_wait(&GC_suspend_ack_sem))
-	    ABORT("sem_wait in handler failed");
-    }
-#   ifdef PARALLEL_MARK
-      GC_release_mark_lock();
-#   endif
-    #if DEBUG_THREADS
-      GC_printf1("World stopped from 0x%lx\n", pthread_self());
-    #endif
-    GC_stopping_thread = 0;  /* debugging only */
-}
-
-/* Caller holds allocation lock, and has held it continuously since	*/
-/* the world stopped.							*/
-void GC_start_world()
-{
-    pthread_t my_thread = pthread_self();
-    register int i;
-    register GC_thread p;
-    register int n_live_threads = 0;
-    register int result;
-    
-#   if DEBUG_THREADS
-      GC_printf0("World starting\n");
-#   endif
-
-    for (i = 0; i < THREAD_TABLE_SZ; i++) {
-      for (p = GC_threads[i]; p != 0; p = p -> next) {
-        if (p -> id != my_thread) {
-            if (p -> flags & FINISHED) continue;
-	    if (p -> thread_blocked) continue;
-            n_live_threads++;
-	    #if DEBUG_THREADS
-	      GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
-	    #endif
-            result = pthread_kill(p -> id, SIG_THR_RESTART);
-	    switch(result) {
-                case ESRCH:
-                    /* Not really there anymore.  Possible? */
-                    n_live_threads--;
-                    break;
-                case 0:
-                    break;
-                default:
-                    ABORT("pthread_kill failed");
-            }
-        }
-      }
-    }
-    #if DEBUG_THREADS
-      GC_printf0("World started\n");
-    #endif
-}
-
-# ifdef IA64
-#   define IF_IA64(x) x
-# else
-#   define IF_IA64(x)
-# endif
-/* We hold allocation lock.  Should do exactly the right thing if the	*/
-/* world is stopped.  Should not fail if it isn't.			*/
-void GC_push_all_stacks()
-{
-    int i;
-    GC_thread p;
-    ptr_t sp = GC_approx_sp();
-    ptr_t lo, hi;
-    /* On IA64, we also need to scan the register backing store. */
-    IF_IA64(ptr_t bs_lo; ptr_t bs_hi;)
-    pthread_t me = pthread_self();
-    
-    if (!GC_thr_initialized) GC_thr_init();
-    #if DEBUG_THREADS
-        GC_printf1("Pushing stacks from thread 0x%lx\n", (unsigned long) me);
-    #endif
-    for (i = 0; i < THREAD_TABLE_SZ; i++) {
-      for (p = GC_threads[i]; p != 0; p = p -> next) {
-        if (p -> flags & FINISHED) continue;
-        if (pthread_equal(p -> id, me)) {
-#  	    ifdef SPARC
-	        lo = (ptr_t)GC_save_regs_in_stack();
-#  	    else
- 	        lo = GC_approx_sp();
-#           endif
-	    IF_IA64(bs_hi = (ptr_t)GC_save_regs_in_stack();)
-	} else {
-	    lo = p -> stack_ptr;
-	    IF_IA64(bs_hi = p -> backing_store_ptr;)
-	}
-        if ((p -> flags & MAIN_THREAD) == 0) {
-	    hi = p -> stack_end;
-	    IF_IA64(bs_lo = p -> backing_store_end);
-        } else {
-            /* The original stack. */
-            hi = GC_stackbottom;
-	    IF_IA64(bs_lo = BACKING_STORE_BASE;)
-        }
-        #if DEBUG_THREADS
-            GC_printf3("Stack for thread 0x%lx = [%lx,%lx)\n",
-    	        (unsigned long) p -> id,
-		(unsigned long) lo, (unsigned long) hi);
-        #endif
-	if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n");
-#       ifdef STACK_GROWS_UP
-	  /* We got them backwards! */
-          GC_push_all_stack(hi, lo);
-#       else
-          GC_push_all_stack(lo, hi);
-#	endif
-#	ifdef IA64
-          if (pthread_equal(p -> id, me)) {
-	    GC_push_all_eager(bs_lo, bs_hi);
-	  } else {
-	    GC_push_all_stack(bs_lo, bs_hi);
-	  }
-#	endif
-      }
-    }
-}
-
 #ifdef USE_PROC_FOR_LIBRARIES
 int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi)
 {
@@ -1145,14 +696,11 @@
     /* appears to be buggy in many cases.				*/
     /* We look for lines "cpu<n>" in /proc/stat.			*/
 #   define STAT_BUF_SIZE 4096
-#   if defined(GC_USE_LD_WRAP)
-#	define STAT_READ __real_read
-#   else
-#	define STAT_READ read
-#   endif    
+#   define STAT_READ read
+	/* If read is wrapped, this may need to be redefined to call 	*/
+	/* the real one.						*/
     char stat_buf[STAT_BUF_SIZE];
     int f;
-    char c;
     word result = 1;
 	/* Some old kernels only have a single "cpu nnnn ..."	*/
 	/* entry in /proc/stat.  We identify those as 		*/
@@ -1181,6 +729,7 @@
 /* If wait_for_all is true, then we exit with the GC lock held and no	*/
 /* collection in progress; otherwise we just wait for the current GC	*/
 /* to finish.								*/
+extern GC_bool GC_collection_in_progress();
 void GC_wait_for_gc_completion(GC_bool wait_for_all)
 {
     if (GC_incremental && GC_collection_in_progress()) {
@@ -1284,39 +833,14 @@
 /* We hold the allocation lock.	*/
 void GC_thr_init()
 {
-    int dummy;
+#	ifndef GC_DARWIN_THREADS
+        int dummy;
+#	endif
     GC_thread t;
-    struct sigaction act;
 
     if (GC_thr_initialized) return;
     GC_thr_initialized = TRUE;
-
-    if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
-    	ABORT("sem_init failed");
-
-    act.sa_flags = SA_RESTART;
-    if (sigfillset(&act.sa_mask) != 0) {
-    	ABORT("sigfillset() failed");
-    }
-#   ifdef NO_SIGNALS
-      if (sigdelset(&act.sa_mask, SIGINT) != 0
-	  || sigdelset(&act.sa_mask, SIGQUIT != 0)
-	  || sigdelset(&act.sa_mask, SIGABRT != 0)
-	  || sigdelset(&act.sa_mask, SIGTERM != 0)) {
-        ABORT("sigdelset() failed");
-      }
-#   endif
-
-    /* SIG_THR_RESTART is unmasked by the handler when necessary. 	*/
-    act.sa_handler = GC_suspend_handler;
-    if (sigaction(SIG_SUSPEND, &act, NULL) != 0) {
-    	ABORT("Cannot set SIG_SUSPEND handler");
-    }
-
-    act.sa_handler = GC_restart_handler;
-    if (sigaction(SIG_THR_RESTART, &act, NULL) != 0) {
-    	ABORT("Cannot set SIG_THR_RESTART handler");
-    }
+    
 #   ifdef HANDLE_FORK
       /* Prepare for a possible fork.	*/
         pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
@@ -1324,21 +848,14 @@
 #   endif /* HANDLE_FORK */
     /* Add the initial thread, so we can stop it.	*/
       t = GC_new_thread(pthread_self());
-      t -> stack_ptr = (ptr_t)(&dummy);
+#     ifdef GC_DARWIN_THREADS
+         t -> stop_info.mach_thread = mach_thread_self();
+#     else
+         t -> stop_info.stack_ptr = (ptr_t)(&dummy);
+#     endif
       t -> flags = DETACHED | MAIN_THREAD;
 
-    /* Check for GC_RETRY_SIGNALS.	*/
-      if (0 != GETENV("GC_RETRY_SIGNALS")) {
-	  GC_retry_signals = TRUE;
-      }
-      if (0 != GETENV("GC_NO_RETRY_SIGNALS")) {
-	  GC_retry_signals = FALSE;
-      }
-#     ifdef CONDPRINT
-          if (GC_print_stats) {
-              GC_printf0("Will retry suspend signal if necessary.\n");
-	  }
-#     endif
+    GC_stop_init();
 
     /* Set GC_nprocs.  */
       {
@@ -1356,6 +873,12 @@
 #	endif
 #       if defined(GC_FREEBSD_THREADS)
           GC_nprocs = 1;
+#       endif
+#       if defined(GC_DARWIN_THREADS)
+	  int ncpus = 1;
+	  size_t len = sizeof(ncpus);
+	  sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
+	  GC_nprocs = ncpus;
 #       endif
 #	if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
           GC_nprocs = GC_get_nprocs();
@@ -1411,7 +934,8 @@
 {
     if (parallel_initialized) return;
     parallel_initialized = TRUE;
-    	/* GC_init() calls us back, so set flag first.	*/
+
+    /* GC_init() calls us back, so set flag first.	*/
     if (!GC_is_initialized) GC_init();
     /* If we are using a parallel marker, start the helper threads.  */
 #     ifdef PARALLEL_MARK
@@ -1426,6 +950,7 @@
 }
 
 
+#if !defined(GC_DARWIN_THREADS)
 int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset)
 {
     sigset_t fudged_set;
@@ -1437,6 +962,7 @@
     }
     return(REAL_FUNC(pthread_sigmask)(how, set, oset));
 }
+#endif /* !GC_DARWIN_THREADS */
 
 /* Wrappers for functions that are likely to block for an appreciable	*/
 /* length of time.  Must be called in pairs, if at all.			*/
@@ -1450,25 +976,29 @@
     me = GC_lookup_thread(pthread_self());
     GC_ASSERT(!(me -> thread_blocked));
 #   ifdef SPARC
-	me -> stack_ptr = (ptr_t)GC_save_regs_in_stack();
+	me -> stop_info.stack_ptr = (ptr_t)GC_save_regs_in_stack();
 #   else
-	me -> stack_ptr = (ptr_t)GC_approx_sp();
+#   ifndef GC_DARWIN_THREADS
+	me -> stop_info.stack_ptr = (ptr_t)GC_approx_sp();
+#   endif
 #   endif
 #   ifdef IA64
 	me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack() + SP_SLOP;
 #   endif
     /* Add some slop to the stack pointer, since the wrapped call may 	*/
     /* end up pushing more callee-save registers.			*/
+#   ifndef GC_DARWIN_THREADS
 #   ifdef STACK_GROWS_UP
-	me -> stack_ptr += SP_SLOP;
+	me -> stop_info.stack_ptr += SP_SLOP;
 #   else
-	me -> stack_ptr -= SP_SLOP;
+	me -> stop_info.stack_ptr -= SP_SLOP;
+#   endif
 #   endif
     me -> thread_blocked = TRUE;
     UNLOCK();
 }
 
-GC_end_blocking(void) {
+void GC_end_blocking(void) {
     GC_thread me;
     LOCK();   /* This will block if the world is stopped.	*/
     me = GC_lookup_thread(pthread_self());
@@ -1596,8 +1126,12 @@
 #   endif
     LOCK();
     me = GC_new_thread(my_pthread);
+#ifdef GC_DARWIN_THREADS
+    me -> stop_info.mach_thread = mach_thread_self();
+#else
+    me -> stop_info.stack_ptr = 0;
+#endif
     me -> flags = si -> flags;
-    me -> stack_ptr = 0;
     /* me -> stack_end = GC_linux_stack_base(); -- currently (11/99)	*/
     /* doesn't work because the stack base in /proc/self/stat is the 	*/
     /* one for the main thread.  There is a strong argument that that's	*/
@@ -1605,12 +1139,14 @@
 #   ifdef STACK_GROWS_DOWN
       me -> stack_end = (ptr_t)(((word)(&dummy) + (GC_page_size - 1))
 		                & ~(GC_page_size - 1));
-      me -> stack_ptr = me -> stack_end - 0x10;
+#	  ifndef GC_DARWIN_THREADS
+        me -> stop_info.stack_ptr = me -> stack_end - 0x10;
+#	  endif
 	/* Needs to be plausible, since an asynchronous stack mark	*/
 	/* should not crash.						*/
 #   else
       me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1));
-      me -> stack_ptr = me -> stack_end + 0x10;
+      me -> stop_info.stack_ptr = me -> stack_end + 0x10;
 #   endif
     /* This is dubious, since we may be more than a page into the stack, */
     /* and hence skip some of it, though it's not clear that matters.	 */
@@ -1639,7 +1175,6 @@
         GC_printf1("Finishing thread 0x%x\n", pthread_self());
 #endif
     me -> status = result;
-    me -> flags |= FINISHED;
     pthread_cleanup_pop(1);
     /* Cleanup acquires lock, ensuring that we can't exit		*/
     /* while a collection that thinks we're alive is trying to stop     */
@@ -1653,8 +1188,6 @@
                   void *(*start_routine)(void *), void *arg)
 {
     int result;
-    GC_thread t;
-    pthread_t my_new_thread;
     int detachstate;
     word my_flags = 0;
     struct start_info * si; 
@@ -1676,6 +1209,22 @@
     si -> arg = arg;
     LOCK();
     if (!GC_thr_initialized) GC_thr_init();
+#   ifdef GC_ASSERTIONS
+      {
+	int stack_size;
+	if (NULL == attr) {
+	   pthread_attr_t my_attr;
+	   pthread_attr_init(&my_attr);
+	   pthread_attr_getstacksize(&my_attr, &stack_size);
+	} else {
+	   pthread_attr_getstacksize(attr, &stack_size);
+	}
+	GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
+	/* Our threads may need to do some work for the GC.	*/
+	/* Ridiculously small threads won't work, and they	*/
+	/* probably wouldn't work anyway.			*/
+      }
+#   endif
     if (NULL == attr) {
 	detachstate = PTHREAD_CREATE_JOINABLE;
     } else { 
@@ -1690,6 +1239,7 @@
 #   endif
 
     result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si);
+
 #   ifdef DEBUG_THREADS
         GC_printf1("Started thread 0x%X\n", *new_thread);
 #   endif
@@ -1697,10 +1247,10 @@
     /* This also ensures that we hold onto si until the child is done	*/
     /* with it.  Thus it doesn't matter whether it is otherwise		*/
     /* visible to the collector.					*/
-        while (0 != sem_wait(&(si -> registered))) {
-	    if (EINTR != errno) ABORT("sem_wait failed");
-	}
-        sem_destroy(&(si -> registered));
+    while (0 != sem_wait(&(si -> registered))) {
+        if (EINTR != errno) ABORT("sem_wait failed");
+    }
+    sem_destroy(&(si -> registered));
 	LOCK();
 	GC_INTERNAL_FREE(si);
 	UNLOCK();
@@ -1742,7 +1292,9 @@
 void GC_pause()
 {
     int i;
-    volatile word dummy = 0;
+#	ifndef __GNUC__
+        volatile word dummy = 0;
+#	endif
 
     for (i = 0; i < 10; ++i) { 
 #     ifdef __GNUC__
@@ -1781,6 +1333,7 @@
 
 void GC_generic_lock(pthread_mutex_t * lock)
 {
+#ifndef NO_PTHREAD_TRYLOCK
     unsigned pause_length = 1;
     unsigned i;
     
@@ -1798,6 +1351,7 @@
 		ABORT("Unexpected error from pthread_mutex_trylock");
         }
     }
+#endif /* !NO_PTHREAD_TRYLOCK */
     pthread_mutex_lock(lock);
 }
 
@@ -1875,14 +1429,17 @@
 }
 
 #else  /* !USE_SPINLOCK */
-
 void GC_lock()
 {
+#ifndef NO_PTHREAD_TRYLOCK
     if (1 == GC_nprocs || GC_collecting) {
 	pthread_mutex_lock(&GC_allocate_ml);
     } else {
         GC_generic_lock(&GC_allocate_ml);
     }
+#else  /* !NO_PTHREAD_TRYLOCK */
+    pthread_mutex_lock(&GC_allocate_ml);
+#endif /* !NO_PTHREAD_TRYLOCK */
 }
 
 #endif /* !USE_SPINLOCK */
src/gc/mips_sgi_mach_dep.S to src/gc/mips_sgi_mach_dep.s
--- a/src/gc/mips_sgi_mach_dep.S
+++ b/src/gc/mips_sgi_mach_dep.s
@@ -1,5 +1,10 @@
 #include <sys/regdef.h>
 #include <sys/asm.h>
+/* This file must be preprocessed.  But the SGI assembler always does	*/
+/* that.  Furthermore, a generic preprocessor won't do, since some of	*/
+/* the SGI-supplied include files rely on behavior of the MIPS 		*/
+/* assembler.  Hence we treat and name this file as though it required	*/
+/* no preprocessing.							*/
 
 # define call_push(x)     move    $4,x;    jal     GC_push_one
 
src/gc/powerpc_macosx_mach_dep.s to src/gc/powerpc_darwin_mach_dep.s
--- a/src/gc/powerpc_macosx_mach_dep.s
+++ b/src/gc/powerpc_darwin_mach_dep.s
@@ -1,70 +1,67 @@
-	
+
+; GC_push_regs function. Under some optimization levels GCC will clobber
+; some of the non-volatile registers before we get a chance to save them
+; therefore, this can't be inline asm.
+
 .text
+	.align 2
+	.globl _GC_push_regs
+_GC_push_regs:
     
-    .set   linkageArea,24
-    .set   params,4
-    .set   alignment,4
+    ; Prolog
+	mflr r0
+	stw r0,8(r1)
+	stwu r1,-80(r1)
 
-    .set   spaceToSave,linkageArea+params+alignment
-    .set   spaceToSave8,spaceToSave+8
+	; Push r13-r31
+	mr r3,r13
+	bl L_GC_push_one$stub
+	mr r3,r14
+	bl L_GC_push_one$stub
+	mr r3,r15
+	bl L_GC_push_one$stub
+	mr r3,r16
+	bl L_GC_push_one$stub
+	mr r3,r17
+	bl L_GC_push_one$stub
+	mr r3,r18
+	bl L_GC_push_one$stub
+	mr r3,r19
+	bl L_GC_push_one$stub
+	mr r3,r20
+	bl L_GC_push_one$stub
+	mr r3,r21
+	bl L_GC_push_one$stub
+	mr r3,r22
+	bl L_GC_push_one$stub
+	mr r3,r23
+	bl L_GC_push_one$stub
+	mr r3,r24
+	bl L_GC_push_one$stub
+	mr r3,r25
+	bl L_GC_push_one$stub
+	mr r3,r26
+	bl L_GC_push_one$stub
+	mr r3,r27
+	bl L_GC_push_one$stub
+	mr r3,r28
+	bl L_GC_push_one$stub
+	mr r3,r29
+	bl L_GC_push_one$stub
+	mr r3,r30
+	bl L_GC_push_one$stub
+	mr r3,r31
+	bl L_GC_push_one$stub
 
-; Mark from machine registers that are saved by C compiler
-    .globl  _GC_push_regs
-_GC_push_regs:
-    ; PROLOG
-    mflr    r0          ; get return address
-    stw     r0,8(r1)    ; save return address
-    stwu    r1,-spaceToSave(r1)   ; skip over caller save area
-    ;
-    mr      r3,r2         ; mark from r2. Well Im not really sure
-                          ; that this is necessary or even the right
-                          ; thing to do - at least it doesnt harm...
-                          ; According to Apples docs it points to
-                          ; the direct data area, whatever that is...
-    bl 	    L_GC_push_one$stub
-    mr      r3,r13        ; mark from r13-r31
-    bl 	    L_GC_push_one$stub
-    mr      r3,r14
-    bl 	    L_GC_push_one$stub
-    mr      r3,r15
-    bl 	    L_GC_push_one$stub
-    mr      r3,r16
-    bl 	    L_GC_push_one$stub
-    mr      r3,r17
-    bl 	    L_GC_push_one$stub
-    mr      r3,r18
-    bl 	    L_GC_push_one$stub
-    mr      r3,r19
-    bl 	    L_GC_push_one$stub
-    mr      r3,r20
-    bl 	    L_GC_push_one$stub
-    mr      r3,r21
-    bl 	    L_GC_push_one$stub
-    mr      r3,r22
-    bl 	    L_GC_push_one$stub
-    mr      r3,r23
-    bl 	    L_GC_push_one$stub
-    mr      r3,r24
-    bl 	    L_GC_push_one$stub
-    mr      r3,r25
-    bl 	    L_GC_push_one$stub
-    mr      r3,r26
-    bl 	    L_GC_push_one$stub
-    mr      r3,r27
-    bl 	    L_GC_push_one$stub
-    mr      r3,r28
-    bl 	    L_GC_push_one$stub
-    mr      r3,r29
-    bl 	    L_GC_push_one$stub
-    mr      r3,r30
-    bl 	    L_GC_push_one$stub
-    mr      r3,r31
-    bl 	    L_GC_push_one$stub
-    ; EPILOG
-    lwz     r0,spaceToSave8(r1)   ; get return address back
-    mtlr    r0    ; reset link register
-    addic   r1,r1,spaceToSave   ; restore stack pointer
-    blr
+    ; 
+    lwz r0,88(r1)
+    addi r1,r1,80
+	mtlr r0
+    	
+	; Return
+	blr
+
+; PIC stuff, generated by GCC
 
 .data
 .picsymbol_stub
@@ -85,11 +82,3 @@
 L_GC_push_one$lazy_ptr:
 	.indirect_symbol _GC_push_one
 	.long dyld_stub_binding_helper
-.non_lazy_symbol_pointer
-L_GC_push_one$non_lazy_ptr:
-	.indirect_symbol _GC_push_one
-	.long 0
-	
-
-
-
1 2 3 .. 7 > >> (Page 1 of 7)