diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 2b12362a6c..c2b8471dde 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -3231,12 +3231,20 @@ EXPORT(JVM_DisableCompiler)(Thread*, jclass) // ignore } +uint64_t +jvmStartThread(Thread* t, uintptr_t* arguments) +{ + jobject thread = reinterpret_cast(arguments[0]); + + return startThread(t, *thread) != 0; +} + extern "C" JNIEXPORT void JNICALL EXPORT(JVM_StartThread)(Thread* t, jobject thread) { - ENTER(t, Thread::ActiveState); + uintptr_t arguments[] = { reinterpret_cast(thread) }; - startThread(t, *thread); + run(t, jvmStartThread, arguments); } extern "C" JNIEXPORT void JNICALL diff --git a/src/machine.cpp b/src/machine.cpp index fbf8ca2511..c9026e5360 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -229,6 +229,9 @@ turnOffTheLights(Thread* t) visitAll(t, t->m->rootThread, disposeNoRemove); System* s = m->system; + + expect(s, m->threadCount == 0); + Heap* h = m->heap; Processor* p = m->processor; Classpath* c = m->classpath; @@ -2435,6 +2438,7 @@ Machine::Machine(System* system, Heap* heap, Finder* bootFinder, propertyCount(propertyCount), arguments(arguments), argumentCount(argumentCount), + threadCount(0), activeCount(0), liveCount(0), daemonCount(0), @@ -2653,6 +2657,8 @@ Thread::dispose() } } + -- m->threadCount; + m->heap->free(defaultHeap, ThreadHeapSizeInBytes); m->processor->dispose(this); @@ -2864,6 +2870,7 @@ enter(Thread* t, Thread::State s) INCREMENT(&(t->m->activeCount), 1); if (t->state == Thread::NoState) { ++ t->m->liveCount; + ++ t->m->threadCount; } t->state = s; } break; diff --git a/src/machine.h b/src/machine.h index b11ca98667..96ac9c5086 100644 --- a/src/machine.h +++ b/src/machine.h @@ -120,6 +120,10 @@ const unsigned ThreadHeapPoolSize = 64; const unsigned FixedFootprintThresholdInBytes = ThreadHeapPoolSize * ThreadHeapSizeInBytes; +// number of zombie threads which may accumulate before we force a GC +// to clean them up: +const unsigned ZombieCollectionThreshold = 16; + enum FieldCode { VoidField, ByteField, @@ -1299,6 +1303,7 @@ class Machine { unsigned propertyCount; const char** arguments; unsigned argumentCount; + unsigned threadCount; unsigned activeCount; unsigned liveCount; unsigned daemonCount; @@ -1994,6 +1999,7 @@ addThread(Thread* t, Thread* p) assert(t, p->state == Thread::NoState); p->state = Thread::IdleState; + ++ t->m->threadCount; ++ t->m->liveCount; p->peer = p->parent->child; @@ -2012,6 +2018,7 @@ removeThread(Thread* t, Thread* p) assert(t, p->state == Thread::IdleState); -- t->m->liveCount; + -- t->m->threadCount; t->m->stateLock->notifyAll(t->systemThread); @@ -2020,11 +2027,25 @@ removeThread(Thread* t, Thread* p) if (p->javaThread) { threadPeer(t, p->javaThread) = 0; } + + p->dispose(); } inline Thread* startThread(Thread* t, object javaThread) { + { PROTECT(t, javaThread); + + stress(t); + + ACQUIRE_RAW(t, t->m->stateLock); + + if (t->m->threadCount > t->m->liveCount + ZombieCollectionThreshold) { + fprintf(stderr, "hit zombie collection threshold\n"); + collect(t, Heap::MinorCollection); + } + } + Thread* p = t->m->processor->makeThread(t->m, javaThread, t); addThread(t, p);