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 + -
显示快捷键?