There is some code in earlier versions of the GC to do thread registration, but it's very platform specific and thus ugly. I think there wasn't a real facility for Linux.
The tricky part of doing this in general is that the GC needs to know the stack bounds for the newly registered thread. It can find the hot end, but the cold end is often hard. GC7 addresses this by providing two ways to get the cold stack end:
1) A generic mechanism that just takes the address of a local. The collector knows how to implement that everywhere. We just provide a function that calls back one of your functions f with a stack address that's guaranteed to be "below" f. Since this is not the actual base of the stack, the GC ends up tracing pointers only in "new" frames.
2) A separate routine that tries to discover the stack base in a platform dependent way. It may fail. (And currently usually does.) I think that for Linux, pthread_getattr_np works for most threads, though perhaps not the main one. (The thread pointer also probably works in many cases.)
I'm not sure the JNI primitives can be implemented in terms of (1). Certainly if you use CNI that has different semantics, in that the GC doesn't see pointers "below" you on the stack. We may need (2) to work for gcj.
Hans
-----Original Message----- From: Robin Green [mailto:greenrd@greenrd.org] Sent: Thursday, July 28, 2005 1:51 PM To: Anthony Green; Boehm, Hans Cc: tromey@redhat.com; Discussion list for java related Fedora development Subject: RE: [fedora-java] rssowl: libgcj bugs that need fixing for it torun
On Thu, 2005-07-28 at 11:34 -0700, Boehm, Hans wrote:
[I missed the beginning of this thread initially.]
I'm actually trying to work on some of these issues. Some status:
Cool.
Robin - is there a local hack/patch we can apply to swt
and/or rssowl
to work around this problem until a real fix from Hans
migrates into
GCC?
I'm a bit out of my depth here.
Hans wrote: "Gc7 (even the released, but very experimental alpha3 version) has a thread registration interface." This implies that the version in gcc _doesn't_ have a thread registration interface, or anything that could be hacked together into one. Is that surmise correct?
If so, the only other thing I can think of is to spawn a new registered thread instead of calling AttachCurrentThread, and somehow translate all C->Java invocations on the unregistered thread into inter-thread calls onto the new registered thread. In other words, keep all Java code on a separate thread. Yuck.
-- Robin
On Thu, 28 Jul 2005 17:02:35 -0700, Boehm, Hans wrote:
There is some code in earlier versions of the GC to do thread registration, but it's very platform specific and thus ugly. I think there wasn't a real facility for Linux.
The tricky part of doing this in general is that the GC needs to know the stack bounds for the newly registered thread. It can find the hot end, but the cold end is often hard. GC7 addresses this by providing two ways to get the cold stack end:
- A generic mechanism that just takes the address of a local.
The collector knows how to implement that everywhere. We just provide a function that calls back one of your functions f with a stack address that's guaranteed to be "below" f. Since this is not the actual base of the stack, the GC ends up tracing pointers only in "new" frames.
- A separate routine that tries to discover the stack base
in a platform dependent way. It may fail. (And currently usually does.) I think that for Linux, pthread_getattr_np works for most threads, though perhaps not the main one. (The thread pointer also probably works in many cases.)
I'm not sure the JNI primitives can be implemented in terms of (1). Certainly if you use CNI that has different semantics, in that the GC doesn't see pointers "below" you on the stack.
On the contrary, I believe that JNI's AttachCurrentThread can and should be implemented in terms of something like (1). AttachCurrentThread (which allows you to set up a thread to call Java from C) is part of the Invocation API, which does not appear to make any special garbage collection guarantees about references held by the native caller. It is my understanding that any references to Java objects held by the native caller must be explicitly registered as JNI global references, and therefore the stack below the Java part does not have to be - and indeed should *not* be - considered. It should not be considered because this could cause spurious leaks or hide wrong code. (However, it's probably OK to include it if doing a temporary workaround.)
However, I think some setup would need to be done *every* time a call was made from native->Java code at "top level" (i.e. where the native caller was not called by Java code on this thread), because the cold end of the Java part of the stack can be in a different place each time.
I am going to take a different tack and try to implement something like my earlier proposal:
If so, the only other thing I can think of is to spawn a new registered thread instead of calling AttachCurrentThread, and somehow translate all C->Java invocations on the unregistered thread into inter-thread calls onto the new registered thread. In other words, keep all Java code on a separate thread. Yuck.
java-devel@lists.fedoraproject.org