fix Thread.join when using Android class library

Android's Thread.join expects the VM to null-out Thread.vmThread when
the thread exits.  Otherwise, it will block forever.
This commit is contained in:
Joel Dice 2014-02-25 12:33:12 -07:00
parent 2b17ba7766
commit 1445835c4f
2 changed files with 49 additions and 23 deletions

View File

@ -157,17 +157,11 @@ makeField(Thread* t, object c, unsigned index)
return makeJfield(t, 0, c, type, 0, 0, name, index); return makeJfield(t, 0, c, type, 0, 0, name, index);
} }
void void initVmThread(Thread* t, object thread, unsigned offset)
initVmThread(Thread* t, object thread)
{ {
PROTECT(t, thread); PROTECT(t, thread);
object field = resolveField if (fieldAtOffset<object>(thread, offset) == 0) {
(t, objectClass(t, thread), "vmThread", "Ljava/lang/VMThread;");
if (fieldAtOffset<object>(thread, fieldOffset(t, field)) == 0) {
PROTECT(t, field);
object c = resolveClass object c = resolveClass
(t, root(t, Machine::BootLoader), "java/lang/VMThread"); (t, root(t, Machine::BootLoader), "java/lang/VMThread");
PROTECT(t, c); PROTECT(t, c);
@ -180,7 +174,7 @@ initVmThread(Thread* t, object thread)
t->m->processor->invoke(t, constructor, instance, thread); t->m->processor->invoke(t, constructor, instance, thread);
set(t, thread, fieldOffset(t, field), instance); set(t, thread, offset, instance);
} }
if (threadGroup(t, thread) == 0) { if (threadGroup(t, thread) == 0) {
@ -189,6 +183,17 @@ initVmThread(Thread* t, object thread)
} }
} }
void initVmThread(Thread* t, object thread)
{
initVmThread(
t,
thread,
fieldOffset(
t,
resolveField(
t, objectClass(t, thread), "vmThread", "Ljava/lang/VMThread;")));
}
object object
translateStackTrace(Thread* t, object raw) translateStackTrace(Thread* t, object raw)
{ {
@ -353,14 +358,28 @@ class MyClasspath : public Classpath {
// later when we try to acquire it: // later when we try to acquire it:
objectMonitor(t, t->javaThread, true); objectMonitor(t, t->javaThread, true);
THREAD_RESOURCE0(t, { object field = resolveField(
vm::acquire(t, t->javaThread); t, objectClass(t, t->javaThread), "vmThread", "Ljava/lang/VMThread;");
t->flags &= ~Thread::ActiveFlag;
vm::notifyAll(t, t->javaThread); unsigned offset = fieldOffset(t, field);
vm::release(t, t->javaThread);
THREAD_RESOURCE(t, unsigned, offset, {
object vmt = fieldAtOffset<object>(t->javaThread, offset);
if (vmt) {
PROTECT(t, vmt);
vm::acquire(t, vmt);
fieldAtOffset<object>(t->javaThread, offset) = 0;
vm::notifyAll(t, vmt);
vm::release(t, vmt);
}
vm::acquire(t, t->javaThread);
t->flags &= ~Thread::ActiveFlag;
vm::notifyAll(t, t->javaThread);
vm::release(t, t->javaThread);
}); });
initVmThread(t, t->javaThread); initVmThread(t, t->javaThread, offset);
object method = resolveMethod object method = resolveMethod
(t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V"); (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V");

View File

@ -1,15 +1,11 @@
public class Threads implements Runnable { public class Threads implements Runnable {
public static void main(String[] args) { public static void main(String[] args) throws Exception {
{ Threads test = new Threads(); { Threads test = new Threads();
Thread thread = new Thread(test); Thread thread = new Thread(test);
try { synchronized (test) {
synchronized (test) { thread.start();
thread.start(); test.wait();
test.wait();
}
} catch (Throwable e) {
e.printStackTrace();
} }
} }
@ -33,6 +29,17 @@ public class Threads implements Runnable {
System.out.println("\nInterrupted!"); System.out.println("\nInterrupted!");
} }
{ Thread thread = new Thread() {
@Override
public void run() {
// do nothing
}
};
thread.start();
thread.join();
}
System.out.println("finished"); System.out.println("finished");
} }