From 270c3e2c4c2f314b9ee083350f4670cbac167424 Mon Sep 17 00:00:00 2001
From: Ivan Maidanski <ivmai@mail.ru>
Date: Thu, 17 Dec 2015 00:51:21 +0300
Subject: [PATCH 4/4] Change GC_[un]register_my_thread prototypes in boehm-gc
 (code refactoring to match BDWGC v7 API)

boehm-gc/
    * include/gc.h (GC_DUPLICATE): New public macro.
    (GC_register_my_thread): Change prototype (accept GC_stack_base*).
    (GC_register_my_thread, GC_unregister_my_thread): Change prototype
    (return operation completion status); update comment.
    * pthread_support.c (GC_register_my_thread): Change prototype; change
    "sb" type to pointer; do not call GC_get_stack_base (it is called by
    GC_register_my_thread caller now); return GC_DUPLICATE or GC_SUCCESS.
    (GC_unregister_my_thread): Change prototype; return GC_SUCCESS.
    * win32_threads.c (GC_register_my_thread, GC_unregister_my_thread):
    New function (stub returning GC_DUPLICATE if threads are registered
    implicitly otherwise GC_UNIMPLEMENTED).

libjava/
    * boehm.cc (_Jv_GCAttachThread, _Jv_GCDetachThread): Do not test
    HAVE_PTHREAD_GETATTR_NP and GC_SOLARIS_THREADS macros, test
    GC_PTHREADS macro instead (i.e., invoke GC thread register/unregister
    for all multi-threaded targets); remove the relevant comment.
    (_Jv_GCAttachThread): Declare "sb" local variable; invoke
    GC_get_stack_base (pass obtained stack base to GC_register_my_thread);
    call JvFail with the appropriate message in case of GC_get_stack_base
    or GC_register_my_thread failure (but handle properly the case when
    GC_get_stack_base returns GC_UNIMPLEMENTED but the thread is already
    registered implicitly).
---
 boehm-gc/ChangeLog         | 14 ++++++++++++++
 boehm-gc/include/gc.h      | 15 +++++++--------
 boehm-gc/pthread_support.c | 17 +++++++----------
 boehm-gc/win32_threads.c   | 17 +++++++++++++++++
 libjava/ChangeLog          | 13 +++++++++++++
 libjava/boehm.cc           | 22 ++++++++++++++--------
 6 files changed, 72 insertions(+), 26 deletions(-)

diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index af44b3e..4e0483a 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,17 @@
+2015-12-17  Ivan Maidanski  <ivmai@mail.ru>
+
+	* include/gc.h (GC_DUPLICATE): New public macro.
+	(GC_register_my_thread): Change prototype (accept GC_stack_base*).
+	(GC_register_my_thread, GC_unregister_my_thread): Change prototype
+	(return operation completion status); update comment.
+	* pthread_support.c (GC_register_my_thread): Change prototype; change
+	"sb" type to pointer; do not call GC_get_stack_base (it is called by
+	GC_register_my_thread caller now); return GC_DUPLICATE or GC_SUCCESS.
+	(GC_unregister_my_thread): Change prototype; return GC_SUCCESS.
+	* win32_threads.c (GC_register_my_thread, GC_unregister_my_thread):
+	New function (stub returning GC_DUPLICATE if threads are registered
+	implicitly otherwise GC_UNIMPLEMENTED).
+
 2015-12-10  Ivan Maidanski  <ivmai@mail.ru>
 
 	* AmigaOS.c (GC_get_stack_base): Rename to GC_get_main_stack_base.
diff --git a/boehm-gc/include/gc.h b/boehm-gc/include/gc.h
index 6ba20e6..99adedd 100644
--- a/boehm-gc/include/gc.h
+++ b/boehm-gc/include/gc.h
@@ -935,6 +935,7 @@ struct GC_stack_base {
 };
 
 #define GC_SUCCESS 0
+#define GC_DUPLICATE 1		/* Was already registered.		*/
 #define GC_UNIMPLEMENTED 3	/* Not yet implemented on the platform.	*/
 
 /* Attempt to fill in the GC_stack_base structure with the stack base	*/
@@ -954,15 +955,13 @@ GC_API int GC_get_stack_base GC_PROTO((struct GC_stack_base *));
 /* a thread can allocate garbage collected memory, or assign pointers	*/
 /* to the garbage collected heap.  Once registered, a thread will be	*/
 /* stopped during garbage collections.					*/
-GC_API void GC_register_my_thread GC_PROTO((void));
+/* Returns GC_SUCCESS on success, GC_DUPLICATE if already done. 	*/
+/* On some platforms it returns GC_UNIMPLEMENTED.			*/
+GC_API int GC_register_my_thread GC_PROTO((struct GC_stack_base *));
 
-/* Register the current thread, with the indicated stack base, as	*/
-/* a new thread whose stack(s) should be traced by the GC.  If a 	*/
-/* platform does not implicitly do so, this must be called before a	*/
-/* thread can allocate garbage collected memory, or assign pointers	*/
-/* to the garbage collected heap.  Once registered, a thread will be	*/
-/* stopped during garbage collections.					*/
-GC_API void GC_unregister_my_thread GC_PROTO((void));
+/* Unregister the current thread.					*/
+/* Returns GC_SUCCESS or GC_UNIMPLEMENTED.				*/
+GC_API int GC_unregister_my_thread GC_PROTO((void));
 
 /* This returns a list of objects, linked through their first		*/
 /* word.  Its use can greatly reduce lock contention problems, since	*/
diff --git a/boehm-gc/pthread_support.c b/boehm-gc/pthread_support.c
index e077abb..acb1a55 100644
--- a/boehm-gc/pthread_support.c
+++ b/boehm-gc/pthread_support.c
@@ -1170,15 +1170,10 @@ int GC_get_stack_base(struct GC_stack_base *sb)
 # endif
 }
 
-void GC_register_my_thread()
+int GC_register_my_thread(struct GC_stack_base *sb)
 {
   GC_thread me;
   pthread_t my_pthread;
-# if !defined(GC_DARWIN_THREADS) || defined(IA64)
-    struct GC_stack_base sb;
-    if (GC_get_stack_base(&sb) == GC_UNIMPLEMENTED)
-      ABORT("Can not determine stack base for attached thread");
-# endif
 
   my_pthread = pthread_self();
 #   ifdef DEBUG_THREADS
@@ -1195,7 +1190,7 @@ void GC_register_my_thread()
 #   ifdef DEBUG_THREADS
       GC_printf1("Attempt to re-attach known thread 0x%lx\n", my_pthread);
 #   endif
-      return;
+      return GC_DUPLICATE;
     }
 
   LOCK();
@@ -1208,7 +1203,7 @@ void GC_register_my_thread()
 #ifdef GC_DARWIN_THREADS
     me -> stop_info.mach_thread = mach_thread_self();
 #else
-    me -> stack_end = sb.mem_base;
+    me -> stack_end = sb -> mem_base;
     
 #   ifdef STACK_GROWS_DOWN
       me -> stop_info.stack_ptr = me -> stack_end - 0x10;
@@ -1218,16 +1213,17 @@ void GC_register_my_thread()
 #endif
 
 #   ifdef IA64
-      me -> backing_store_end = sb.reg_base;
+      me -> backing_store_end = sb -> reg_base;
 #   endif /* IA64 */
 
 #   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
         GC_init_thread_local(me);
 #   endif
   UNLOCK();
+  return GC_SUCCESS;
 }
 
-void GC_unregister_my_thread()
+int GC_unregister_my_thread GC_PROTO((void))
 {
   pthread_t my_pthread;
 
@@ -1238,6 +1234,7 @@ void GC_unregister_my_thread()
 #   endif
 
   GC_thread_exit_proc (0);
+  return GC_SUCCESS;
 }
 
 void * GC_start_routine(void * arg)
diff --git a/boehm-gc/win32_threads.c b/boehm-gc/win32_threads.c
index 354e5a7..a32bf8d 100644
--- a/boehm-gc/win32_threads.c
+++ b/boehm-gc/win32_threads.c
@@ -527,6 +527,23 @@ static DWORD WINAPI thread_start(LPVOID arg)
 
 #endif /* !CYGWIN32 */
 
+int GC_register_my_thread(struct GC_stack_base *sb)
+{
+#   if defined(GC_DLL) && !defined(CYGWIN32) && !defined(MSWINCE)
+	/* Registered by DllMain. */
+	return GC_DUPLICATE;
+#   else
+	/* TODO: Implement. */
+	return GC_UNIMPLEMENTED;
+#   endif
+}
+
+int GC_unregister_my_thread GC_PROTO((void))
+{
+    /* TODO: Implement. */
+    return GC_UNIMPLEMENTED;
+}
+
 #ifdef MSWINCE
 
 typedef struct {
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 28adfaf..7f52a3f 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2015-12-17  Ivan Maidanski  <ivmai@mail.ru>
+
+	* boehm.cc (_Jv_GCAttachThread, _Jv_GCDetachThread): Do not test
+	HAVE_PTHREAD_GETATTR_NP and GC_SOLARIS_THREADS macros, test
+	GC_PTHREADS macro instead (i.e., invoke GC thread register/unregister
+	for all multi-threaded targets); remove the relevant comment.
+	(_Jv_GCAttachThread): Declare "sb" local variable; invoke
+	GC_get_stack_base (pass obtained stack base to GC_register_my_thread);
+	call JvFail with the appropriate message in case of GC_get_stack_base
+	or GC_register_my_thread failure (but handle properly the case when
+	GC_get_stack_base returns GC_UNIMPLEMENTED but the thread is already
+	registered implicitly).
+
 2015-12-05  Ivan Maidanski  <ivmai@mail.ru>
 
 	* boehm.cc (GC_enable, GC_disable): Remove prototype (as declared in
diff --git a/libjava/boehm.cc b/libjava/boehm.cc
index 39563f0..4ec91af 100644
--- a/libjava/boehm.cc
+++ b/libjava/boehm.cc
@@ -738,20 +738,26 @@ _Jv_IsThreadSuspended (_Jv_Thread_t *thread)
 void
 _Jv_GCAttachThread ()
 {
-  // The registration interface is only defined on posixy systems and
-  // only actually works if pthread_getattr_np is defined.
-  // FIXME: until gc7 it is simpler to disable this on solaris.
-#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) \
-    && !defined(GC_WIN32_THREADS)
-  GC_register_my_thread ();
+#if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
+  struct GC_stack_base sb;
+
+  if (GC_get_stack_base (&sb) == GC_UNIMPLEMENTED)
+    {
+      // Do not fail in case of implicitly registered threads.
+      sb.mem_base = &sb;
+      if (GC_register_my_thread (&sb) != GC_DUPLICATE)
+        JvFail ("Cannot determine stack base for attached thread");
+      return;
+    }
+  if (GC_register_my_thread (&sb) == GC_UNIMPLEMENTED)
+    JvFail ("Cannot attach thread");
 #endif
 }
 
 void
 _Jv_GCDetachThread ()
 {
-#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) \
-    && !defined(GC_WIN32_THREADS)
+#if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
   GC_unregister_my_thread ();
 #endif
 }
-- 
2.8.2

