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
@@ -127,7 +117,7 @@
/**
* Native thread which is associated with VM_thread
*/
- hythread_t native_thread;
+ hythread_t p_HyThread;
/**
* Java thread object to corresponding java.lang.Thread instance
@@ -179,8 +169,6 @@
// thread stack size
UDATA stack_size;
- // ??
- enum gc_state gc_status;
int finalize_thread_flags;
// CPU registers.
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;
}
/*
@@ -250,12 +251,10 @@
JNIEXPORT jint JNICALL Java_java_lang_VMThreadManager_getState
(JNIEnv * UNREF jenv, jclass clazz, jobject jthread)
{
- 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);
+
+ 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);