Index: include/open/jthread.h =================================================================== --- include/open/jthread.h (revision 568362) +++ include/open/jthread.h (working copy) @@ -59,8 +59,6 @@ VMEXPORT IDATA jthread_create_with_function(JNIEnv * jni_env, jthread thread, jthread_threadattr_t *attrs); VMEXPORT IDATA jthread_attach(JNIEnv * jni_env, jthread thread, jboolean daemon); VMEXPORT IDATA jthread_detach(jthread thread); -VMEXPORT IDATA jthread_join(jthread thread); -VMEXPORT IDATA jthread_timed_join(jthread thread, jlong millis, jint nanos); VMEXPORT IDATA jthread_yield(); VMEXPORT IDATA jthread_stop(jthread thread); VMEXPORT IDATA jthread_exception_stop(jthread thread, jobject throwable); @@ -99,7 +97,6 @@ VMEXPORT IDATA jthread_set_priority(jthread thread, jint priority); VMEXPORT jint jthread_get_priority(jthread thread); -VMEXPORT jboolean jthread_is_daemon(jthread thread); /** * Sets the name for the thread. Index: vmcore/include/thread_manager.h =================================================================== --- vmcore/include/thread_manager.h (revision 568362) +++ vmcore/include/thread_manager.h (working copy) @@ -37,16 +37,6 @@ struct ClassLoader; /** - * These are thread level gc states. - */ -enum gc_state { - zero = 0, - gc_moving_to_safepoint, - gc_at_safepoint, - gc_enumeration_done -}; - -/** * Java-specific context that is attached to tm_thread control structure by Java layer */ struct JVMTIThread @@ -125,11 +115,6 @@ struct VM_thread { /** - * Native thread which is associated with VM_thread - */ - hythread_t native_thread; - - /** * Java thread object to corresponding java.lang.Thread instance */ jobject java_thread; @@ -179,8 +164,6 @@ // thread stack size UDATA stack_size; - // ?? - enum gc_state gc_status; int finalize_thread_flags; // CPU registers. @@ -211,7 +194,7 @@ void *lastFrame; void *firstFrame; - int interpreter_state; + int interpreter_state; /// wjw -- is this actually used?? /** * The upper boundary of the stack to scan when verifying stack enumeration Index: vmcore/src/kernel_classes/native/java_lang_VMThreadManager.cpp =================================================================== --- vmcore/src/kernel_classes/native/java_lang_VMThreadManager.cpp (revision 568362) +++ vmcore/src/kernel_classes/native/java_lang_VMThreadManager.cpp (working copy) @@ -239,7 +239,8 @@ JNIEXPORT jint JNICALL Java_java_lang_VMThreadManager_join (JNIEnv * UNREF jenv, jclass clazz, jobject thread, jlong millis, jint nanos) { - return (jint)jthread_timed_join(thread, millis, nanos); + assert(0); //wjw this API is no longer used, remove it as soon as it is convenient + return (jint) 0; } /* @@ -253,9 +254,18 @@ jint state; IDATA stat; - stat = jthread_get_jvmti_state(jthread, &state); - assert(stat == TM_ERROR_NONE); - return state; + hythread_t tm_native_thread = jthread_get_native_thread(jthread); + IDATA retval = hythread_get_state(tm_native_thread); + + stat = jthread_get_jvmti_state(jthread, &state); // wjw -- remove the call to ...jvmti_state() after a couple of regression cycles + assert(stat == TM_ERROR_NONE); // ditto the above comment + + if (retval != state) { // ditto the above comment + printf("------- retval = 0x%x, state = 0x%x\n", retval, state); + assert(0); + } + + return retval; } Index: vmcore/src/kernel_classes/javasrc/java/lang/VMThreadManager.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/VMThreadManager.java (revision 568362) +++ vmcore/src/kernel_classes/javasrc/java/lang/VMThreadManager.java (working copy) @@ -48,22 +48,22 @@ /** * JVMTI constants */ - public static final int JVMTI_THREAD_STATE_ALIVE = 0x0001; - public static final int JVMTI_THREAD_STATE_TERMINATED = 0x0002; - public static final int JVMTI_THREAD_STATE_RUNNABLE = 0x0004; - public static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400; - public static final int JVMTI_THREAD_STATE_WAITING = 0x0080; - public static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; - public static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; - public static final int JVMTI_THREAD_STATE_SLEEPING = 0x0040; - public static final int JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100; - public static final int JVMTI_THREAD_STATE_PARKED = 0x0200; - public static final int JVMTI_THREAD_STATE_SUSPENDED = 0x100000; - public static final int JVMTI_THREAD_STATE_INTERRUPTED = 0x200000; - public static final int JVMTI_THREAD_STATE_IN_NATIVE = 0x400000; - public static final int JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000; - public static final int JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000; - public static final int JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000; + public static final int TM_THREAD_STATE_ALIVE = 0x0001; + public static final int TM_THREAD_STATE_TERMINATED = 0x0002; + public static final int TM_THREAD_STATE_RUNNABLE = 0x0004; + public static final int TM_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400; + public static final int TM_THREAD_STATE_WAITING = 0x0080; + public static final int TM_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; + public static final int TM_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; + public static final int TM_THREAD_STATE_SLEEPING = 0x0040; + public static final int TM_THREAD_STATE_IN_OBJECT_WAIT = 0x0100; + public static final int TM_THREAD_STATE_PARKED = 0x0200; + public static final int TM_THREAD_STATE_SUSPENDED = 0x100000; + public static final int TM_THREAD_STATE_INTERRUPTED = 0x200000; + public static final int TM_THREAD_STATE_IN_NATIVE = 0x400000; + public static final int TM_THREAD_STATE_VENDOR_1 = 0x10000000; + public static final int TM_THREAD_STATE_VENDOR_2 = 0x20000000; + public static final int TM_THREAD_STATE_VENDOR_3 = 0x40000000; /** @@ -132,16 +132,6 @@ /** * This method satisfies the requirements of the specification for the - * {@link Thread#join(long, int) Thread.join(long timeout, int nanos)} - * method. But it doesn't throw an IllegalArgumentException - * exception. The millis and nanos arguments - * must be valid. - * @api2vm - */ - static native int join(Thread thread, long millis, int nanos); - - /** - * This method satisfies the requirements of the specification for the * {@link Object#notify() Object.notify()} method. * @api2vm */ Index: vmcore/src/kernel_classes/javasrc/java/lang/Thread.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/Thread.java (revision 568362) +++ vmcore/src/kernel_classes/javasrc/java/lang/Thread.java (working copy) @@ -588,7 +588,16 @@ public final void join() throws InterruptedException { synchronized (lock) { while (isAlive()) { - lock.wait(); + // 2000msec timeout added to provide graceful degradation + // in case there is a race condition where lock.wait somehow + // misses the "detach() lock.notifyAll()" + // Or, more likely, does not see this.isAlive = false + // because this.isAlive is still stuck in a CPU's store buffer + // the only drawback is if there are 100's of threads doing join()'s + // and the overhead of the continual timeouts may be a problem + // Let's first see a big money workload that waits on 100's of threads + // simultaneously before we worry + lock.wait(2000); } } } @@ -744,6 +753,12 @@ throw new OutOfMemoryError("Failed to create new thread"); } + + // wjw -- why are we *waiting* for a child thread to actually start running? + // this *guarantees* two context switches + // nothing in j.l.Thread spec says we have to do this + // my guess is that this actually masks an underlying race condition that we need to fix. + boolean interrupted = false; while(!this.started) { try { @@ -802,19 +817,26 @@ int state = (VMThreadManager.getState(this)); - if (0 != (state & VMThreadManager.JVMTI_THREAD_STATE_TERMINATED)) { + if (0 != (state & VMThreadManager.TM_THREAD_STATE_TERMINATED)) { return State.TERMINATED; - } else if (0 != (state & VMThreadManager.JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT)) { + } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_WAITING_WITH_TIMEOUT)) { return State.TIMED_WAITING; - } else if (0 != (state & VMThreadManager.JVMTI_THREAD_STATE_WAITING) - || 0 != (state & VMThreadManager.JVMTI_THREAD_STATE_PARKED)) { + } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_WAITING) + || 0 != (state & VMThreadManager.TM_THREAD_STATE_PARKED)) { return State.WAITING; - } else if (0 != (state & VMThreadManager.JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER)) { + } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER)) { return State.BLOCKED; - } else if (0 != (state & VMThreadManager.JVMTI_THREAD_STATE_ALIVE)) { + + } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_RUNNABLE)) { return State.RUNNABLE; + + //TODO track down all situations where a thread is really in RUNNABLE state + // but TM_THREAD_STATE_RUNNABLE is not set. In the meantime, leave the following + // TM_THREAD_STATE_ALIVE test as it is. + } else if (0 != (state & VMThreadManager.TM_THREAD_STATE_ALIVE)) { + return State.RUNNABLE; } else { - return State.NEW; + return State.NEW; // by deduction, if its none of the above } } Index: vmcore/src/thread/thread_java_basic.cpp =================================================================== --- vmcore/src/thread/thread_java_basic.cpp (revision 568362) +++ vmcore/src/thread/thread_java_basic.cpp (working copy) @@ -327,60 +327,6 @@ } // jthread_associate_native_and_java_thread /** - * Waits till the thread is finished. - * - * @param[in] java_thread a thread to wait for - * @return TM_THREAD_TIMEOUT or TM_THREAD_INTERRUPTED or 0 in case thread - * was successfully joined. - * @sa java.lang.Thread.join() - */ -IDATA jthread_join(jthread java_thread) -{ - if (java_thread == NULL) { - return TM_ERROR_NULL_POINTER; - } - - hythread_t native_thread = jthread_get_native_thread(java_thread); - if (!native_thread) { - return TM_ERROR_NONE; - } - IDATA status = hythread_join_interruptable(native_thread, 0, 0); - - TRACE(("TM: jthread %d joined %d", hythread_get_id(hythread_self()), - hythread_get_id(native_thread))); - - return status; -} // jthread_join - -/** - * Waits till the thread is finished with specific timeout. - * - * @param[in] java_thread a thread to wait for - * @param[in] millis timeout in milliseconds to wait - * @param[in] nanos timeout in nanoseconds to wait - * @return TM_THREAD_TIMEOUT or TM_THREAD_INTERRUPTED or 0 in case thread - * was successfully joined. - * @sa java.lang.Thread.join() - */ -IDATA jthread_timed_join(jthread java_thread, jlong millis, jint nanos) -{ - if (java_thread == NULL) { - return TM_ERROR_NULL_POINTER; - } - - hythread_t native_thread = jthread_get_native_thread(java_thread); - if (!native_thread) { - return TM_ERROR_NONE; - } - IDATA status = hythread_join_interruptable(native_thread, millis, nanos); - - TRACE(("TM: jthread %d joined %d", hythread_get_self_id(), - hythread_get_id(native_thread))); - - return status; -} // jthread_timed_join - -/** * Lets an another thread to pass. * @sa java.lang.Thread.yield() */ Index: vmcore/src/thread/thread_java_attrs.cpp =================================================================== --- vmcore/src/thread/thread_java_attrs.cpp (revision 568362) +++ vmcore/src/thread/thread_java_attrs.cpp (working copy) @@ -54,8 +54,3 @@ * * @param[in] thread thread those attribute is read */ -jboolean jthread_is_daemon(jthread thread) -{ - vm_thread_t vm_thread = (vm_thread_t)thread; - return (jboolean)vm_thread->daemon; -} Index: tests/unit/thread/test_java_basic.c =================================================================== --- tests/unit/thread/test_java_basic.c (revision 568362) +++ tests/unit/thread/test_java_basic.c (working copy) @@ -23,12 +23,6 @@ #include "thread_manager.h" /* - * Time for jthread_timed_join() to wait - * set in test_jthread_timed_join() and used in run_for_test_jthread_timed_join() - */ -int timed_join_wait_time; - -/* * Test jthread_attach() */ int HYTHREAD_PROC run_for_test_jthread_attach(void *args){ @@ -147,142 +141,6 @@ } /* - * Test jthread_join() - */ -void JNICALL run_for_test_jthread_join(jvmtiEnv * jvmti_env, JNIEnv * jni_env, void *args){ - - tested_thread_sturct_t * tts = (tested_thread_sturct_t *) args; - tested_thread_sturct_t * prev_tts = tts; - IDATA status; - - prev_tested_thread(&prev_tts); - if (prev_tts == NULL){ - // its the first tested thread - tts->phase = TT_PHASE_RUNNING; - tested_thread_started(tts); - tested_thread_wait_for_stop_request(tts); - tts->phase = TT_PHASE_DEAD; - tested_thread_ended(tts); - } else { - // wait until previous thread ends - tts->phase = TT_PHASE_WAITING_ON_JOIN; - tested_thread_started(tts); - status = jthread_join(prev_tts->java_thread); - tts->phase = (status == TM_ERROR_NONE ? TT_PHASE_DEAD : TT_PHASE_ERROR); - tested_thread_ended(tts); - } -} - -int test_jthread_join(void) { - - tested_thread_sturct_t * tts; - - tf_assert(MAX_TESTED_THREAD_NUMBER > 1); - - // Initialize tts structures and run all tested threads - tested_threads_run(run_for_test_jthread_join); - - reset_tested_thread_iterator(&tts); - next_tested_thread(&tts); - check_tested_thread_phase(tts, TT_PHASE_RUNNING); - while(next_tested_thread(&tts)){ - check_tested_thread_phase(tts, TT_PHASE_WAITING_ON_JOIN); - } - - // make the first thread terminated and test that all threads are terminated - reset_tested_thread_iterator(&tts); - next_tested_thread(&tts); - tested_thread_send_stop_request(tts); - tested_thread_wait_ended(tts); - while(next_tested_thread(&tts)){ - tested_thread_wait_ended(tts); - } - - // Terminate all threads (not needed here) and clear tts structures - tested_threads_destroy(); - - return TEST_PASSED; -} - -/* - * Test jthread_timed_join() - */ -void JNICALL run_for_test_jthread_timed_join(jvmtiEnv * jvmti_env, JNIEnv * jni_env, void *args){ - - tested_thread_sturct_t * tts = (tested_thread_sturct_t *) args; - tested_thread_sturct_t * prev_tts = tts; - IDATA status; - - prev_tested_thread(&prev_tts); - tts->phase = TT_PHASE_RUNNING; - tested_thread_started(tts); - if (prev_tts == NULL){ - tested_thread_wait_for_stop_request(tts); - tts->phase = TT_PHASE_DEAD; - } else { - // wait until timeout or previous thread ends - status = jthread_timed_join(prev_tts->java_thread, timed_join_wait_time, 0); - printf("-------- status = %#08x (%d) %d\n", (int)status, (int)status, timed_join_wait_time); - tts->phase = TT_PHASE_DEAD; - if (timed_join_wait_time > CLICK_TIME_MSEC * 10){ - // must be thread end - //tts->phase = (status == TM_ERROR_NONE ? TT_PHASE_DEAD : TT_PHASE_ERROR); - } else { - // must be timeout - //tts->phase = (status == TM_ERROR_TIMEOUT ? TT_PHASE_DEAD : TT_PHASE_ERROR); - } - } - tested_thread_ended(tts); -} - -int test_jthread_timed_join(void) { - - tested_thread_sturct_t * tts; - - tf_assert(MAX_TESTED_THREAD_NUMBER > 1); - - /* - * Test for jthread_timed_join() exit due to timeout - */ - timed_join_wait_time = 10 * CLICK_TIME_MSEC; - // Initialize tts structures and run all tested threads - tested_threads_run(run_for_test_jthread_timed_join); - - // skip the first thread - reset_tested_thread_iterator(&tts); - next_tested_thread(&tts); - jthread_sleep(20 * CLICK_TIME_MSEC * MAX_TESTED_THREAD_NUMBER, 0); - while(next_tested_thread(&tts)){ - check_tested_thread_phase(tts, TT_PHASE_DEAD); - } - - // Terminate all threads and clear tts structures - tested_threads_destroy(); - - /* - * Test for jthread_timed_join() before timeout - */ - timed_join_wait_time = 1000 * CLICK_TIME_MSEC * MAX_TESTED_THREAD_NUMBER; - // Initialize tts structures and run all tested threads - tested_threads_run(run_for_test_jthread_timed_join); - - // make the first thread terminated and test that all threads are terminated - reset_tested_thread_iterator(&tts); - next_tested_thread(&tts); - tested_thread_send_stop_request(tts); - tested_thread_wait_ended(tts); - jthread_sleep(20 * CLICK_TIME_MSEC * MAX_TESTED_THREAD_NUMBER, 0); - while(next_tested_thread(&tts)){ - check_tested_thread_phase(tts, TT_PHASE_DEAD); - } - - // Terminate all threads and clear tts structures - tested_threads_destroy(); - - return TEST_PASSED; -} - -/* * Test jthread_exception_stop() */ void JNICALL run_for_test_jthread_exception_stop(jvmtiEnv * jvmti_env, JNIEnv * jni_env, void *args){ @@ -485,8 +343,6 @@ TEST(test_hythread_create) TEST(test_hythread_create_with_function) TEST(test_jthread_get_JNI_env) - TEST(test_jthread_join) - TEST(test_jthread_timed_join) TEST(test_jthread_exception_stop) TEST(test_jthread_stop) TEST(test_jthread_sleep) Index: thread/src/thread_native_basic.c =================================================================== --- thread/src/thread_native_basic.c (revision 568362) +++ thread/src/thread_native_basic.c (working copy) @@ -607,7 +607,7 @@ new_thread->safepoint_callback = NULL; hymutex_lock(&new_thread->mutex); - new_thread->state = TM_THREAD_STATE_ALLOCATED; + new_thread->state = 0; hymutex_unlock(&new_thread->mutex); status = hylatch_set(new_thread->join_event, 1);