Re: JNI Attach/DetachCurrentThread
Marcel Wiesweg <[email protected]> Fri, 6 May 2005 19:18:07 +0200
| Newsgroups | gmane.comp.java.vm.sablevm.devel |
|---|---|
| Message-ID | <[email protected]> |
Am Donnerstag 14 April 2005 23:02 schrieb Marcel Wiesweg: > Hi, > > the attached patch implements the JNI AttachCurrentThread and > DetachCurrentThread calls. > I have tested this shortly without any problems so far with an application > that accesses the VM from multiple threads. The code is combined from > _svmf_thread_native_start and JNI_CreateJavaVM, I hope I got everything > right. I just learned that it is valid to call AttachCurrentThread when the thread is already attached. In that case env shall be set to the current env and JNI_OK be returned. Attached is an updated patch. One thing still missing is handling of the JavaVMAttachArgs (thread name and thread group). Currently I don't know where to store this information until the thread_instance object is created in java_lang_VMThread.c. Marcel > > > Marcel _______________________________________________ SableVM-devel mailing list [email protected] http://sablevm.org/lists/control/listinfo/sablevm-devel
attachthread.diff
(text/x-diff, 4.7 KB)
Index: src/libsablevm/invoke_interface.c
===================================================================
--- src/libsablevm/invoke_interface.c (revision 3960)
+++ src/libsablevm/invoke_interface.c (working copy)
@@ -491,10 +491,140 @@
*/
JNIEXPORT static jint JNICALL
-AttachCurrentThread (JavaVM *vm SVM_UNUSED, void **penv SVM_UNUSED,
- void *args SVM_UNUSED)
+AttachCurrentThread (JavaVM *_vm, void **penv,
+ void *args)
{
- _svmm_fatal_error ("todo");
+ _svmt_JNIEnv *new_env = NULL;
+ _svmt_JavaVM *vm = (_svmt_JavaVM *) (void *) _vm;
+
+ /* make sure this thread isn't already attached to a vm */
+ _svmt_JNIEnv *current_env = _svmf_get_current_env ();
+ if (current_env != NULL) {
+ if (vm == current_env->vm)
+ {
+ /* if already attached and vm is valid, set penv and return OK */
+ *penv = current_env;
+ return JNI_OK;
+ }
+ else
+ {
+ goto end;
+ }
+ }
+
+ {
+ 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_NOT_RUNNING_JAVA_RESUMING_ALLOWED;
+ }
+ else if (vm->threads.next_thread_id <= SVM_MAX_THREAD_ID)
+ {
+ if (_svmm_gzalloc_env_no_exception (new_env) != JNI_OK)
+ {
+ status=JNI_ERR;
+ 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;
+ }
+
+ new_env->thread.interrupted_status = SVM_THREAD_NOT_INTERRUPTED;
+ new_env->thread.sleeping_on_fat_lock = NULL;
+
+ 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_cond_init (new_env->wakeup_cond);
+ _svmm_cond_init (new_env->suspension.cond);
+ _svmm_mutex_init (new_env->contention.owner.mutex);
+ _svmm_cond_init (new_env->contention.requester.cond);
+
+ new_env->thread_status =
+ SVM_THREAD_STATUS_NOT_RUNNING_JAVA_RESUMING_ALLOWED;
+ }
+ else
+ {
+ status = JNI_ERR;
+ }
+
+ unlock:
+ _svmm_mutex_unlock ();
+
+ if (status != JNI_OK)
+ {
+ goto end;
+ }
+ }
+
+ new_env->thread.pthread = pthread_self ();
+ _svmf_set_current_env (new_env);
+
+ if (_svmm_gzalloc_native_ref_no_exception (new_env->native_locals.list) !=
+ JNI_OK)
+ {
+ /* we should be cleaning up! todo ... */
+ 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 ... */
+ goto end;
+ }
+
+ if (_svmm_gzalloc_native_ref_no_exception
+ (new_env->native_locals.list->next) != JNI_OK)
+ {
+ /* we should be cleaning up! todo ... */
+ goto end;
+ }
+ new_env->contention.requester.jobject =
+ _svmf_cast_jobject_nref (new_env->native_locals.list->next);
+
+ if (_svmf_stack_init (new_env) != JNI_OK)
+ {
+ /* we should be cleaning up! todo ... */
+ goto end;
+ }
+
+ new_env->is_alive = JNI_TRUE;
+
+ *penv = new_env;
+ return JNI_OK;
+
+end:
return JNI_ERR;
}
@@ -505,9 +635,55 @@
*/
JNIEXPORT static jint JNICALL
-DetachCurrentThread (JavaVM *vm SVM_UNUSED)
+DetachCurrentThread (JavaVM *_vm)
{
- _svmm_fatal_error ("todo");
+ _svmt_JNIEnv *env;
+ _svmt_JavaVM *vm = (_svmt_JavaVM *) (void *) _vm;
+
+ env = _svmf_get_current_env();
+ /* make sure this thread attached to a vm */
+ if ( env == NULL || !env->vm || env->vm != vm )
+ {
+ goto error;
+ }
+
+ _svmm_mutex_lock (vm->global_mutex);
+
+ _svmf_halt_if_requested (env);
+
+ env->is_alive = JNI_FALSE;
+ _svmf_set_current_env( NULL );
+
+ if (env->previous != NULL)
+ {
+ env->previous->next = env->next;
+ }
+ else
+ {
+ if (env->thread.is_daemon)
+ {
+ vm->threads.system = env->next;
+ }
+ else
+ {
+ vm->threads.user = env->next;
+ }
+ }
+
+ if (env->next != NULL)
+ {
+ env->next->previous = env->previous;
+ }
+
+ _svmm_cond_signal (vm->threads.vm_destruction_cond);
+
+ /* leak it for now... */
+
+ _svmm_mutex_unlock ();
+
+ return JNI_OK;
+
+error:
return JNI_ERR;
}