jvm.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,294 行 · 第 1/5 页
C
2,294 行
/* NOTE: First function called by child thread. *//* NOTE: Every Java thread (except the main thread) starts executing from here. */static void start_func(void *arg){ JNIEnv *env; jclass clazz; jmethodID methodID; CVMThreadStartInfo *info = (CVMThreadStartInfo *) arg; CVMExecEnv *ee = info->ee; CVMThreadICell *threadCell = info->threadICell; CVMThreadICell *eeThreadCell = NULL; CVMNativeRunInfo nativeInfo = {NULL, NULL}; CVMBool attachResult; /* Wait for parent if necessary */ CVMmutexLock(&info->parentLock); /* attach thread */ info->started = attachResult = CVMattachExecEnv(ee, CVM_FALSE); if (attachResult) { CVMaddThread(ee, !info->isDaemon); /* Store eetop */ { CVMJavaLong eetopVal = CVMvoidPtr2Long(ee); CVMID_fieldWriteLong(ee, threadCell, CVMoffsetOfjava_lang_Thread_eetop, eetopVal); } eeThreadCell = CVMcurrentThreadICell(ee); CVMID_icellAssign(ee, eeThreadCell, threadCell); if (info->nativeFunc != NULL) { nativeInfo.nativeFunc = info->nativeFunc; nativeInfo.nativeFuncArg = info->nativeFuncArg;#ifdef CVM_DEBUG_ASSERTS CVMassert(ee->nativeRunInfo == NULL); CVMassert(ee->nativeRunInfoType == NATIVERUNINFO_UNDEFINED); ee->nativeRunInfoType = NATIVERUNINFO_NATIVE_RUN_INFO;#endif ee->nativeRunInfo = (void *)&nativeInfo; } } CVMcondvarNotify(&info->parentCond); CVMthreadSetPriority(&ee->threadInfo, info->priority);#ifdef CVM_INSPECTOR ee->priority = info->priority;#endif CVMmutexUnlock(&info->parentLock); /* Parent frees info, child can no longer access it */#if defined(CVM_DEBUG) || defined(CVM_DEBUG_ASSERTS) info = NULL;#endif env = CVMexecEnv2JniEnv(ee); if (!attachResult) { goto failed; }#ifdef CVM_JVMTI if (CVMjvmtiIsEnabled()) { CVMjvmtiDebugEventsEnabled(ee) = CVM_TRUE; }#endif /* Should have startup() call this too... */ CVMpostThreadStartEvents(ee); clazz = CVMcbJavaInstance(CVMsystemClass(java_lang_Thread)); /* Call Thread.startup() */ methodID = (*env)->GetMethodID(env, clazz, "startup", "(Z)V"); CVMassert(methodID != NULL); (*env)->CallVoidMethod(env, eeThreadCell, methodID, nativeInfo.nativeFunc != NULL); CVMassert(!(*env)->ExceptionCheck(env)); CVMdetachExecEnv(ee); CVMremoveThread(ee, ee->userThread); failed: if (attachResult) { CVMdestroyExecEnv(ee); free(ee); } else { /* parent will free */ } /* * Thread is effectively dead from the VM's point of view, so * no VM data structures can be accessed after this point. */}/* Purpose: Native implementation of java.lang.Thread.runNative(). *//* NOTE: Called from child thread. */JNIEXPORT void JNICALLJVM_RunNativeThread(JNIEnv *env, jobject thisObj){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); CVMNativeRunInfo *info = (CVMNativeRunInfo *)ee->nativeRunInfo; void *arg = info->nativeFuncArg; void (*nativeFunc)(void *) = info->nativeFunc;#ifdef CVM_DEBUG_ASSERTS CVMassert(ee->nativeRunInfoType == NATIVERUNINFO_NATIVE_RUN_INFO); ee->nativeRunInfoType = NATIVERUNINFO_UNDEFINED;#endif ee->nativeRunInfo = NULL; CVMframeSetContextArtificial(ee); (*nativeFunc)(arg);}/* Purpose: Native implementation of java.lang.Thread.start0(). *//* NOTE: Called from parent thread. */JNIEXPORT void JNICALLJVM_StartThread(JNIEnv *env, jobject thisObj, jint priority){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); CVMExecEnv *targetEE = NULL; CVMThreadStartInfo *info = (CVMThreadStartInfo*)ee->nativeRunInfo; CVMThreadICell *threadICell = CVMID_getGlobalRoot(ee); const char *msg = NULL;#ifdef CVM_DEBUG_ASSERTS if (info != NULL) { /* This function will take control of it now. Clear it in the thread so that no one else can access it: */ CVMassert(ee->nativeRunInfoType == NATIVERUNINFO_THREAD_START_INFO); ee->nativeRunInfoType = NATIVERUNINFO_UNDEFINED; } else { CVMassert(ee->nativeRunInfoType == NATIVERUNINFO_UNDEFINED); }#endif /* NOTE: This function is the native implementation of Thread.start0() and it will be called every time Thread.start() is called. We need to reset the ee->nativeRunInfo here because we'll free its content when we free(info) below. If we don't, the next time Thread.start() is called, it will mistakenly think there is already a CVMThreadStartInfo record available for its use when there is not. */ ee->nativeRunInfo = NULL; if (threadICell == NULL) {#ifdef CVM_DEBUG msg = "no global roots";#endif goto out_of_memory; } if (info == NULL) { /* Normal thread */ info = (CVMThreadStartInfo *)malloc(sizeof(CVMThreadStartInfo)); if (info == NULL) {#ifdef CVM_DEBUG msg = "malloc failed";#endif goto out_of_memory; } info->nativeFunc = NULL; info->nativeFuncArg = NULL; info->started = 0; } if (!CVMmutexInit(&info->parentLock)) {#ifdef CVM_DEBUG msg = "CVMmutexInit failed";#endif goto out_of_memory; } if (!CVMcondvarInit(&info->parentCond, &info->parentLock)) {#ifdef CVM_DEBUG msg = "CVMcondvarInit failed";#endif goto out_of_memory1; } info->threadICell = threadICell; targetEE = (CVMExecEnv *)calloc(1, sizeof *targetEE); if (targetEE == NULL) {#ifdef CVM_DEBUG msg = "calloc failed";#endif goto out_of_memory2; } CVMID_icellAssign(ee, threadICell, thisObj); CVMID_fieldReadInt(ee, threadICell, CVMoffsetOfjava_lang_Thread_daemon, info->isDaemon); CVMassert(info->nativeFunc == NULL || info->isDaemon); { CVMBool success;#ifdef CVM_LVM /* %begin lvm */ if (!CVMLVMeeInitAuxInit(ee, &info->lvmEEInitAux)) {#ifdef CVM_DEBUG msg = "CVMLVMeeInitAuxInit failed";#endif goto out_of_memory2; }#endif /* %end lvm */ success = CVMinitExecEnv(ee, targetEE, info);#ifdef CVM_LVM /* %begin lvm */ CVMLVMeeInitAuxDestroy(ee, &info->lvmEEInitAux);#endif /* %end lvm */ if (!success) {#ifdef CVM_DEBUG msg = "CVMinitExecEnv failed";#endif free(targetEE); /* CVMdestroyExecEnv already called */ targetEE = NULL; goto out_of_memory2; } }#ifdef CVM_JVMTI if (info->nativeFunc == NULL) { /* "Normal" thread vs. system thread */ /* NOTE: First pass JVMTI support has only one global environment */ /* targetEE->_jvmti_env = ee->_jvmti_env; */ }#endif info->ee = targetEE; CVMmutexLock(&info->parentLock); info->priority = priority; CVMID_fieldReadInt(ee, CVMcurrentThreadICell(ee), CVMoffsetOfjava_lang_Thread_priority, priority); { CVMBool success = CVMthreadCreate(&targetEE->threadInfo, CVMglobals.config.nativeStackSize, priority, start_func, info); if (!success) {#ifdef CVM_DEBUG msg = "CVMthreadCreate failed";#endif CVMmutexUnlock(&info->parentLock); goto out_of_memory2; } } info->started = -1; { /* CVM.maskInterrupts() in Thread.start() should prevent this */ CVMassert(!CVMthreadIsInterrupted(CVMexecEnv2threadID(ee), CVM_TRUE)); while (info->started == -1) { if (!CVMcondvarWait(&info->parentCond, &info->parentLock, CVMlongConstZero())) { /* Java locking should prevent further interrupts */ CVMassert(CVM_FALSE); } } } CVMmutexUnlock(&info->parentLock);#ifdef CVM_JVMTI CVMtimeThreadCpuClockInit(&targetEE->threadInfo);#endif /* In case we want to see where threads are created CVMdumpStack(&ee->interpreterStack, 0, 0, 0); */ if (!info->started) {#ifdef CVM_DEBUG msg = "child init failed";#endif } out_of_memory2: CVMcondvarDestroy(&info->parentCond); out_of_memory1: CVMmutexDestroy(&info->parentLock); out_of_memory: if (threadICell != NULL) { CVMID_freeGlobalRoot(ee, threadICell); } if (info == NULL || !info->started) { if (targetEE != NULL) { CVMdestroyExecEnv(targetEE); free(targetEE); } CVMthrowOutOfMemoryError(ee, msg); } if (info != NULL) { free(info); }}/* Purpose: Starts a system thread. *//* NOTE: Called from parent thread. */voidJVM_StartSystemThread(JNIEnv *env, jobject thisObj, void(*nativeFunc)(void *), void* nativeFuncArg){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); CVMThreadStartInfo *info = (CVMThreadStartInfo *)malloc(sizeof(CVMThreadStartInfo)); info->nativeFunc = nativeFunc; info->nativeFuncArg = nativeFuncArg;#ifdef CVM_DEBUG_ASSERTS CVMassert(ee->nativeRunInfo == NULL); CVMassert(ee->nativeRunInfoType == NATIVERUNINFO_UNDEFINED); ee->nativeRunInfoType = NATIVERUNINFO_THREAD_START_INFO;#endif ee->nativeRunInfo = info; { /* Call Thread.start() */ jclass clazz = CVMcbJavaInstance(CVMsystemClass(java_lang_Thread)); jmethodID methodID = (*env)->GetMethodID(env, clazz, "start", "()V"); CVMassert(methodID != NULL); (*env)->CallNonvirtualVoidMethod(env, thisObj, clazz, methodID); }#ifdef CVM_DEBUG_ASSERTS /* We expect java.lang.Thread.start0() will have freed this up already: */ CVMassert(ee->nativeRunInfoType == NATIVERUNINFO_UNDEFINED); CVMassert(ee->nativeRunInfo == NULL);#endif}#if defined(CVM_HAVE_DEPRECATED) || defined(CVM_THREAD_SUSPENSION)#ifdef JAVASEJNIEXPORT void JNICALLJVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable){ CVMconsolePrintf("unimplemented function JVM_StopThread called!");}#endifJNIEXPORT void JNICALLJVM_SuspendThread(JNIEnv *env, jobject thread){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); CVMThreadICell *thisThreadCell; CVMExecEnv *targetEE; CVMJavaLong eetopVal; CVMBool isSelf; if (!CVMglobals.suspendCheckerInitialized) { CVMsuspendCheckerInit(); CVMglobals.suspendCheckerInitialized = JNI_TRUE; } thisThreadCell = CVMcurrentThreadICell(ee); CVMID_icellSameObject(ee, thisThreadCell, thread, isSelf); if (!isSelf) { CVMlocksForThreadSuspendAcquire(ee); CVMID_fieldReadLong(ee, thread, CVMoffsetOfjava_lang_Thread_eetop, eetopVal); targetEE = (CVMExecEnv *)CVMlong2VoidPtr(eetopVal); if (targetEE != NULL) { CVMBool success = CVM_FALSE; CVMthreadSuspendConsistentRequest(ee); CVMsysMicroLockAll(ee); while (!success) { /* Suspend the target: */ targetEE->threadState |= CVM_THREAD_SUSPENDED; CVMthreadSuspend(&targetEE->threadInfo); /* Check to see if the target is holding any ciritcal native locks while suspended: */ success = CVMsuspendCheckerIsOK(ee, targetEE); if (!success) { /* If we get here, then the target thread is holding some critical lock. Resume the thread, back-off for a while and try suspending again a bit later: */ CVMthreadResume(&targetEE->threadInfo); targetEE->threadState &= ~CVM_THREAD_SUSPENDED; /* Now sleep for a while to back off before trying to suspend the target thread again: */ { CVMSysMonitor mon; if (CVMsysMonitorInit(&mon, NULL, 0)) { jlong millis; /* Sleep for a random amount of non-zero time: sleepTime = (CVMtimeMillis() & 0xff) + 1; */ millis = CVMtimeMillis(); millis = CVMlongAnd(millis, CVMint2Long(0xff)); millis = CVMlongAdd(millis, CVMlongConstOne()); CVMsysMonitorEnter(ee, &mon); CVMsysMonitorWait(ee, &mon, millis); CVMsysMonitorExit(ee, &mon); CVMsysMonitorDestroy(&mon); } else { CVMthreadYield(); } } } } CVMsysMicroUnlockAll(ee); CVMthreadSuspendConsistentRelease(ee); } CVMlocksForThreadSuspendRelease(ee); } else { /* %comment: rt034 */ ee->threadState |= CVM_THREAD_SUSPENDED; CVMthreadSuspend(&ee->threadInfo); }}JNIEXPORT void JNICALLJVM_ResumeThread(JNIEnv *env, jobject thread){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); CVMExecEnv *targetEE; CVMJavaLong eetopVal; CVMsysMutexLock(ee, &CVMglobals.threadLock); CVMID_fieldReadLong(ee, thread, CVMoffsetOfjava_lang_Thread_eetop, eetopVal); targetEE = (CVMExecEnv *)CVMlong2VoidPtr(eetopVal); if (targetEE != NULL) { if (targetEE->threadState & CVM_THREAD_SUSPENDED) { CVMassert(targetEE != ee); CVMthreadResume(&targetEE->threadInfo); targetEE->threadState &= ~CVM_THREAD_SUSPENDED; } } CVMsysMutexUnlock(ee, &CVMglobals.threadLock);}#endif /* CVM_HAVE_DEPRECATED || CVM_THREAD_SUSPENSION *//* We want to rely on priorities as set/got via the threadX functions. * However, it is legal to call setPriority() and getPriority() after * 'new' and before start() is called, in which case the thread's TID has * been allocated but its thread not yet creat
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?