This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Boehm GC API update backport
- From: Ivan Maidanski <ivmai at mail dot ru>
- To: GCJ-patches <java-patches at gcc dot gnu dot org>
- Date: Sat, 16 Jan 2016 15:19:35 +0300
- Subject: Boehm GC API update backport
- Authentication-results: sourceware.org; auth=none
- Reply-to: Ivan Maidanski <ivmai at mail dot ru>
Hello,
Proposed 4 commits are code refactoring of boehm-gc (and libjava/boehm.cc, accordingly) to match API of recent BDWGC master ( https://github.com/ivmai/bdwgc ). This should simplify optional replacement of internal boehm-gcc with the external one.
All gcj tests pass.
Some of the benefits of using mainline boehm gc:
* has no compiler warning
* more targets supported (e.g. arm64)
* no trouble with back-porting gc patches Similar thing was proposed for the Mono community - https://github.com/mono/mono/pull/2247 (the patches were accepted recently)
References:
[1] The proposed patches in GCC unofficial git mirror fork - https://github.com/ivmai/gcc/tree/match-bdwgc-api
--
Best regards,
Ivan
From ba81d07864ebaba8a16afdf0e4fd9a6e22d64bee Mon Sep 17 00:00:00 2001
From: Ivan Maidanski <ivmai@mail.ru>
Date: Thu, 3 Dec 2015 01:48:30 +0300
Subject: [PATCH 1/4] Change GC_set_free_space_divisor prototype in boehm-gc
(code refactoring to match BDWGC v7 API)
boehm-gc/
* include/gc.h (GC_set_free_space_divisor): Change return type from
word to void.
(GC_get_free_space_divisor): New function.
* misc.c (GC_set_free_space_divisor): Decouple to setter and getter.
libjava/
* boehm.cc (_Jv_SetGCFreeSpaceDivisor): Use GC_get_free_space_divisor
to get old_div (before GC_set_free_space_divisor call).
---
boehm-gc/ChangeLog | 7 +++++++
boehm-gc/include/gc.h | 6 +++---
boehm-gc/misc.c | 11 +++++++----
libjava/ChangeLog | 5 +++++
libjava/boehm.cc | 4 +++-
5 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 365038e..1d86061 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,10 @@
+2015-12-03 Ivan Maidanski <ivmai@mail.ru>
+
+ * include/gc.h (GC_set_free_space_divisor): Change return type from
+ word to void.
+ (GC_get_free_space_divisor): New function.
+ * misc.c (GC_set_free_space_divisor): Decouple to setter and getter.
+
2015-10-09 David Malcolm <dmalcolm@redhat.com>
* testsuite/lib/boehm-gc.exp: Load multiline.exp before
diff --git a/boehm-gc/include/gc.h b/boehm-gc/include/gc.h
index 6b38f2d..d02dab2 100644
--- a/boehm-gc/include/gc.h
+++ b/boehm-gc/include/gc.h
@@ -803,9 +803,9 @@ typedef void (*GC_warn_proc) GC_PROTO((char *msg, GC_word arg));
GC_API GC_warn_proc GC_set_warn_proc GC_PROTO((GC_warn_proc p));
/* Returns old warning procedure. */
-GC_API GC_word GC_set_free_space_divisor GC_PROTO((GC_word value));
- /* Set free_space_divisor. See above for definition. */
- /* Returns old value. */
+GC_API void GC_set_free_space_divisor GC_PROTO((GC_word value));
+GC_API GC_word GC_get_free_space_divisor GC_PROTO((void));
+ /* Set and get free_space_divisor. See above for the definition. */
/* The following is intended to be used by a higher level */
/* (e.g. Java-like) finalization facility. It is expected */
diff --git a/boehm-gc/misc.c b/boehm-gc/misc.c
index 069c7d5..c1faed0 100644
--- a/boehm-gc/misc.c
+++ b/boehm-gc/misc.c
@@ -1048,15 +1048,18 @@ GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
}
# if defined(__STDC__) || defined(__cplusplus)
- GC_word GC_set_free_space_divisor (GC_word value)
+ void GC_set_free_space_divisor (GC_word value)
# else
- GC_word GC_set_free_space_divisor (value)
+ void GC_set_free_space_divisor (value)
GC_word value;
# endif
{
- GC_word old = GC_free_space_divisor;
GC_free_space_divisor = value;
- return old;
+}
+
+GC_word GC_get_free_space_divisor GC_PROTO((void))
+{
+ return GC_free_space_divisor;
}
#ifndef PCR
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 0d75195..954b1a1 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-03 Ivan Maidanski <ivmai@mail.ru>
+
+ * boehm.cc (_Jv_SetGCFreeSpaceDivisor): Use GC_get_free_space_divisor
+ to get old_div (before GC_set_free_space_divisor call).
+
2015-07-24 Michael Darling <darlingm@gmail.com>
PR other/66259
diff --git a/libjava/boehm.cc b/libjava/boehm.cc
index 043fd00..34a6ead 100644
--- a/libjava/boehm.cc
+++ b/libjava/boehm.cc
@@ -468,7 +468,9 @@ _Jv_GCSetMaximumHeapSize (size_t size)
int
_Jv_SetGCFreeSpaceDivisor (int div)
{
- return (int)GC_set_free_space_divisor ((GC_word)div);
+ int old_div = (int)GC_get_free_space_divisor ();
+ GC_set_free_space_divisor ((GC_word)div);
+ return old_div;
}
void
--
2.1.4
From 965937dc482db1417ee3e00db6fe911216ab4b4d Mon Sep 17 00:00:00 2001
From: Ivan Maidanski <ivmai@mail.ru>
Date: Sat, 5 Dec 2015 19:28:20 +0300
Subject: [PATCH 2/4] Move 'extern C' from boehm.cc to boehm-gc header files;
avoid explicit include gc_local_alloc.h from boehm.cc; remove
GC_enable/disable duplicate prototyping (code refactoring to match BDWGC v7
API)
boehm-gc/
* include/gc.h (GC_suspend_thread, GC_resume_thread,
GC_is_thread_suspended): Move inside 'extern "C"' block.
[GC_REDIRECT_TO_LOCAL]: Include gc_local_alloc.h outside 'extern "C"'
block; do not include gc_local_alloc.h if gc.h is included from
gc_gcj.h (so that GC_[LOCAL_]GCJ_MALLOC to be defined after other GCJ
symbols).
* include/gc_gcj.h [__cplusplus]: Wrap all declarations into
'extern "C"' block.
* include/gc_local_alloc.h [__cplusplus]: Likewise.
* include/javaxfc.h [__cplusplus]: Likewise.
* include/gc_gcj.h [GC_REDIRECT_TO_LOCAL]: Include gc_local_alloc.h.
libjava/
* boehm.cc (GC_enable, GC_disable): Remove prototype (as declared in
boehm-gc/include/gc.h).
[THREAD_LOCAL_ALLOC] (GC_REDIRECT_TO_LOCAL): Define before include
gc_gcj.h file.
* boehm.cc: Remove 'extern "C"' for included boehm-gc/include header
files (they are properly decorated inside now); remove include
"gc_local_alloc.h" (as it is implicitly included now by
boehm-gc/include/gc_gcj.h); include "gc_gcj.h" before any other
boehm-gc header file (to let GC_GCJ_MALLOC be properly redefined to
a thread-local allocator in boehm-gc/include/gc_local_alloc.h).
---
boehm-gc/ChangeLog | 14 ++++++++++++++
boehm-gc/include/gc.h | 22 ++++++++++++++--------
boehm-gc/include/gc_gcj.h | 12 ++++++++++++
boehm-gc/include/gc_local_alloc.h | 8 ++++++++
boehm-gc/include/gc_mark.h | 9 ++++++++-
boehm-gc/include/javaxfc.h | 8 +++++++-
libjava/ChangeLog | 13 +++++++++++++
libjava/boehm.cc | 14 +++-----------
8 files changed, 79 insertions(+), 21 deletions(-)
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 1d86061..9988605 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,17 @@
+2015-12-05 Ivan Maidanski <ivmai@mail.ru>
+
+ * include/gc.h (GC_suspend_thread, GC_resume_thread,
+ GC_is_thread_suspended): Move inside 'extern "C"' block.
+ [GC_REDIRECT_TO_LOCAL]: Include gc_local_alloc.h outside 'extern "C"'
+ block; do not include gc_local_alloc.h if gc.h is included from
+ gc_gcj.h (so that GC_[LOCAL_]GCJ_MALLOC to be defined after other GCJ
+ symbols).
+ * include/gc_gcj.h [__cplusplus]: Wrap all declarations into
+ 'extern "C"' block.
+ * include/gc_local_alloc.h [__cplusplus]: Likewise.
+ * include/javaxfc.h [__cplusplus]: Likewise.
+ * include/gc_gcj.h [GC_REDIRECT_TO_LOCAL]: Include gc_local_alloc.h.
+
2015-12-03 Ivan Maidanski <ivmai@mail.ru>
* include/gc.h (GC_set_free_space_divisor): Change return type from
diff --git a/boehm-gc/include/gc.h b/boehm-gc/include/gc.h
index d02dab2..f193065 100644
--- a/boehm-gc/include/gc.h
+++ b/boehm-gc/include/gc.h
@@ -1061,14 +1061,6 @@ GC_API void GC_register_has_static_roots_callback
# include "gc_amiga_redirects.h"
#endif
-#if defined(GC_REDIRECT_TO_LOCAL) && !defined(GC_LOCAL_ALLOC_H)
-# include "gc_local_alloc.h"
-#endif
-
-#ifdef __cplusplus
- } /* end of extern "C" */
-#endif
-
/* External thread suspension support. These functions do not implement
* suspension counts or any other higher-level abstraction. Threads which
* have been suspended numerous times will resume with the very first call
@@ -1080,4 +1072,18 @@ GC_API void GC_suspend_thread GC_PROTO((pthread_t));
GC_API void GC_resume_thread GC_PROTO((pthread_t));
GC_API int GC_is_thread_suspended GC_PROTO((pthread_t));
#endif
+
+#ifdef __cplusplus
+ } /* end of extern "C" */
+#endif
+
+#if defined(GC_REDIRECT_TO_LOCAL) && !defined(GC_LOCAL_ALLOC_H) \
+ && !defined(GC_GCJ_H)
+ /* In case of gc.h is included from gc_gcj.h file, gc_local_alloc.h */
+ /* should be included at the end of gc_gcj.h instead of gc.h to have */
+ /* all GCJ symbols defined before some of them are redefined to */
+ /* their thread-local counterparts. */
+# include "gc_local_alloc.h"
+#endif
+
#endif /* _GC_H */
diff --git a/boehm-gc/include/gc_gcj.h b/boehm-gc/include/gc_gcj.h
index 5e79e27..b771734 100644
--- a/boehm-gc/include/gc_gcj.h
+++ b/boehm-gc/include/gc_gcj.h
@@ -44,6 +44,10 @@
# include "gc.h"
#endif
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
/* The following allocators signal an out of memory condition with */
/* return GC_oom_fn(bytes); */
@@ -110,4 +114,12 @@ extern int GC_gcj_debug_kind;
GC_gcj_malloc_ignore_off_page(s,d)
# endif
+#ifdef __cplusplus
+ } /* end of extern "C" */
+#endif
+
+#if defined(GC_REDIRECT_TO_LOCAL)
+# include "gc_local_alloc.h"
+#endif
+
#endif /* GC_GCJ_H */
diff --git a/boehm-gc/include/gc_local_alloc.h b/boehm-gc/include/gc_local_alloc.h
index 1874c7b..e4fe205 100644
--- a/boehm-gc/include/gc_local_alloc.h
+++ b/boehm-gc/include/gc_local_alloc.h
@@ -49,6 +49,10 @@
# include "gc_gcj.h"
#endif
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
/* We assume ANSI C for this interface. */
GC_PTR GC_local_malloc(size_t bytes);
@@ -86,4 +90,8 @@ GC_PTR GC_local_malloc_atomic(size_t bytes);
# endif
# endif
+#ifdef __cplusplus
+ } /* end of extern "C" */
+#endif
+
#endif /* GC_LOCAL_ALLOC_H */
diff --git a/boehm-gc/include/gc_mark.h b/boehm-gc/include/gc_mark.h
index 953bb74..7c92946 100644
--- a/boehm-gc/include/gc_mark.h
+++ b/boehm-gc/include/gc_mark.h
@@ -29,6 +29,10 @@
# include "gc.h"
# endif
+# ifdef __cplusplus
+ extern "C" {
+# endif
+
/* A client supplied mark procedure. Returns new mark stack pointer. */
/* Primary effect should be to push new entries on the mark stack. */
/* Mark stack pointer values are passed and returned explicitly. */
@@ -199,5 +203,8 @@ void GC_register_describe_type_fn GC_PROTO((int kind, GC_describe_type_fn knd));
/* to be used when printing objects */
/* of a particular kind. */
-#endif /* GC_MARK_H */
+# ifdef __cplusplus
+ } /* end of extern "C" */
+# endif
+#endif /* GC_MARK_H */
diff --git a/boehm-gc/include/javaxfc.h b/boehm-gc/include/javaxfc.h
index 23e0100..669ba64 100644
--- a/boehm-gc/include/javaxfc.h
+++ b/boehm-gc/include/javaxfc.h
@@ -2,6 +2,10 @@
# include "gc.h"
# endif
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
/*
* Invoke all remaining finalizers that haven't yet been run.
* This is needed for strict compliance with the Java standard,
@@ -18,4 +22,6 @@
*/
void GC_finalize_all();
-
+#ifdef __cplusplus
+ } /* end of extern "C" */
+#endif
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 954b1a1..d581c8f 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2015-12-05 Ivan Maidanski <ivmai@mail.ru>
+
+ * boehm.cc (GC_enable, GC_disable): Remove prototype (as declared in
+ boehm-gc/include/gc.h).
+ [THREAD_LOCAL_ALLOC] (GC_REDIRECT_TO_LOCAL): Define before include
+ gc_gcj.h file.
+ * boehm.cc: Remove 'extern "C"' for included boehm-gc/include header
+ files (they are properly decorated inside now); remove include
+ "gc_local_alloc.h" (as it is implicitly included now by
+ boehm-gc/include/gc_gcj.h); include "gc_gcj.h" before any other
+ boehm-gc header file (to let GC_GCJ_MALLOC be properly redefined to
+ a thread-local allocator in boehm-gc/include/gc_local_alloc.h).
+
2015-12-03 Ivan Maidanski <ivmai@mail.ru>
* boehm.cc (_Jv_SetGCFreeSpaceDivisor): Use GC_get_free_space_divisor
diff --git a/libjava/boehm.cc b/libjava/boehm.cc
index 34a6ead..39563f0 100644
--- a/libjava/boehm.cc
+++ b/libjava/boehm.cc
@@ -38,8 +38,6 @@ details. */
#include <dlfcn.h>
#endif
-extern "C"
-{
#include <gc_config.h>
// Set GC_DEBUG before including gc.h!
@@ -47,19 +45,13 @@ extern "C"
# define GC_DEBUG
#endif
-#include <gc_mark.h>
-#include <gc_gcj.h>
-#include <javaxfc.h> // GC_finalize_all declaration.
-
#ifdef THREAD_LOCAL_ALLOC
# define GC_REDIRECT_TO_LOCAL
-# include <gc_local_alloc.h>
#endif
+#include <gc_gcj.h> // includes gc.h and gc_local_alloc.h
- // From boehm's misc.c
- void GC_enable();
- void GC_disable();
-};
+#include <gc_mark.h>
+#include <javaxfc.h> // GC_finalize_all declaration.
#define MAYBE_MARK(Obj, Top, Limit, Source) \
Top=GC_MARK_AND_PUSH((GC_PTR) Obj, Top, Limit, (GC_PTR *) Source)
--
2.1.4
From 1dd69df15093a51485da80043d243e470d5ab9da 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 35bd442..4253b94 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 d581c8f..5da8df1 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.1.4
From 8bc263a68ac3d99c2ce80acc4bdfb9b37d2ecfd5 Mon Sep 17 00:00:00 2001
From: Ivan Maidanski <ivmai@mail.ru>
Date: Thu, 10 Dec 2015 21:46:54 +0300
Subject: [PATCH 3/4] Change GC_get_[thread/main_]stack_base prototypes (code
refactoring to match BDWGC v7 API)
GC_get_stack_base renamed to GC_get_main_stack_base;
ptr_t GC_get_thread_stack_base() public prototype changed to
int GC_get_stack_base(struct GC_stack_base*);
GC_get_stack_base now defined for all targets (but returns
GC_UNIMPLEMENTED if no implementation for the target).
boehm-gc/
* AmigaOS.c (GC_get_stack_base): Rename to GC_get_main_stack_base.
* include/private/gc_priv.h (GC_get_stack_base): Likewise.
* include/gc.h (struct GC_stack_base): New public type.
(GC_SUCCESS, GC_UNIMPLEMENTED): New public macro.
(GC_get_thread_stack_base): Replace with
int GC_get_stack_base(struct GC_stack_base*); declare even in
a single-threaded case; refine comment.
* misc.c (GC_init_inner): Rename GC_get_stack_base to
GC_get_main_stack_base.
(GC_init_inner): Replace GC_get_thread_stack_base to
GC_get_stack_base.
* win32_threads.c [CYGWIN32] (GC_get_thread_stack_base): Likewise.
* os_dep.c [MSWIN32 || MSWINCE || BEOS || OS2] (GC_get_stack_base):
Accommodate to GC_get_stack_base prototype change.
* win32_threads.c (GC_new_thread): Likewise.
* os_dep.c (HAVE_GET_STACK_BASE): Define in every case when
target-specific GC_get_stack_base is defined (including for cases
when GC_get_stack_base is pthread_support.c or win32_threads.c).
(GC_get_stack_base): Rename to GC_get_main_stack_base (except for
Win32, WinCE, BeOS and OS/2).
(GET_MAIN_STACKBASE_SPECIAL): Define in every case when
target-specific GC_get_main_stack_base is defined.
[!HAVE_GET_STACK_BASE] (GC_get_stack_base): Define with the default
implementation.
[!GET_MAIN_STACKBASE_SPECIAL] (GC_get_main_stack_base): Likewise.
* pthread_support.c (GC_get_thread_stack_base): Replace to
GC_get_stack_base; set reg_base for IA64.
[!GC_DARWIN_THREADS] (GC_register_my_thread): Call GC_get_stack_base
instead of GC_get_thread_stack_base and GC_save_regs_in_stack.
---
boehm-gc/AmigaOS.c | 4 +--
boehm-gc/ChangeLog | 32 +++++++++++++++++++
boehm-gc/include/gc.h | 20 ++++++++++--
boehm-gc/include/private/gc_priv.h | 2 +-
boehm-gc/misc.c | 8 +++--
boehm-gc/os_dep.c | 63 ++++++++++++++++++++++++++++++++------
boehm-gc/pthread_support.c | 30 ++++++++++--------
boehm-gc/win32_threads.c | 14 +++++----
8 files changed, 139 insertions(+), 34 deletions(-)
diff --git a/boehm-gc/AmigaOS.c b/boehm-gc/AmigaOS.c
index f4024a7..b76f446 100644
--- a/boehm-gc/AmigaOS.c
+++ b/boehm-gc/AmigaOS.c
@@ -40,7 +40,7 @@
Find the base of the stack.
******************************************************************/
-ptr_t GC_get_stack_base()
+ptr_t GC_get_main_stack_base()
{
struct Process *proc = (struct Process*)SysBase->ThisTask;
@@ -58,7 +58,7 @@ ptr_t GC_get_stack_base()
}
#if 0 /* old version */
-ptr_t GC_get_stack_base()
+ptr_t GC_get_main_stack_base()
{
extern struct WBStartup *_WBenchMsg;
extern long __base;
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 9988605..35bd442 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,3 +1,35 @@
+2015-12-10 Ivan Maidanski <ivmai@mail.ru>
+
+ * AmigaOS.c (GC_get_stack_base): Rename to GC_get_main_stack_base.
+ * include/private/gc_priv.h (GC_get_stack_base): Likewise.
+ * include/gc.h (struct GC_stack_base): New public type.
+ (GC_SUCCESS, GC_UNIMPLEMENTED): New public macro.
+ (GC_get_thread_stack_base): Replace with
+ int GC_get_stack_base(struct GC_stack_base*); declare even in
+ a single-threaded case; refine comment.
+ * misc.c (GC_init_inner): Rename GC_get_stack_base to
+ GC_get_main_stack_base.
+ (GC_init_inner): Replace GC_get_thread_stack_base to
+ GC_get_stack_base.
+ * win32_threads.c [CYGWIN32] (GC_get_thread_stack_base): Likewise.
+ * os_dep.c [MSWIN32 || MSWINCE || BEOS || OS2] (GC_get_stack_base):
+ Accommodate to GC_get_stack_base prototype change.
+ * win32_threads.c (GC_new_thread): Likewise.
+ * os_dep.c (HAVE_GET_STACK_BASE): Define in every case when
+ target-specific GC_get_stack_base is defined (including for cases
+ when GC_get_stack_base is pthread_support.c or win32_threads.c).
+ (GC_get_stack_base): Rename to GC_get_main_stack_base (except for
+ Win32, WinCE, BeOS and OS/2).
+ (GET_MAIN_STACKBASE_SPECIAL): Define in every case when
+ target-specific GC_get_main_stack_base is defined.
+ [!HAVE_GET_STACK_BASE] (GC_get_stack_base): Define with the default
+ implementation.
+ [!GET_MAIN_STACKBASE_SPECIAL] (GC_get_main_stack_base): Likewise.
+ * pthread_support.c (GC_get_thread_stack_base): Replace to
+ GC_get_stack_base; set reg_base for IA64.
+ [!GC_DARWIN_THREADS] (GC_register_my_thread): Call GC_get_stack_base
+ instead of GC_get_thread_stack_base and GC_save_regs_in_stack.
+
2015-12-05 Ivan Maidanski <ivmai@mail.ru>
* include/gc.h (GC_suspend_thread, GC_resume_thread,
diff --git a/boehm-gc/include/gc.h b/boehm-gc/include/gc.h
index f193065..6ba20e6 100644
--- a/boehm-gc/include/gc.h
+++ b/boehm-gc/include/gc.h
@@ -926,6 +926,24 @@ GC_API void (*GC_is_visible_print_proc)
# include "gc_pthread_redirects.h"
#endif
+/* Structure representing the base of a thread stack. */
+struct GC_stack_base {
+ void * mem_base; /* Base of memory stack. */
+# if defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
+ void * reg_base; /* Base of separate register stack. */
+# endif
+};
+
+#define GC_SUCCESS 0
+#define GC_UNIMPLEMENTED 3 /* Not yet implemented on the platform. */
+
+/* Attempt to fill in the GC_stack_base structure with the stack base */
+/* for this thread. This appears to be required to implement anything */
+/* like the JNI AttachCurrentThread in an environment in which new */
+/* threads are not automatically registered with the collector. */
+/* Returns GC_SUCCESS or GC_UNIMPLEMENTED. */
+GC_API int GC_get_stack_base GC_PROTO((struct GC_stack_base *));
+
# if defined(PCR) || defined(GC_SOLARIS_THREADS) || \
defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
/* Any flavor of threads except SRC_M3. */
@@ -946,8 +964,6 @@ GC_API void GC_register_my_thread GC_PROTO((void));
/* stopped during garbage collections. */
GC_API void GC_unregister_my_thread GC_PROTO((void));
-GC_API GC_PTR GC_get_thread_stack_base GC_PROTO((void));
-
/* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */
/* the allocation lock can be acquired and released many fewer times. */
diff --git a/boehm-gc/include/private/gc_priv.h b/boehm-gc/include/private/gc_priv.h
index 4dbfa7d..a6fda46 100644
--- a/boehm-gc/include/private/gc_priv.h
+++ b/boehm-gc/include/private/gc_priv.h
@@ -1493,7 +1493,7 @@ GC_bool GC_register_main_static_data GC_PROTO((void));
/* dynamic library registration. */
/* Machine dependent startup routines */
-ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */
+ptr_t GC_get_main_stack_base GC_PROTO((void)); /* Cold end of stack */
#ifdef IA64
ptr_t GC_get_register_stack_base GC_PROTO((void));
/* Cold end of register stack. */
diff --git a/boehm-gc/misc.c b/boehm-gc/misc.c
index c1faed0..0f4edff 100644
--- a/boehm-gc/misc.c
+++ b/boehm-gc/misc.c
@@ -677,10 +677,14 @@ void GC_init_inner()
# if defined(GC_PTHREADS) && ! defined(GC_SOLARIS_THREADS)
/* Use thread_stack_base if available, as GC could be initialized from
a thread that is not the "main" thread. */
- GC_stackbottom = GC_get_thread_stack_base();
+ struct GC_stack_base sb;
+ sb.mem_base = NULL;
+ (void)GC_get_stack_base(&sb);
+ /* In case of failure, mem_base remains NULL. */
+ GC_stackbottom = sb.mem_base;
# endif
if (GC_stackbottom == 0)
- GC_stackbottom = GC_get_stack_base();
+ GC_stackbottom = GC_get_main_stack_base();
# if (defined(LINUX) || defined(HPUX)) && defined(IA64)
GC_register_stackbottom = GC_get_register_stack_base();
# endif
diff --git a/boehm-gc/os_dep.c b/boehm-gc/os_dep.c
index 60cbc2b..f8da082 100644
--- a/boehm-gc/os_dep.c
+++ b/boehm-gc/os_dep.c
@@ -639,42 +639,53 @@ word GC_get_writable_length(ptr_t p, ptr_t *base)
return(buf.RegionSize);
}
-ptr_t GC_get_stack_base()
+int GC_get_stack_base(struct GC_stack_base *sb)
{
int dummy;
ptr_t sp = (ptr_t)(&dummy);
ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_page_size - 1));
word size = GC_get_writable_length(trunc_sp, 0);
- return(trunc_sp + size);
+ sb -> mem_base = trunc_sp + size;
+ return GC_SUCCESS;
}
+# define HAVE_GET_STACK_BASE
+# elif defined(CYGWIN32) && defined(GC_WIN32_THREADS)
+
+ /* GC_get_stack_base() is defined in win32_threads.c. */
+# define HAVE_GET_STACK_BASE
# endif /* MS Windows */
# ifdef BEOS
# include <kernel/OS.h>
-ptr_t GC_get_stack_base(){
+int GC_get_stack_base(struct GC_stack_base *sb)
+{
thread_info th;
get_thread_info(find_thread(NULL),&th);
- return th.stack_end;
+ sb -> mem_base = th.stack_end;
+ return GC_SUCCESS;
}
+# define HAVE_GET_STACK_BASE
# endif /* BEOS */
# ifdef OS2
-ptr_t GC_get_stack_base()
+int GC_get_stack_base(struct GC_stack_base *sb)
{
PTIB ptib;
PPIB ppib;
if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
GC_err_printf0("DosGetInfoBlocks failed\n");
- ABORT("DosGetInfoBlocks failed\n");
+ return GC_UNIMPLEMENTED;
}
- return((ptr_t)(ptib -> tib_pstacklimit));
+ sb -> mem_base = (void *)(ptib -> tib_pstacklimit);
+ return GC_SUCCESS;
}
+# define HAVE_GET_STACK_BASE
# endif /* OS2 */
@@ -682,6 +693,7 @@ ptr_t GC_get_stack_base()
# define GC_AMIGA_SB
# include "AmigaOS.c"
# undef GC_AMIGA_SB
+# define GET_MAIN_STACKBASE_SPECIAL
# endif /* AMIGA */
# if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
@@ -819,10 +831,11 @@ ptr_t GC_get_stack_base()
# endif
#if defined(ECOS) || defined(NOSYS)
- ptr_t GC_get_stack_base()
+ ptr_t GC_get_main_stack_base GC_PROTO((void))
{
return STACKBOTTOM;
}
+# define GET_MAIN_STACKBASE_SPECIAL
#endif
#ifdef HPUX_STACKBOTTOM
@@ -1059,7 +1072,7 @@ ptr_t GC_get_stack_base()
#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
&& !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS)
-ptr_t GC_get_stack_base()
+ptr_t GC_get_main_stack_base GC_PROTO((void))
{
# if defined(HEURISTIC1) || defined(HEURISTIC2) || \
defined(LINUX_STACKBOTTOM) || defined(FREEBSD_STACKBOTTOM) || \
@@ -1118,9 +1131,41 @@ ptr_t GC_get_stack_base()
return(result);
# endif /* STACKBOTTOM */
}
+# define GET_MAIN_STACKBASE_SPECIAL
# endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */
+#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
+ && !defined(GC_WIN32_THREADS)
+ /* GC_get_stack_base() is defined in pthread_support.c. */
+# define HAVE_GET_STACK_BASE
+#endif
+
+#ifndef HAVE_GET_STACK_BASE
+ int GC_get_stack_base(struct GC_stack_base *sb)
+ {
+# if defined(GET_MAIN_STACKBASE_SPECIAL) && !defined(THREADS) \
+ && !defined(IA64)
+ sb->mem_base = GC_get_main_stack_base();
+ return GC_SUCCESS;
+# else
+ return GC_UNIMPLEMENTED;
+# endif
+ }
+#endif /* !HAVE_GET_STACK_BASE */
+
+#ifndef GET_MAIN_STACKBASE_SPECIAL
+ /* This is always called from the main thread. Default implementation. */
+ ptr_t GC_get_main_stack_base GC_PROTO((void))
+ {
+ struct GC_stack_base sb;
+
+ if (GC_get_stack_base(&sb) != GC_SUCCESS)
+ ABORT("GC_get_stack_base failed");
+ return (ptr_t)sb.mem_base;
+ }
+#endif /* !GET_MAIN_STACKBASE_SPECIAL */
+
/*
* Register static data segment(s) as roots.
* If more data segments are added later then they need to be registered
diff --git a/boehm-gc/pthread_support.c b/boehm-gc/pthread_support.c
index 6d8f020..e077abb 100644
--- a/boehm-gc/pthread_support.c
+++ b/boehm-gc/pthread_support.c
@@ -1127,7 +1127,7 @@ WRAP_FUNC(pthread_detach)(pthread_t thread)
GC_bool GC_in_thread_creation = FALSE;
-GC_PTR GC_get_thread_stack_base()
+int GC_get_stack_base(struct GC_stack_base *sb)
{
# ifdef HAVE_PTHREAD_GETATTR_NP
pthread_t my_pthread;
@@ -1141,7 +1141,7 @@ GC_PTR GC_get_thread_stack_base()
# ifdef DEBUG_THREADS
GC_printf0("Can not determine stack base for attached thread");
# endif
- return 0;
+ return GC_UNIMPLEMENTED;
}
pthread_attr_getstack (&attr, (void **) &stack_addr, &stack_size);
pthread_attr_destroy (&attr);
@@ -1151,16 +1151,22 @@ GC_PTR GC_get_thread_stack_base()
# endif
# ifdef STACK_GROWS_DOWN
- return stack_addr + stack_size;
+ sb -> mem_base = stack_addr + stack_size;
# else
- return stack_addr;
+ sb -> mem_base = stack_addr;
# endif
+# ifdef IA64
+ sb -> reg_base = (void*)(GC_save_regs_in_stack() & ~(GC_page_size - 1));
+ /* This is not 100% convincing. We should also read this */
+ /* from /proc, but the hook to do so isn't there yet. */
+# endif
+ return GC_SUCCESS;
# else
# ifdef DEBUG_THREADS
GC_printf0("Can not determine stack base for attached thread");
# endif
- return 0;
+ return GC_UNIMPLEMENTED;
# endif
}
@@ -1168,6 +1174,11 @@ void GC_register_my_thread()
{
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
@@ -1197,9 +1208,7 @@ void GC_register_my_thread()
#ifdef GC_DARWIN_THREADS
me -> stop_info.mach_thread = mach_thread_self();
#else
- me -> stack_end = GC_get_thread_stack_base();
- if (me -> stack_end == 0)
- GC_abort("Can not determine stack base for attached thread");
+ me -> stack_end = sb.mem_base;
# ifdef STACK_GROWS_DOWN
me -> stop_info.stack_ptr = me -> stack_end - 0x10;
@@ -1209,10 +1218,7 @@ void GC_register_my_thread()
#endif
# ifdef IA64
- me -> backing_store_end = (ptr_t)
- (GC_save_regs_in_stack() & ~(GC_page_size - 1));
- /* This is also < 100% convincing. We should also read this */
- /* from /proc, but the hook to do so isn't there yet. */
+ me -> backing_store_end = sb.reg_base;
# endif /* IA64 */
# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
diff --git a/boehm-gc/win32_threads.c b/boehm-gc/win32_threads.c
index 2de1c69..354e5a7 100644
--- a/boehm-gc/win32_threads.c
+++ b/boehm-gc/win32_threads.c
@@ -80,6 +80,7 @@ extern LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
*/
static GC_thread GC_new_thread(void) {
int i;
+ struct GC_stack_base sb;
/* It appears to be unsafe to acquire a lock here, since this */
/* code is apparently not preeemptible on some systems. */
/* (This is based on complaints, not on Microsoft's official */
@@ -131,11 +132,11 @@ static GC_thread GC_new_thread(void) {
GC_printf1("Last error code: %lx\n", last_error);
ABORT("DuplicateHandle failed");
}
- thread_table[i].stack_base = GC_get_stack_base();
+ if (GC_get_stack_base(&sb) == GC_UNIMPLEMENTED)
+ ABORT("Failed to find stack base in GC_new_thread");
+ thread_table[i].stack_base = sb.mem_base;
/* Up until this point, GC_push_all_stacks considers this thread */
/* invalid. */
- if (thread_table[i].stack_base == NULL)
- ABORT("Failed to find stack base in GC_new_thread");
/* Up until this point, this entry is viewed as reserved but invalid */
/* by GC_delete_thread. */
thread_table[i].id = GetCurrentThreadId();
@@ -757,14 +758,15 @@ int GC_pthread_detach(pthread_t thread)
return result;
}
-GC_PTR GC_get_thread_stack_base()
+int GC_get_stack_base(struct GC_stack_base *sb)
{
#ifdef __x86_64__
- return ((NT_TIB*)NtCurrentTeb())->StackBase;
+ sb -> mem_base = ((NT_TIB*)NtCurrentTeb())->StackBase;
#else
extern GC_PTR _tlsbase __asm__ ("%fs:4");
- return _tlsbase;
+ sb -> mem_base = _tlsbase;
#endif
+ return GC_SUCCESS;
}
#else /* !CYGWIN32 */
--
2.1.4