Permalink
Browse files

fix custom-classloader-related concurrency problems and other bugs

The main changes in this commit ensure that we don't hold the global
class lock when doing class resolution using application-defined
classloaders.  Such classloaders may do their own locking (in fact,
it's almost certain), making deadlock likely when mixed with VM-level
locking in various orders.

Other changes include a fix to avoid overflow when waiting for
extremely long intervals and a GC root stack mapping bug.
  • Loading branch information...
1 parent f485016 commit d0d53e2e10b70a5fa467b4446af988286c28cca4 @dicej dicej committed Sep 17, 2010
Showing with 333 additions and 228 deletions.
  1. +3 −19 classpath/java/lang/Thread.java
  2. +0 −4 makefile
  3. +17 −4 src/builtin.cpp
  4. +2 −1 src/classpath-avian.cpp
  5. +29 −4 src/classpath-openjdk.cpp
  6. +159 −117 src/compile.cpp
  7. +2 −2 src/jnienv.cpp
  8. +76 −64 src/machine.cpp
  9. +25 −10 src/machine.h
  10. +5 −1 src/posix.cpp
  11. +3 −2 src/types.def
  12. +12 −0 test/GC.java
@@ -15,7 +15,7 @@
public class Thread implements Runnable {
private long peer;
- private boolean interrupted;
+ private volatile boolean interrupted;
private boolean daemon;
private byte state;
private byte priority;
@@ -141,25 +141,9 @@ public void setContextClassLoader(ClassLoader v) {
public static native Thread currentThread();
- private static native void interrupt(long peer);
+ public native void interrupt();
- public synchronized void interrupt() {
- if (peer != 0) {
- interrupt(peer);
- } else {
- interrupted = true;
- }
- }
-
- public static boolean interrupted() {
- Thread t = currentThread();
-
- synchronized (t) {
- boolean v = t.interrupted;
- t.interrupted = false;
- return v;
- }
- }
+ public native boolean interrupted();
public static boolean isInterrupted() {
return currentThread().interrupted;
View
@@ -340,10 +340,6 @@ vm-sources = \
vm-asm-sources = $(src)/$(asm).S
ifeq ($(process),compile)
- vm-depends += \
- $(src)/compiler.h \
- $(src)/vector.h
-
vm-sources += \
$(src)/compiler.cpp \
$(src)/$(asm).cpp
View
@@ -84,7 +84,12 @@ Avian_avian_SystemClassLoader_resourceExists
if (LIKELY(name)) {
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
- return getFinder(t, loader)->exists(RUNTIME_ARRAY_BODY(n));
+
+ bool r = getFinder(t, loader)->exists(RUNTIME_ARRAY_BODY(n));
+
+ fprintf(stderr, "resource %s exists? %d\n", n, r);
+
+ return r;
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
@@ -144,7 +149,11 @@ Avian_avian_resource_Handler_00024ResourceInputStream_getContentLength
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
- System::Region* r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p));
+ System::Region* r = t->m->bootFinder->find(RUNTIME_ARRAY_BODY(p));
+ if (r == 0) {
+ r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p));
+ }
+
if (r) {
jint rSize = r->length();
r->dispose();
@@ -164,8 +173,12 @@ Avian_avian_resource_Handler_00024ResourceInputStream_open
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
- return reinterpret_cast<int64_t>
- (t->m->appFinder->find(RUNTIME_ARRAY_BODY(p)));
+ System::Region* r = t->m->bootFinder->find(RUNTIME_ARRAY_BODY(p));
+ if (r == 0) {
+ r = t->m->appFinder->find(RUNTIME_ARRAY_BODY(p));
+ }
+
+ return reinterpret_cast<int64_t>(r);
} else {
t->exception = t->m->classpath->makeThrowable
(t, Machine::NullPointerExceptionType);
@@ -50,7 +50,7 @@ class MyClasspath : public Classpath {
return vm::makeThread
(t, 0, 0, 0, NewState, NormalPriority, 0, 0, 0,
- root(t, Machine::BootLoader), 0, 0, group);
+ root(t, Machine::BootLoader), 0, 0, group, 0);
}
virtual void
@@ -70,6 +70,7 @@ class MyClasspath : public Classpath {
(Thread* t, Machine::Type type, object message, object trace, object cause)
{
PROTECT(t, message);
+ PROTECT(t, trace);
PROTECT(t, cause);
if (trace == 0) {
@@ -186,7 +186,7 @@ class MyClasspath : public Classpath {
return vm::makeThread
(t, 0, NormalPriority, 0, 0, false, false, false, 0, group,
root(t, Machine::BootLoader), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0,
- 0, false);
+ 0, 0, false);
}
virtual void
@@ -210,6 +210,7 @@ class MyClasspath : public Classpath {
(Thread* t, Machine::Type type, object message, object trace, object cause)
{
PROTECT(t, message);
+ PROTECT(t, trace);
PROTECT(t, cause);
if (trace == 0) {
@@ -534,6 +535,23 @@ setProperty(Thread* t, object method, object properties,
t->m->processor->invoke(t, method, properties, n, v);
}
+object
+interruptLock(Thread* t, object thread)
+{
+ if (threadInterruptLock(t, thread) == 0) {
+ PROTECT(t, thread);
+ ACQUIRE(t, t->m->referenceLock);
+
+ if (threadInterruptLock(t, thread) == 0) {
+ object head = makeMonitorNode(t, 0, 0);
+ object lock = makeMonitor(t, 0, 0, 0, head, head, 0);
+ set(t, thread, ThreadInterruptLock, lock);
+ }
+ }
+
+ return threadInterruptLock(t, thread);
+}
+
} // namespace local
} // namespace
@@ -1255,23 +1273,27 @@ JVM_Interrupt(Thread* t, jobject thread)
{
ENTER(t, Thread::ActiveState);
+ monitorAcquire(t, local::interruptLock(t, *thread));
Thread* p = reinterpret_cast<Thread*>(threadPeer(t, *thread));
if (p) {
interrupt(t, p);
+ } else {
+ threadInterrupted(t, *thread) = true;
}
+ monitorRelease(t, local::interruptLock(t, *thread));
}
extern "C" JNIEXPORT jboolean JNICALL
JVM_IsInterrupted(Thread* t, jobject thread, jboolean clear)
{
ENTER(t, Thread::ActiveState);
- acquire(t, *thread);
+ monitorAcquire(t, local::interruptLock(t, *thread));
bool v = threadInterrupted(t, *thread);
if (clear) {
threadInterrupted(t, *thread) = false;
}
- release(t, *thread);
+ monitorRelease(t, local::interruptLock(t, *thread));
return v;
}
@@ -2414,7 +2436,10 @@ extern "C" JNIEXPORT struct hostent* JNICALL
JVM_GetHostByName(char*) { abort(); }
extern "C" JNIEXPORT int JNICALL
-JVM_GetHostName(char*, int) { abort(); }
+JVM_GetHostName(char* name, int length)
+{
+ return gethostname(name, length);
+}
extern "C" JNIEXPORT void* JNICALL
JVM_RawMonitorCreate(void)
Oops, something went wrong.

0 comments on commit d0d53e2

Please sign in to comment.