From e8dafc0db4944de1e991eab605a6cc114d6726bd Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 07:37:25 +0000 Subject: [PATCH] 2003/09/26 06:41:51 darcs-hash:20040130073725-2ba56-b105af6100888ba5126b86a817ab42ddc49c90a0.gz --- upstream/gcc-3.3/patches/darwin-gc.patch | 420 +----------------------------- 1 file changed, 6 insertions(+), 414 deletions(-) diff --git a/upstream/gcc-3.3/patches/darwin-gc.patch b/upstream/gcc-3.3/patches/darwin-gc.patch index 26f0942..c462e70 100644 --- a/upstream/gcc-3.3/patches/darwin-gc.patch +++ b/upstream/gcc-3.3/patches/darwin-gc.patch @@ -1368,7 +1368,7 @@ diff -buNr boehm-gc/alpha_mach_dep.s boehm-gc/alpha_mach_dep.s --- 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 @@ -27265,430 +27265,22 @@ diff -buNr boehm-gc/version.h boehm-gc/version.h --- /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 -+#ifdef CYGWIN32 -+# include -+ -+ /* 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 */ - -- 1.7.10.4