threads on kaffe rough draft
dlambright at ast.osf.org
Tue Apr 21 10:18:05 PDT 1998
In message <353CA69C.8AE2DF68 at himh1.hi.bosch.de>"Michael Schr der" writes
>What must I do to get Kaffe running with native-threads ?
>I am using Kaffe0.9.2 on some kind of real-time OS.
>Has anyone done something like that and can tell me how ?
Below is a draft of our solutions to getting Kaffe to work with pthreads.
This is about 4 months old, and doesn't contain some recent efficiency
work we've done. Comments on technical points are welcome.
Hope this helps some.
We have implemented Mach threads (cthreads) and pthreads (version
1003.1c-1995) on Kaffe v0.9.2. The platform was the osf operating system
running over the Mach MK microkernel on an i386. The pthreads
modifications to Kaffe should be portable to other platforms. We have
tried it on the test cases which come with Kaffe and an in-house
testsuite. We hope to make our patches to kaffe publically available soon.
When using cthreads or pthreads, the host OS does context switches
transparently to user-level tasks, i.e. Kaffe doesn't know which thread
is currently running. It needs this information to maintain
thread-specific context (e.g. priorities, stacksize, stackbase, TOS,
etc.). Our solution was to modify "currentThread" to be a macro that calls
cthread/pthread_self(). The value returned maps to a slot pointing to the
thread specific context.
Kaffe's walkThread() function searches the stacks of threads to mark live
blocks of memory durring garbage collection. But because of the
transparency of context switches, the position of the stack pointer was no
longer known. walkThread() needs to know (1) the stack base and (2) the
top of the stack.
We find (1) simply by taking the address of an automatic variable in
Kaffe's entry-point procedure for threads, createInititalThread() (also
have to do this in initThreads() for the startup thread.)
We find (2) by tracking the stack pointer changes when you enter or exit a
method. Kaffe's x86 implementation is written such that the frame is a
constant size (i.e. is not calculated for each method). Whenever you
enter a method this counter is incremented by the size of the frame, and
decremented when you exit the method.
Note that theoretically, the garbage collector could interrupt a thread
*in the middle of updating the counter*. Were this to happen, walkThread()
may receive invalid information, and then free memory that should not be
freed (say another thread is scheduled and calls gc_malloc(), which in
turn calls invokeGC().) We currently handle that problem by locking a
mutex associated with the counter, an expensive proposition for every
procedure call and exit. Also, we currently do not update the counter when
control passes to native code.
The prologue routine was also a convenient place to check for stack
overflow. If there is a stack overflow in cthreads/pthreads, a java
exception will not be thrown. So, we do this by hand in the prologue.
Implementation of Java thread package:
Implementation of the threadKill() method is problematic (what if the
target thread holds a mutex internal to the JVM)? Although pthreads does
have methods for killing other threads (e.g. pthread_cancel), our
pthreads implementation doesn't support those methods. cthreads doesn't
have this either. So, we did not support the THREAD_STOP macro called from
thread.c:stopThread(). We may put this in eventually.
We created the files thread-internal.[ch] and locks-native.[ch] to replace
the corresponding thread-internal and lock-internal code. We had to also
change thread.c to initialize thread context, and to include the
*-internal.* files. Two macros in jit-def were changed. The rest of Kaffe
is untouched. Note the latest Kaffe version has rearanged the thread
organization and I'm unclear as to the implications.
More information about the kaffe