Boehm GC API update backport
Ivan Maidanski <[email protected]> Sat, 16 Jan 2016 15:19:35 +0300
| Newsgroups | gmane.comp.gcc.java.patches |
|---|---|
| Message-ID | <[email protected]> |
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
0001-Change-GC_set_free_space_divisor-prototy pe-in-boehm-.patch
(application/x-patch, 3.6 KB)
From ba81d07864ebaba8a16afdf0e4fd9a6e22d64bee Mon Sep 17 00:00:00 2001 From: Ivan Maidanski <[email protected]> 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 <[email protected]> + + * 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 <[email protected]> * 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 <[email protected]> + + * 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 <[email protected]> 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
0002-Move-extern-C-from-boehm.cc-to-boehm-gc- header-files.patch
(application/x-patch, 8.3 KB)
From 965937dc482db1417ee3e00db6fe911216ab4b4d Mon Sep 17 00:00:00 2001 From: Ivan Maidanski <[email protected]> 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 <[email protected]> + + * 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 <[email protected]> * 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 <[email protected]> + + * 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 <[email protected]> * 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
0004-Change-GC_-un-register_my_thread-prototy pes-in-boehm.patch
(application/x-patch, 9.2 KB)
From 1dd69df15093a51485da80043d243e470d5ab9da Mon Sep 17 00:00:00 2001 From: Ivan Maidanski <[email protected]> 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 <[email protected]> + + * 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 <[email protected]> * 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 <[email protected]> + + * 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 <[email protected]> * 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
0003-Change-GC_get_-thread-main_-stack_base-p rototypes.patch
(application/x-patch, 16 KB)
From 8bc263a68ac3d99c2ce80acc4bdfb9b37d2ecfd5 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski <[email protected]> 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 <[email protected]> + + * 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 <[email protected]> * 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