thread.c
来自「基于LWVCL开发的库」· C语言 代码 · 共 793 行 · 第 1/2 页
C
793 行
vmtid, name, prio, true); unhand(vmtid)->thread = tid; unhand(vmtid)->running = true; do_execute_java_class_method (&retval, "java/lang/ClassLoader", NULL, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); unhand(tid)->contextClassLoader = (struct Hjava_lang_ClassLoader *) retval.l; specialArgument[0] = func; specialArgument[1] = arg; specialArgument[2] = KTHREAD(current)(); nativeTid = KTHREAD(create)((unhand(tid)->priority), startSpecialThread, true, specialArgument, stacksize); if (nativeTid == NULL) { postOutOfMemory(einfo); return NULL; } KTHREAD(get_data)(nativeTid)->exceptPtr = NULL; KTHREAD(get_data)(nativeTid)->exceptObj = NULL; do { r = KSEM(get)(&THREAD_DATA()->sem, (jlong)0); } while (!r); linkNativeAndJavaThread (nativeTid, vmtid); KSEM(put)(&KTHREAD(get_data)(nativeTid)->sem); return (tid);}/* * All threads start here. */staticvoidfirstStartThread(void* arg){ Hjava_lang_VMThread* tid; jthread_t cur; JNIEnv *env; jmethodID runmethod; jthread_t calling_thread = (jthread_t) arg; threadData *thread_data; int r; cur = KTHREAD(current)(); thread_data = KTHREAD(get_data)(cur); KSEM(init)(&thread_data->sem); /* We acknowledge the parent thread that this thread has been started. */ KSEM(put)(&KTHREAD(get_data)(calling_thread)->sem); /* Now we must wait the parent to link the thread to the Java VM. */ do { r = KSEM(get)(&thread_data->sem, (jlong)0); } while (!r); tid = (Hjava_lang_VMThread *)(thread_data->jlThread); env = &thread_data->jniEnv;#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_THREAD_START) ) { JVMPI_Event ev; jvmpiFillThreadStart(&ev, tid); jvmpiPostEvent(&ev); jvmpiCleanupThreadStart(&ev); }#endifDBG(VMTHREAD, dprintf("%p (%p) firstStartThread\n", cur, 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); /* * We may ignore all exceptions here as it is already handled by VMThread.run(). */ (*env)->ExceptionClear(env); exitThread();}/* * Yield process to another thread of equal priority. */voidyieldThread(void){ KTHREAD(yield)();}/* * Change thread priority. * * We assume the call comes from VMThread and so that the field priority has * already been updated. In the other case, there will be a small inconsistency. */voidsetPriorityThread(Hjava_lang_VMThread* tid, jint prio){ /* no native thread yet */ if (unhand(tid)->vmdata == 0) return; KTHREAD(setpriority)((jthread_t)unhand(tid)->vmdata, prio);}/* * Terminate a thread. This function never returns. */voidexitThread(void){DBG(VMTHREAD, dprintf("%p (%p) exitThread\n", KTHREAD(current)(), THREAD_DATA()->jlThread); );#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 /* * This may never return. If it does return, control is returned to * the threading implementation where firstStartThread() is called. * * The threading implementation is responsible for calling * KaffeVM_unlinkNativeAndJavaThread() before killing or * reusing the thread. */ KTHREAD(exit)();}/* * Get the current JavaVM thread. */Hjava_lang_VMThread*getCurrentVMThread(void){ return (Hjava_lang_VMThread *) THREAD_DATA()->jlThread;}/* * Get the current Java thread. */Hjava_lang_Thread*getCurrentThread(void){ Hjava_lang_VMThread *vmtid; vmtid = getCurrentVMThread(); assert(vmtid != NULL); return unhand(vmtid)->thread;}/* * Finalize a thread. * This is to free the native thread context. */voidfinalizeThread(Hjava_lang_VMThread* tid){ jthread_t jtid = (jthread_t)unhand(tid)->vmdata; if (jtid != NULL) { KTHREAD(destroy)(jtid); }}/* * extract name of a thread as a C string. * Returns static buffer. */char *nameThread(Hjava_lang_VMThread *tid){ static char buf[80]; if (tid != NULL && unhand(tid)->thread != NULL && unhand(unhand(tid)->thread)->name != NULL) stringJava2CBuf(unhand(unhand(tid)->thread)->name, buf, sizeof(buf)); else strcpy(buf, "<null name>"); return buf;}static void broadcastDeath(void *jlThread){ Hjava_lang_VMThread *vmtid = (Hjava_lang_VMThread *)jlThread; Hjava_lang_Thread *tid = unhand(vmtid)->thread; /* Notify on the object just in case anyone is waiting */ lockMutex(&tid->base); broadcastCond(&tid->base); unlockMutex(&tid->base);}static voidthrowDeath(void){ throwException(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. */ KaffeVM_attachFakedThreadInstance("main", false); } 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, UNUSED void *p){DBG(VMTHREAD, Hjava_lang_VMThread *tid = (Hjava_lang_VMThread *)KTHREAD(get_data)(thread)->jlThread; dprintf("`%s' ", nameThread(tid)); KTHREAD(dumpthreadinfo)(thread); dprintf("\n"););}static voiddumpThreads(void){DBG(VMTHREAD, dprintf("Dumping live threads:\n"); KTHREAD(walkLiveThreads_r)(dumpJavaThread, NULL););}/* * Return the name of a java thread, given its native thread pointer. */char*nameNativeThread(void* native_data){ return nameThread((Hjava_lang_VMThread*) KTHREAD(get_data)((jthread_t)native_data)->jlThread);}/* * Invoked when threading system detects a deadlock. */static voidonDeadlock(void){ if (!deadlockDetection) { return; }#if defined(JTHREAD_RESTORE_FD) jthreadRestoreFD(2);#endif dumpLocks(); dumpThreads();DBG(VMTHREAD, dprintf("Deadlock: all threads blocked on internal events\n");); fflush(stderr); KAFFEVM_ABORT();}voidinitNativeThreads(int nativestacksize){ threadData *thread_data; rlim_t stackSize; 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; KTHREAD(init)( DBGEXPR(JTHREADNOPREEMPT, false, true), java_lang_Thread_MAX_PRIORITY+1, java_lang_Thread_MIN_PRIORITY, main_collector, broadcastDeath, throwDeath, onDeadlock); KTHREAD(atexit)(runfinalizer); /* * Doing KTHREAD(createfirst) as early as possible has several advantages: * * - we can rely on a working KTHREAD(current)() and KTHREAD(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. */#if defined(KAFFEMD_STACKSIZE) stackSize = mdGetStackSize(); if (stackSize == KAFFEMD_STACK_ERROR) { fprintf(stderr, "WARNING: Impossible to retrieve the real stack size\n"); fprintf(stderr, "WARNING: You may experience deadlocks\n"); } else if (stackSize == KAFFEMD_STACK_INFINITE || stackSize >= threadStackSize) {#ifndef KAFFEMD_DISABLE_SETSTACKSIZE mdSetStackSize(threadStackSize);#endif /* Last chance. We check whether the size has really been updated. */ stackSize = mdGetStackSize(); } else { fprintf(stderr, "NOTE: It is impossible to set the main thread stack\n" "NOTE: size because the system stack size is too low\n"); }#else stackSize = MAINSTACKSIZE;#endif DBG(INIT, dprintf("Detected stackSize %zu\n", (size_t)stackSize); ); KTHREAD(createfirst)((size_t)stackSize, (unsigned char)java_lang_Thread_NORM_PRIORITY, NULL); /* * initialize some things that are absolutely necessary: * - the semaphore * - the jniEnv */ thread_data = THREAD_DATA(); KSEM(init)(&thread_data->sem); thread_data->jnireferences = NULL; thread_data->jniEnv = &Kaffe_JNINativeInterface; DBG(INIT, dprintf("initNativeThreads(0x%x) done\n", nativestacksize); );}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?