--- boehm-gc/alpha_mach_dep.s Fri Aug 17 11:30:45 2001
+++ boehm-gc/alpha_mach_dep.s Sat Sep 13 02:10:15 2003
@@ -1,3 +1,4 @@
-+ # $Id: darwin-gc.patch,v 1.4 2003/09/26 01:54:05 megacz Exp $
++ # $Id: darwin-gc.patch,v 1.5 2003/09/26 05:41:51 megacz Exp $
.arch ev6
.text
--- /tmp/gcc-3.3/boehm-gc/win32_threads.c Mon Apr 28 13:55:07 2003
-+++ upstream/gcc-3.3/src/boehm-gc/win32_threads.c Thu Sep 25 05:31:33 2003
-@@ -2,12 +2,26 @@
++++ upstream/gcc-3.3/src/boehm-gc/win32_threads.c Thu Sep 25 22:38:28 2003
+@@ -337,7 +337,7 @@
- #include "private/gc_priv.h"
-
--#if 0
--#define STRICT
--#include <windows.h>
-+#ifdef CYGWIN32
-+# include <errno.h>
-+
-+ /* Cygwin-specific forward decls */
-+# undef pthread_create
-+# undef pthread_sigmask
-+# undef pthread_join
-+# undef dlopen
-+
-+# define DEBUG_CYGWIN_THREADS 0
-+
-+ GC_bool GC_thr_initialized = FALSE;
-+ void * GC_start_routine(void * arg);
-+ void GC_thread_exit_proc(void *arg);
-+
- #endif
-
--#define MAX_THREADS 64
-+#ifndef MAX_THREADS
-+# define MAX_THREADS 64
-+#endif
-
- struct thread_entry {
- LONG in_use;
-@@ -18,6 +32,12 @@
- /* !in_use ==> stack == 0 */
- CONTEXT context;
- GC_bool suspended;
-+
-+# ifdef CYGWIN32
-+ void *status; /* hold exit value until join in case it's a pointer */
-+ pthread_t pthread_id;
-+# endif
-+
- };
-
- volatile GC_bool GC_please_stop = FALSE;
-@@ -29,6 +49,12 @@
- /* Unlike the other threads implementations, the thread table here */
- /* contains no pointers to the collectable heap. Thus we have */
- /* no private structures we need to preserve. */
-+# ifdef CYGWIN32
-+ { int i; /* pthreads may keep a pointer in the thread exit value */
-+ for (i = 0; i < MAX_THREADS; i++)
-+ if (thread_table[i].in_use) GC_push_all((ptr_t)&(thread_table[i].status),(ptr_t)(&(thread_table[i].status)+1));
-+ }
-+# endif
- }
-
- void GC_stop_world()
-@@ -36,6 +62,10 @@
- DWORD thread_id = GetCurrentThreadId();
- int i;
-
-+#ifdef CYGWIN32
-+ if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
-+#endif
-+
- GC_please_stop = TRUE;
- for (i = 0; i < MAX_THREADS; i++)
- if (thread_table[i].stack != 0
-@@ -53,10 +83,14 @@
- DWORD exitCode;
- if (GetExitCodeThread(thread_table[i].handle,&exitCode) &&
- exitCode != STILL_ACTIVE) {
-- thread_table[i].stack = 0;
-+ thread_table[i].stack = 0; /* prevent stack from being pushed */
-+# ifndef CYGWIN32
-+ /* this breaks pthread_join on Cygwin, which is guaranteed to */
-+ /* only see user pthreads */
- thread_table[i].in_use = FALSE;
- CloseHandle(thread_table[i].handle);
- BZERO((void *)(&thread_table[i].context), sizeof(CONTEXT));
-+# endif
- continue;
- }
- if (SuspendThread(thread_table[i].handle) == (DWORD)-1)
-@@ -335,9 +369,11 @@
- if (*lo < start) *lo = start;
- }
-
--#if !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL))
-+#if !defined(MSWINCE) && defined(GC_DLL)
+ #if !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL))
-HANDLE WINAPI GC_CreateThread(
-+/* We register threads from DllMain */
-+
+GC_API HANDLE GC_CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
-@@ -346,7 +382,10 @@
- lpParameter, dwCreationFlags, lpThreadId);
- }
-
--#else /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */
-+#else /* defined(MSWINCE) || !defined(GC_DLL)) */
-+
-+/* We have no DllMain to take care of new threads. Thus we */
-+/* must properly intercept thread creation. */
-
- typedef struct {
- HANDLE child_ready_h, parent_ready_h;
-@@ -357,7 +396,7 @@
+@@ -357,7 +357,7 @@
DWORD WINAPI thread_start(LPVOID arg);
-HANDLE WINAPI GC_CreateThread(
-+HANDLE GC_CreateThread(
++GC_API HANDLE GC_CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
-@@ -527,22 +566,11 @@
-
- LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
-
--#ifdef GC_DLL
--
--/*
-- * This isn't generally safe, since DllMain is not premptible.
-- * If another thread holds the lock while this runs we're in trouble.
-- * Pontus Rydin suggests wrapping the thread start routine instead.
-+/* threadAttach/threadDetach routines used by both CYGWIN and DLL
-+ * implementation, since both recieve explicit notification on thread
-+ * creation/destruction.
- */
--BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
--{
-- switch (reason) {
-- case DLL_PROCESS_ATTACH:
-- InitializeCriticalSection(&GC_allocate_ml);
-- GC_init(); /* Force initialization before thread attach. */
-- /* fall through */
-- case DLL_THREAD_ATTACH:
-- {
-+static void threadAttach() {
- int i;
- /* It appears to be unsafe to acquire a lock here, since this */
- /* code is apparently not preeemptible on some systems. */
-@@ -554,14 +582,11 @@
- /* The following should be a noop according to the win32 */
- /* documentation. There is empirical evidence that it */
- /* isn't. - HB */
--# ifdef MPROTECT_VDB
-+# if defined(MPROTECT_VDB)
- if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler);
- # endif
--
-- for (i = 0;
- /* cast away volatile qualifier */
-- InterlockedExchange((LPLONG) &thread_table[i].in_use, 1) != 0;
-- i++) {
-+ for (i = 0; InterlockedExchange((LONG*)&thread_table[i].in_use,1) != 0; i++) {
- /* Compare-and-swap would make this cleaner, but that's not */
- /* supported before Windows 98 and NT 4.0. In Windows 2000, */
- /* InterlockedExchange is supposed to be replaced by */
-@@ -571,11 +596,13 @@
- ABORT("too many threads");
- }
- thread_table[i].id = GetCurrentThreadId();
-+# ifdef CYGWIN32
-+ thread_table[i].pthread_id = pthread_self();
-+# endif
- if (!DuplicateHandle(GetCurrentProcess(),
- GetCurrentThread(),
- GetCurrentProcess(),
-- /* cast away volatile qualifier */
-- (HANDLE *) &thread_table[i].handle,
-+ (HANDLE*)&thread_table[i].handle,
- 0,
- 0,
- DUPLICATE_SAME_ACCESS)) {
-@@ -584,33 +611,226 @@
- ABORT("DuplicateHandle failed");
- }
- thread_table[i].stack = GC_get_stack_base();
-+ if (thread_table[i].stack == NULL)
-+ ABORT("Failed to find stack base in threadAttach");
- /* If this thread is being created while we are trying to stop */
- /* the world, wait here. Hopefully this can't happen on any */
- /* systems that don't allow us to block here. */
- while (GC_please_stop) Sleep(20);
-- }
-- break;
-- case DLL_THREAD_DETACH:
-- {
-+}
-+
-+static void threadDetach(DWORD thread_id) {
- int i;
-- DWORD thread_id = GetCurrentThreadId();
-+
- LOCK();
- for (i = 0;
- i < MAX_THREADS &&
-- (thread_table[i].stack == 0 || thread_table[i].id != thread_id);
-+ !thread_table[i].in_use || thread_table[i].id != thread_id;
- i++) {}
-- if (i >= MAX_THREADS) {
-+ if (i >= MAX_THREADS ) {
- WARN("thread %ld not found on detach", (GC_word)thread_id);
-- } else {
-+ }
-+ else {
- thread_table[i].stack = 0;
- thread_table[i].in_use = FALSE;
- CloseHandle(thread_table[i].handle);
- /* cast away volatile qualifier */
-- BZERO((void *) &thread_table[i].context, sizeof(CONTEXT));
-+ BZERO((void *)&thread_table[i].context, sizeof(CONTEXT));
-+ }
-+ UNLOCK();
-+}
-+
-+#ifdef CYGWIN32
-+
-+/* Called by GC_init() - we hold the allocation lock. */
-+void GC_thr_init() {
-+ if (GC_thr_initialized) return;
-+ GC_thr_initialized = TRUE;
-+
-+#if 0
-+ /* this might already be handled in GC_init... */
-+ InitializeCriticalSection(&GC_allocate_ml);
-+#endif
-+
-+ /* Add the initial thread, so we can stop it. */
-+ threadAttach();
-+}
-+
-+struct start_info {
-+ void *(*start_routine)(void *);
-+ void *arg;
-+};
-+
-+int GC_pthread_join(pthread_t pthread_id, void **retval) {
-+ int result;
-+ int i;
-+
-+# if DEBUG_CYGWIN_THREADS
-+ GC_printf3("thread 0x%x(0x%x) is joining thread 0x%x.\n",(int)pthread_self(),
-+ GetCurrentThreadId(), (int)pthread_id);
-+# endif
-+
-+ /* Can't do any table lookups here, because thread being joined
-+ might not have registered itself yet */
-+
-+ result = pthread_join(pthread_id, retval);
-+
-+ LOCK();
-+ for (i = 0; !thread_table[i].in_use || thread_table[i].pthread_id != pthread_id;
-+ i++) {
-+ if (i == MAX_THREADS - 1) {
-+ GC_printf1("Failed to find thread 0x%x in pthread_join()\n", pthread_id);
-+ ABORT("thread not found on detach");
-+ }
- }
- UNLOCK();
-+ threadDetach(thread_table[i].id);
-+
-+# if DEBUG_CYGWIN_THREADS
-+ GC_printf3("thread 0x%x(0x%x) completed join with thread 0x%x.\n",
-+ (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);
-+# endif
-+
-+ return result;
-+}
-+
-+/* Cygwin-pthreads calls CreateThread internally, but it's not
-+ * easily interceptible by us..
-+ * so intercept pthread_create instead
-+ */
-+int
-+GC_pthread_create(pthread_t *new_thread,
-+ const pthread_attr_t *attr,
-+ void *(*start_routine)(void *), void *arg) {
-+ int result;
-+ struct start_info * si;
-+
-+ if (!GC_is_initialized) GC_init();
-+ /* make sure GC is initialized (i.e. main thread is attached) */
-+
-+ /* This is otherwise saved only in an area mmapped by the thread */
-+ /* library, which isn't visible to the collector. */
-+ si = GC_malloc_uncollectable(sizeof(struct start_info));
-+ if (0 == si) return(EAGAIN);
-+
-+ si -> start_routine = start_routine;
-+ si -> arg = arg;
-+
-+# if DEBUG_CYGWIN_THREADS
-+ GC_printf2("About to create a thread from 0x%x(0x%x)\n",(int)pthread_self(),
-+ GetCurrentThreadId);
-+# endif
-+ result = pthread_create(new_thread, attr, GC_start_routine, si);
-+
-+ if (result) { /* failure */
-+ GC_free(si);
-+ }
-+
-+ return(result);
-+}
-+
-+void * GC_start_routine(void * arg)
-+{
-+ struct start_info * si = arg;
-+ void * result;
-+ void *(*start)(void *);
-+ void *start_arg;
-+ pthread_t pthread_id;
-+ int i;
-+
-+# if DEBUG_CYGWIN_THREADS
-+ GC_printf2("thread 0x%x(0x%x) starting...\n",(int)pthread_self(),
-+ GetCurrentThreadId());
-+# endif
-+
-+ /* If a GC occurs before the thread is registered, that GC will */
-+ /* ignore this thread. That's fine, since it will block trying to */
-+ /* acquire the allocation lock, and won't yet hold interesting */
-+ /* pointers. */
-+ LOCK();
-+ /* We register the thread here instead of in the parent, so that */
-+ /* we don't need to hold the allocation lock during pthread_create. */
-+ threadAttach();
-+ UNLOCK();
-+
-+ start = si -> start_routine;
-+ start_arg = si -> arg;
-+ pthread_id = pthread_self();
-+
-+ GC_free(si); /* was allocated uncollectable */
-+
-+ pthread_cleanup_push(GC_thread_exit_proc, pthread_id);
-+ result = (*start)(start_arg);
-+ pthread_cleanup_pop(0);
-+
-+# if DEBUG_CYGWIN_THREADS
-+ GC_printf2("thread 0x%x(0x%x) returned from start routine.\n",
-+ (int)pthread_self(),GetCurrentThreadId());
-+# endif
-+
-+ LOCK();
-+ for (i = 0; thread_table[i].pthread_id != pthread_id; i++) {
-+ if (i == MAX_THREADS - 1)
-+ ABORT("thread not found on exit");
-+ }
-+ thread_table[i].status = result;
-+ UNLOCK();
-+
-+ return(result);
-+}
-+
-+void GC_thread_exit_proc(void *arg)
-+{
-+ pthread_t pthread_id = (pthread_t)arg;
-+ int i;
-+
-+# if DEBUG_CYGWIN_THREADS
-+ GC_printf2("thread 0x%x(0x%x) called pthread_exit().\n",
-+ (int)pthread_self(),GetCurrentThreadId());
-+# endif
-+
-+ LOCK();
-+ for (i = 0; thread_table[i].pthread_id != pthread_id; i++) {
-+ if (i == MAX_THREADS - 1)
-+ ABORT("thread not found on exit");
- }
-+ UNLOCK();
-+
-+#if 0
-+ /* TODO: we need a way to get the exit value after a pthread_exit so we can stash it safely away */
-+ thread_table[i].status = ???
-+#endif
-+}
-+
-+/* nothing required here... */
-+int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) {
-+ return pthread_sigmask(how, set, oset);
-+}
-+int GC_pthread_detach(pthread_t thread) {
-+ return pthread_detach(thread);
-+}
-+#else /* !CYGWIN32 */
-+
-+/*
-+ * We avoid acquiring locks here, since this doesn't seem to be preemptable.
-+ * Pontus Rydin suggests wrapping the thread start routine instead.
-+ */
-+#ifdef GC_DLL
-+BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
-+{
-+ switch (reason) {
-+ case DLL_PROCESS_ATTACH:
-+ InitializeCriticalSection(&GC_allocate_ml);
-+ GC_init(); /* Force initialization before thread attach. */
-+ /* fall through */
-+ case DLL_THREAD_ATTACH:
-+ threadAttach();
-+ break;
-+
-+ case DLL_THREAD_DETACH:
-+ threadDetach(GetCurrentThreadId());
- break;
-+
- case DLL_PROCESS_DETACH:
- {
- int i;
-@@ -636,8 +856,8 @@
- }
- return TRUE;
- }
--
--# endif /* GC_DLL */
-+#endif /* GC_DLL */
-+#endif /* !CYGWIN32 */
-
- # endif /* !MSWINCE */
-