/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 */ static JNIEXPORT void JNICALL Java_java_lang_VMThread_yield (JNIEnv *_env, jclass _class) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmf_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: _svmf_stopping_java (env); return; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeIsAlive ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: nativeIsAlive * Signature: ([B)Z */ static JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_nativeIsAlive (JNIEnv *_env, jobject this, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jboolean result; _svmf_resuming_java (env); result = ((_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData))->is_alive; _svmf_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeStart ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: nativeStart * Signature: ()[B */ static JNIEXPORT jbyteArray JNICALL Java_java_lang_VMThread_nativeStart (JNIEnv *_env, jobject this, jobject threadInstance) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jbyteArray result = NULL; _svmf_resuming_java (env); { _svmt_JavaVM *vm = env->vm; _svmt_JNIEnv *new_env = NULL; { jint status = JNI_OK; _svmm_mutex_lock (vm->global_mutex); if (vm->threads.free_list != NULL) { new_env = vm->threads.free_list; assert (new_env->previous == NULL); vm->threads.free_list = new_env->next; if (vm->threads.free_list != NULL) { vm->threads.free_list->previous = NULL; } new_env->next = vm->threads.user; if (new_env->next != NULL) { assert (new_env->next->previous == NULL); new_env->next->previous = new_env; } new_env->thread_status = SVM_THREAD_STATUS_RUNNING_JAVA; } else if (vm->threads.next_thread_id <= SVM_MAX_THREAD_ID) { if (_svmm_gzalloc_env_no_exception (new_env) != JNI_OK) { goto unlock; } new_env->interface = &_svmv_native_interface; new_env->vm = vm; new_env->next = vm->threads.user; vm->threads.user = new_env; if (new_env->next != NULL) { assert (new_env->next->previous == NULL); new_env->next->previous = new_env; } /* Initialize locking / monitors structures */ new_env->interrupted_status = SVM_THREAD_NOT_INTERRUPTED; new_env->thread.id = vm->threads.next_thread_id++; _svmf_initialize_thinlock_id (new_env); vm->threads.array[new_env->thread.id] = new_env; _svmm_mutex_init (new_env->contention.owner.mutex); _svmm_cond_init (new_env->contention.requester.cond); new_env->thread_status = SVM_THREAD_STATUS_RUNNING_JAVA; } else { status = JNI_ERR; } unlock: _svmm_mutex_unlock (); if (status != JNI_OK) { _svmf_error_OutOfMemoryError (env); goto end; } } if (_svmm_gzalloc_thread_node_no_exception (new_env->contention.thread_node) != JNI_OK) { _svmf_error_OutOfMemoryError (env); goto end; } new_env->contention.thread_node->thread = new_env; if (_svmm_gzalloc_native_ref_no_exception (new_env->native_locals.list) != JNI_OK) { /* we should be cleaning up! todo ... */ _svmf_error_OutOfMemoryError (env); goto end; } new_env->throwable = _svmf_cast_jobject_nref (new_env->native_locals.list); if (_svmm_gzalloc_native_ref_no_exception (new_env->native_locals.list->next) != JNI_OK) { /* we should be cleaning up! todo ... */ _svmf_error_OutOfMemoryError (env); goto end; } new_env->thread.thread_instance = _svmf_cast_jobject_nref (new_env->native_locals.list->next); *(new_env->thread.thread_instance) = *(threadInstance); if (_svmm_gzalloc_native_ref_no_exception (new_env->native_locals.list->next->next) != JNI_OK) { /* we should be cleaning up! todo ... */ _svmf_error_OutOfMemoryError (env); goto end; } new_env->contention.requester.jobject = _svmf_cast_jobject_nref (new_env->native_locals.list->next->next); if (_svmf_stack_init (new_env) != JNI_OK) { /* we should be cleaning up! todo ... */ *(env->throwable) = *(new_env->throwable); goto end; } /* start it! */ new_env->is_alive = JNI_TRUE; if (pthread_create (&new_env->thread.pthread, NULL, &_svmf_thread_start, new_env) != 0) { /* something went wrong */ /* we should be cleaning up! todo ... */ new_env->is_alive = JNI_FALSE; _svmf_error_InternalError (env); goto end; } /* it's started! */ result = _svmf_get_jni_frame_native_local_array (env); if (_svmf_wrap_pointer (env, new_env, result) != JNI_OK) { result = NULL; goto end; } } end: _svmf_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_currentThread ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: currentThread * Signature: ()Ljava/lang/Thread; */ static JNIEXPORT jobject JNICALL Java_java_lang_VMThread_currentThread (JNIEnv *_env, jclass _class) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); jobject result = NULL; _svmf_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: _svmf_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeInterrupt ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: interrupt * Signature: ()V */ static JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeInterrupt (JNIEnv *_env, jobject this, jbyteArray vmData) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JNIEnv *target_env = (_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData); _svmt_word old_status, new_status; _svmf_resuming_java (env); do { new_status = old_status = target_env->interrupted_status; if (old_status & SVM_THREAD_INTERRUPTIBLE_ON_FAT_LOCK) { new_status |= SVM_THREAD_THROW_INTERRUPTED; } else { new_status |= SVM_THREAD_INTERRUPTED; } } while (!_svmm_compare_and_swap (target_env->interrupted_status, old_status, new_status)); if (old_status & SVM_THREAD_INTERRUPTIBLE_ON_FAT_LOCK) { jint fat_id = old_status >> 16; _svmt_fat_lock *fat_lock; assert (fat_id < env->vm->threads.next_thread_id); fat_lock = env->vm->fat_locks.array[fat_id]; _svmm_mutex_lock (fat_lock->mutex); _svmm_cond_broadcast (fat_lock->cond); _svmm_mutex_unlock (); } _svmf_stopping_java (env); return; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_nativeIsInterrupted ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: isInterrupted * Signature: ()Z */ static JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_nativeIsInterrupted (JNIEnv *_env, jobject this, jbyteArray vmData) { jboolean result; _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmf_resuming_java (env); result = (((_svmt_JNIEnv *) _svmf_unwrap_pointer (*vmData))-> interrupted_status) & SVM_THREAD_INTERRUPTED; _svmf_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_interrupted ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: interrupted * Signature: ()Z */ static JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_interrupted (JNIEnv *_env, jclass this) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_word old_status, new_status; jboolean result; _svmf_resuming_java (env); /* this is static method that refers to the _current_ thread only, * so no need to search which thread is referred to by "this" */ do { new_status = old_status = env->interrupted_status; new_status &= ~SVM_THREAD_INTERRUPTED; } while (!_svmm_compare_and_swap (env->interrupted_status, old_status, new_status)); if (old_status & SVM_THREAD_INTERRUPTED) { result = JNI_TRUE; } else { result = JNI_FALSE; } _svmf_stopping_java (env); return result; } /* ---------------------------------------------------------------------- Java_java_lang_VMThread_holdsLock ---------------------------------------------------------------------- */ /* * Class: java_lang_VMThread * Method: holdsLock * Signature: (Ljava/lang/Object;)Z */ static JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_holdsLock (JNIEnv *_env, jclass class, jobject o) { _svmt_JNIEnv *env = _svmf_cast_svmt_JNIEnv (_env); _svmt_JavaVM *vm = env->vm; jboolean result = JNI_TRUE; _svmf_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_id = _svmf_lockword_get_fatlock_index (lockword); _svmt_fat_lock *fat_lock = vm->fat_locks.array[fat_id]; if (fat_lock->owner != env) { result = JNI_FALSE; } } } end: _svmf_stopping_java (env); return result; }