/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This source file is part of SableVM. * * * * See the file "LICENSE" for the copyright information and for * * the terms and conditions for copying, distribution and * * modification of this source file. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* ---------------------------------------------------------------------- Java_java_lang_VMThread_yield ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: yield * Signature: ()V */ JNIEXPORT static void JNICALL Java_java_lang_VMThread_yield (JNIEnv *_env, jclass _class SVM_UNUSED) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmm_resuming_java (env); if (sched_yield () != 0) { /* Should we really really throw an error on failure? Maybe we could simply ignore the return value, if no harm is implied. Suggestions are welcome. Etienne */ _svmf_error_InternalError (env); goto end; } end: _svmm_stopping_java (env); return; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_sleep ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: sleep * Signature: ()Z */ JNIEXPORT static void JNICALL Java_java_lang_VMThread_sleep (JNIEnv *_env SVM_UNUSED, jclass this SVM_UNUSED, jlong ms, jint ns) { /* _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); */ struct timespec timeout; timeout.tv_sec = ms / 1000; timeout.tv_nsec = (ms % 1000) * 1000 * 1000 + ns; /* Watch for overflow of timeout.tv_nsec... OK; I assume that tv_nsec has at least 32 bits (signed or not, I don't care), a reasonable assumption given that it must be able to hold the value 999999999. */ if (timeout.tv_nsec >= 1000000000L) { timeout.tv_sec++; timeout.tv_nsec -= 1000000000L; } /* we don't check the return value, as in case of interrupt() that * caused a signal that woke us up, we'll have interrupted_status * flag set accordingly */ nanosleep (&timeout, NULL); } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeIsAlive ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: nativeIsAlive * Signature: ([B)Z */ JNIEXPORT static jboolean JNICALL Java_java_lang_VMThread_nativeIsAlive (JNIEnv *_env, jobject this SVM_UNUSED, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jboolean result; _svmm_resuming_java (env); result = ((_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData))->is_alive; _svmm_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeStart ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: nativeStart * Signature: ()[B */ JNIEXPORT static jbyteArray JNICALL Java_java_lang_VMThread_nativeStart (JNIEnv *_env, jobject this SVM_UNUSED, jobject threadInstance) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jbyteArray result = NULL; _svmm_resuming_java (env); { _svmt_JNIEnv *new_env = _svmf_thread_native_start (env, threadInstance); if (new_env != NULL) { result = _svmf_get_jni_frame_native_local_array (env); if (_svmf_wrap_pointer (env, new_env, result) != JNI_OK) { result = NULL; goto end; } } } end: _svmm_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_currentThread ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: currentThread * Signature: ()Ljava/lang/Thread; */ JNIEXPORT static jobject JNICALL Java_java_lang_VMThread_currentThread (JNIEnv *_env, jclass _class SVM_UNUSED) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jobject result = NULL; _svmm_resuming_java (env); { if (env->thread.thread_instance == NULL) { jobject thread; jbyteArray wrapper; if (_svmm_new_native_local (env, thread) != JNI_OK) { goto end; } if (_svmm_local_wrap_pointer (env, env, wrapper) != JNI_OK) { _svmm_free_native_local (env, thread); goto end; } if (_svmm_invoke_static_virtualmachine_createrootthread (env, _svmf_cast_jobject (wrapper), thread) != JNI_OK) { _svmm_free_native_local_array (env, wrapper); _svmm_free_native_local (env, thread); goto end; } _svmm_free_native_local_array (env, wrapper); env->thread.thread_instance = thread; } result = _svmf_get_jni_frame_native_local (env); *result = *(env->thread.thread_instance); } end: _svmm_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeInterrupt ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: interrupt * Signature: ()V */ JNIEXPORT static void JNICALL Java_java_lang_VMThread_nativeInterrupt (JNIEnv *_env, jobject this SVM_UNUSED, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JavaVM *vm = env->vm; _svmt_JNIEnv *target_env = (_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData); _svmm_resuming_java (env); /* < interrupting current thread > */ if (env == target_env) { /* [ * set "interrupted" flag on the current thread ] */ env->locking.interrupted = JNI_TRUE; } else { /* [ * suspend the target thread ] */ _svmm_mutex_lock (vm->global_mutex); _svmf_suspend_thread (env, target_env); _svmm_mutex_unlock (); /* < target thread "waiting on object" reference is set > */ if (*target_env->locking.waiting_on) { _svmt_word body_index; _svmt_JNIEnv *main_body; /* [ * acquire mutex of the main body associated with ] * [ the object the target thread is waiting on ] */ body_index = _svmf_lockword_get_fatlock_index ((*target_env->locking.waiting_on)->lockword); main_body = env->vm->threads.array[body_index]; _svmm_mutex_lock (main_body->body.mutex); /* [ * set "interrupted" flag on target thread ] */ target_env->locking.interrupted = JNI_TRUE; /* [ * signal (with UNIX signal) the target thread ] */ _svmm_kill (target_env->thread.pthread, SVM_INTERRUPT_SIGNAL); /* Note: this is not guaranteed by POSIX standards that * a signal will actually wake up a blocked thread. */ /* [ * release main body mutex ] */ _svmm_mutex_unlock (); } else { /* [ * set "interrupted" flag of the target thread ] */ env->locking.interrupted = JNI_TRUE; } /* [ * resume the target thread ] */ _svmm_mutex_lock (vm->global_mutex); _svmf_resume_thread (env, target_env); _svmm_mutex_unlock (); } _svmm_stopping_java (env); return; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeIsInterrupted ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: isInterrupted * Signature: ()Z */ JNIEXPORT static jboolean JNICALL Java_java_lang_VMThread_nativeIsInterrupted (JNIEnv *_env SVM_UNUSED, jobject this SVM_UNUSED, jbyteArray vmData) { _svmt_JNIEnv *target_env = (_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData); return target_env->locking.interrupted; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_interrupted ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: interrupted * Signature: ()Z */ JNIEXPORT static jboolean JNICALL Java_java_lang_VMThread_interrupted (JNIEnv *_env, jclass this SVM_UNUSED) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jboolean result; /* this is static method that refers to the _current_ thread only, * so no need to search which thread is referred to by "this" */ result = env->locking.interrupted; env->locking.interrupted = JNI_FALSE; return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_holdsLock ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: holdsLock * Signature: (Ljava/lang/Object;)Z */ JNIEXPORT static jboolean JNICALL Java_java_lang_VMThread_holdsLock (JNIEnv *_env, jclass class SVM_UNUSED, jobject o) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JavaVM *vm = env->vm; jboolean result = JNI_TRUE; _svmm_resuming_java (env); { /* Note: the case where o == NULL should be handled before calling this function */ _svmt_object_instance *instance = *o; _svmt_word lockword = instance->lockword; if (_svmf_lockword_is_thin (lockword)) { if (_svmf_lockword_get_thinlock_id (lockword) != env->thread.thinlock_id) { result = JNI_FALSE; } goto end; } /* It's a fat lock. */ { _svmt_word fat_index = _svmf_lockword_get_fatlock_index (lockword); _svmt_JNIEnv *fat_lock = vm->threads.array[fat_index]; if (fat_lock->body.owner != env) { result = JNI_FALSE; } } } end: _svmm_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_suspend ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: suspend * Signature: ()V */ JNIEXPORT static void JNICALL Java_java_lang_VMThread_suspend (JNIEnv *_env, jclass class SVM_UNUSED, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JavaVM *vm = env->vm; _svmm_resuming_java (env); { _svmt_JNIEnv *target; target = _svmf_unwrap_pointer (*vmData); _svmm_mutex_lock (vm->global_mutex); _svmf_suspend_thread (env, target); _svmm_mutex_unlock (); } _svmm_stopping_java (env); } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_resume ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: resume * Signature: ()V */ JNIEXPORT static void JNICALL Java_java_lang_VMThread_resume (JNIEnv *_env, jclass class SVM_UNUSED, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JavaVM *vm = env->vm; _svmm_resuming_java (env); { _svmt_JNIEnv *target; target = _svmf_unwrap_pointer (*vmData); _svmm_mutex_lock (vm->global_mutex); _svmf_resume_thread (env, target); _svmm_mutex_unlock (); } _svmm_stopping_java (env); }