📄 thread.c
字号:
jthrowable eobj; int iLockRoot; cur = jthread_current(); ksemInit(&jthread_get_data(cur)->sem); lockStaticMutex(&thread_start_lock); unlockStaticMutex(&thread_start_lock); tid = jthread_get_data(cur)->jlThread; env = &jthread_get_data(cur)->jniEnv;#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_THREAD_START) ) { JVMPI_Event ev; jvmpiFillThreadStart(&ev, tid); jvmpiPostEvent(&ev); KFREE(ev.u.thread_start.parent_name); KFREE(ev.u.thread_start.group_name); KFREE(ev.u.thread_start.thread_name); }#endifDBG(VMTHREAD, dprintf("firstStartThread %p\n", tid); ) /* * We use JNI here to make sure the stack is unrolled when we get * into the uncaughtException handler. Otherwise, we wouldn't be * able to handle StackOverflowError. */ /* Find the run()V method and call it */ runmethod = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, tid), "run", "()V"); if (runmethod != 0) { (*env)->CallVoidMethod(env, tid, runmethod); /* note that since exception.c does not allow JNI to catch * ThreadDeath (for now!), we won't see ThreadDeath here. * That is, we must invoke the uncaughtException method * if we see an exception here. */ eobj = (*env)->ExceptionOccurred(env); (*env)->ExceptionClear(env); } else { /* eobj will usually be NoSuchMethodError */ eobj = (*env)->ExceptionOccurred(env); (*env)->ExceptionClear(env); } /* If all else fails we call the the uncaught exception method * on this thread's group. Note we must set a flag so we * don't do this again while in the handler. */ if (eobj != 0 && unhand(tid)->dying == false) { jobject group = unhand(tid)->group; jclass groupclass = (*env)->GetObjectClass(env, group); jmethodID uncaughtmeth = (*env)->GetMethodID(env, groupclass, "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V"); unhand(tid)->dying = true; (*env)->CallVoidMethod(env, group, uncaughtmeth, tid, eobj); /* exceptions thrown in `uncaughtException' are * silently ignored says the JLS. */ (*env)->ExceptionClear(env); } exitThread();}/* * Yield process to another thread of equal priority. */voidyieldThread(void){ jthread_yield();}/* * Change thread priority. */voidsetPriorityThread(Hjava_lang_Thread* tid, int prio){ unhand(tid)->priority = prio; /* no native thread yet */ if (unhand(tid)->PrivateInfo == 0) return; jthread_setpriority((jthread_t)unhand(tid)->PrivateInfo, prio);}/* * Terminate a thread. This function never returns. */voidexitThread(void){DBG(VMTHREAD, dprintf("exitThread %p\n", getCurrentThread()); )#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_THREAD_END) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_THREAD_END; jvmpiPostEvent(&ev); }#endif do_execute_java_method(getCurrentThread(), "finish", "()V", 0, 0); /* Destroy this thread's heavy lock */ unlinkNativeAndJavaThread(jthread_current()); /* This never returns */ jthread_exit();}#if 0/* * Put a thread to sleep. */voidsleepThread(jlong time){ if (time > 0) { jthread_sleep(time); }}/* * Is this thread alive? */boolaliveThread(Hjava_lang_Thread* tid){ bool status;DBG(VMTHREAD, dprintf("aliveThread: tid %p\n", tid); ) status = jthread_alive((jthread_t)unhand(tid)->PrivateInfo); return (status);}/* * How many stack frames have I invoked? */jintframesThread(Hjava_lang_Thread* tid){ return (jthread_frames((jthread_t)unhand(tid)->PrivateInfo));}#endif/* * Get the current Java thread. */Hjava_lang_Thread*getCurrentThread(void){ Hjava_lang_Thread* tid; tid = THREAD_DATA()->jlThread; assert(tid); return tid;}/* * Finalize a thread. * This is to free the native thread context. */voidfinalizeThread(Hjava_lang_Thread* tid){ jthread_t jtid = (jthread_t)unhand(tid)->PrivateInfo; if (jtid != NULL) { jthread_destroy(jtid); }}/* * extract name of a thread as a C string. * Returns static buffer. */char *nameThread(Hjava_lang_Thread *tid){ static char buf[80]; stringJava2CBuf(unhand(tid)->name, buf, sizeof(buf)); return buf;}static void broadcastDeath(void *jlThread){ Hjava_lang_Thread *tid = jlThread; int iLockRoot; /* Notify on the object just in case anyone is waiting */ lockMutex(&tid->base); broadcastCond(&tid->base); unlockMutex(&tid->base);}static void throwDeath(void){ Hjava_lang_Thread *cur = getCurrentThread(); Hjava_lang_Throwable *death = cur->death; cur->death = NULL; throwException(death ? death : ThreadDeath);}staticvoidrunfinalizer(void){ DBG (VMTHREAD, dprintf ("shutting down %p\n", THREAD_DATA()->jlThread); ) if (THREAD_DATA()->jlThread == 0) { /* if the thread executing the shutdown hooks doesn't have a * java.lang.Thread instance or it was gc'ed in the mean time, * create a new one. */ attachFakedThreadInstance("main"); } /* Do java-land cleanup */ do_execute_java_method(SystemClass, "exitJavaCleanup", "()V", NULL, true); if (runFinalizerOnExit) { invokeFinalizer(); }#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_JVM_SHUT_DOWN) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_JVM_SHUT_DOWN; jvmpiPostEvent(&ev); }#endif}/* * print info about a java thread. */static voiddumpJavaThread(jthread_t thread){ Hjava_lang_Thread *tid = jthread_get_data(thread)->jlThread; dprintf("`%s' ", nameThread(tid)); jthread_dumpthreadinfo(thread); dprintf("\n");}static voiddumpThreads(void){ dprintf("Dumping live threads:\n"); jthread_walkLiveThreads(dumpJavaThread);}/* * Return the name of a java thread, given its native thread pointer. */char*nameNativeThread(void* native){ return nameThread((Hjava_lang_Thread*) jthread_get_data((jthread_t)native)->jlThread);}/* * Invoked when threading system detects a deadlock. */static voidonDeadlock(void){ if (!deadlockDetection) { return; }#if defined(JTHREAD_RESTORE_FD) jthreadRestoreFD(2);#endif dumpLocks(); dumpThreads(); dprintf("Deadlock: all threads blocked on internal events\n"); fflush(stderr); ABORT();}voidinitNativeThreads(int nativestacksize){ threadData *thread_data; DBG(INIT, dprintf("initNativeThreads(0x%x)\n", nativestacksize); ) /* Even though the underlying operating or threading system could * probably extend the main thread's stack, we must impose this * artificial boundary, because otherwise we wouldn't be able to * catch stack overflow exceptions thrown by the main thread. */ threadStackSize = nativestacksize; jthread_init( DBGEXPR(JTHREADNOPREEMPT, false, true), java_lang_Thread_MAX_PRIORITY+1, java_lang_Thread_MIN_PRIORITY, thread_malloc, thread_free, thread_realloc, broadcastDeath, throwDeath, onDeadlock); jthread_atexit(runfinalizer); /* * Doing jthread_createfirst as early as possible has several advantages: * * - we can rely on a working jthread_current() and jthread_get_data() * everywhere else in the vm, no need to specialcase anything * * - catching exceptions during the initialisation is easier now * * Since everything is stored in the threadData struct now, we can simply * attach a faked java.lang.Thread instance later on. */ jthread_createfirst(MAINSTACKSIZE, java_lang_Thread_NORM_PRIORITY, 0); /* * initialize some things that are absolutely necessary: * - the semaphore * - the jniEnv */ thread_data = THREAD_DATA(); ksemInit(&thread_data->sem); thread_data->jniEnv = &Kaffe_JNINativeInterface; DBG(INIT, dprintf("initNativeThreads(0x%x) done\n", nativestacksize); )}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -