📄 thread.c
字号:
*/ MainThread->nextThread = NIL; AliveThreadCount = 1; Timeslice = BASETIMESLICE; MainThread->state = THREAD_ACTIVE; /* Initialize VM registers */ CurrentThread = MainThread; RunnableThreads = NULL; TimerQueue = NULL; setSP((MainThread->stack->cells - 1)); setFP(NULL); setIP(KILLTHREAD); /* We can't create a frame consisting of "method", since its class * has not yet been initialized, (and this would mess up the * garbage collector). So we set up a pseudo-frame, and arrange * for the interpreter to do the work for us. */ pushFrame(RunCustomCodeMethod); pushStackAsType(CustomCodeCallbackFunction, initInitialThreadBehaviorFromThread); /* We want to push method, but that would confuse the GC, since * method is a pointer into the middle of a heap object. Only * heap objects, and things that are clearly not on the heap, can * be pushed onto the stack. */ pushStackAsType(INSTANCE_CLASS, mainClass); pushStackAsType(ARRAY, arguments); initializeClass(mainClass); END_TEMPORARY_ROOTS}static voidinitInitialThreadBehaviorFromThread(FRAME_HANDLE exceptionFrameH) { INSTANCE_CLASS thisClass; METHOD thisMethod; if (exceptionFrameH != NULL) { /* We have no interest in dealing with exceptions. */ return; } thisClass = secondStackAsType(INSTANCE_CLASS); thisMethod = getSpecialMethod(thisClass, mainNameAndType); if (thisMethod == NULL) { AlertUser(KVM_MSG_CLASS_DOES_NOT_HAVE_MAIN_FUNCTION); stopThread(); } else if ((thisMethod->accessFlags & ACC_PUBLIC) == 0) { AlertUser(KVM_MSG_MAIN_FUNCTION_MUST_BE_PUBLIC); stopThread(); } else { START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(ARRAY, arguments, topStackAsType(ARRAY)); /* Reinitialize the thread for the new method */ setSP((CurrentThread->stack->cells - 1) + thisMethod->argCount); setFP(NULL); setIP(KILLTHREAD); pushFrame(thisMethod); ((ARRAY *)getLP())[0] = arguments; END_TEMPORARY_ROOTS if (thisMethod->accessFlags & ACC_SYNCHRONIZED) { getFP()->syncObject = (OBJECT)thisClass; monitorEnter((OBJECT)thisClass); } else { getFP()->syncObject = NULL; } }}/*========================================================================= * FUNCTION: getVMthread() * TYPE: public auxiliary operation * OVERVIEW: Given a Java-level thread, ensure that the internal * VM-level thread structure has been created. * INTERFACE: * parameters: JAVATHREAD pointer * returns: THREAD pointer *=======================================================================*/THREAD getVMthread(JAVATHREAD_HANDLE javaThreadH){ /* Create the VM-level thread structure if necessary */ THREAD VMthread = unhand(javaThreadH)->VMthread; if (!VMthread) { VMthread = BuildThread(javaThreadH); } return VMthread;}/*========================================================================= * Thread activation and deactivation operations *=======================================================================*//*========================================================================= * FUNCTION: initThreadBehavior() * TYPE: public instance-level operation * OVERVIEW: Set the behavior of a thread without the context of * a current execution stack (i.e. don't use sp). * INTERFACE: * parameters: thread pointer, pointer to a method object and the sync * object that will be used if this is a synchronized method. * returns: <nothing> * NOTE: You have to explicitly construct the local stack of * this thread after returning from this call. Don't * forget that 'this' must be the first local is this * thisMethod is virtual. * There are no safety checks here, so do not activate * the same thread twice. *=======================================================================*/static voidinitThreadBehaviorFromThread(FRAME_HANDLE);void initThreadBehavior(THREAD thisThread, METHOD thisMethod, OBJECT syncObject){ /* Note, thisThread == CurrentThread when booting. This code below is * slightly inefficient, but it's not worth the hassle of fixing for * a one-time case. */ THREAD current = CurrentThread; if (current != NULL) { storeExecutionEnvironment(current); } CurrentThread = thisThread; setSP((thisThread->stack->cells - 1) + thisMethod->argCount); setFP(NULL); setIP(KILLTHREAD); pushFrame(thisMethod); if (thisMethod->accessFlags & ACC_SYNCHRONIZED) { getFP()->syncObject = syncObject; pushFrame(RunCustomCodeMethod); pushStackAsType(CustomCodeCallbackFunction, initThreadBehaviorFromThread); } else { getFP()->syncObject = NULL; } storeExecutionEnvironment(thisThread); if (current) { loadExecutionEnvironment(current); } CurrentThread = current;}/*========================================================================= * FUNCTION: initThreadBehaviorFromThread() * TYPE: private initialization of a class * OVERVIEW: This function performs any thread initialization that can * only be performed by the thread on itself after it has * begun running, and not by whoever created the threads. * * Notes: This is a "CustomCode" callback function. * * Currently, it only handles the method being synchronized, * and needing to enter the monitor. It may be extended to * do more. * * INTERFACE: * parameters: exceptionFrameH: NULL if called from the interpreter. * A pointer to the current exception if called from * the error handler. * We can either set the pointer to NULL to indicate we've * completely handled it, or we can replace it with a * different exception. * * returns: <nothing> * *=======================================================================*/static voidinitThreadBehaviorFromThread(FRAME_HANDLE exceptionFrameH) { if (exceptionFrameH == NULL) { popFrame(); if (getFP()->syncObject) { monitorEnter(getFP()->syncObject); } } else { /* We have no interest in dealing with exceptions */ }}/*========================================================================= * FUNCTION: startThread() * TYPE: public instance-level operation * OVERVIEW: Make a thread alive, but suspended. * INTERFACE: * parameters: thread pointer * returns: <nothing> * NOTE: There are no safety checks here, so please * do not activate the same thread twice. *=======================================================================*/void startThread(THREAD thisThread){#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(thisThread, "Starting"); }#endif /* Add one to the count of alive Java threads */ thisThread->state = THREAD_SUSPENDED; AliveThreadCount++;#if ENABLE_JAVA_DEBUGGER START_TEMPORARY_ROOTS IS_TEMPORARY_ROOT(thisThread, thisThread); if (vmDebugReady) { CEModPtr cep = GetCEModifier(); cep->threadID = getObjectID((OBJECT)thisThread->javaThread); cep->eventKind = JDWP_EventKind_THREAD_START; insertDebugEvent(cep); } END_TEMPORARY_ROOTS#endif /* ENABLE_JAVA_DEBUGGER */}/*========================================================================= * FUNCTION: stopThread() * TYPE: public instance-level operation * OVERVIEW: Stop a thread and free its resources * INTERFACE: * parameters: thread pointer * returns: <nothing> * NOTE: There are no safety checks here, so please * do not stopThread the same thread twice. *=======================================================================*/void stopThread(void){ THREAD thisThread = CurrentThread;#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(thisThread, "Stopping"); }#endif /* First suspend the thread */ suspendThread(); /* Always force the end of the current thread */ CurrentThread = NIL; /* Make the thread be no longer alive */ thisThread->state = THREAD_DEAD; AliveThreadCount--; /* Then kill it off */ DismantleThread(thisThread);}/*========================================================================= * FUNCTION: suspendThread() * TYPE: public instance-level operation * OVERVIEW: Suspend the currently executing thread. * INTERFACE: * parameters: <none> * returns: <nothing> * NOTE: When this function is used with an asynchronous * callback routine that calls resumeThread(), it * is vital that this routine is called *BEFORE* * the callback routine can execute. **NS** *=======================================================================*/void suspendThread(void){ if (CurrentThread == NULL) { /* This shouldn't happen, but don't crash */ return; }#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(CurrentThread, "Suspending"); }#endif if (!(CurrentThread->state & THREAD_SUSPENDED)) { /* Save the VM registers of the currently executing thread */ storeExecutionEnvironment(CurrentThread); /* Signal time to reschedule the interpreter */ signalTimeToReschedule(); } /* Set the flag to show that it is inactive */ CurrentThread->state |= THREAD_SUSPENDED;#if ENABLE_JAVA_DEBUGGER /* If we are running the debugger, we must send any pending events * that this thread knows about before we set CurrentThread to NIL. */ __checkDebugEvent();#endif /* Show that there is no current thread anymore */ CurrentThread = NIL;}#if ENABLE_JAVA_DEBUGGERvoid suspendSpecificThread(THREAD thread){ if (thread == NULL) { /* This shouldn't happen, but don't crash */ return; } if (thread == CurrentThread) { if (!(CurrentThread->state & THREAD_SUSPENDED)) { /* Save the VM registers of the currently executing thread */ storeExecutionEnvironment(CurrentThread); /* Signal time to reschedule the interpreter */ signalTimeToReschedule(); } /* Show that there is no current thread anymore */ /* Only do this if we are not in supervisor mode */ CurrentThread = NIL; } else { if (!(thread->state & (THREAD_SUSPENDED | THREAD_DEAD))) { removeFromQueue(&RunnableThreads, thread); } } thread->state |= THREAD_DBG_SUSPENDED; thread->debugSuspendCount++;}#endif /* ENABLE_JAVA_DEBUGGER *//*========================================================================= * FUNCTION: resumeThread() * TYPE: public instance-level operation * OVERVIEW: Resume a thread by placing it from the dormant * thread chain. * INTERFACE: * parameters: thread pointer * returns: <nothing> *=======================================================================*/void resumeThread(THREAD thisThread){#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(thisThread, "Resuming"); }#endif if (!(thisThread->state & THREAD_SUSPENDED)) { fatalError(KVM_MSG_ATTEMPTING_TO_RESUME_NONSUSPENDED_THREAD); }#if ENABLE_JAVA_DEBUGGER if (thisThread->state & THREAD_DBG_SUSPENDED) { thisThread->state &= ~THREAD_SUSPENDED; return; }#endif /* Set the flag to show that it is now active */ thisThread->state = THREAD_ACTIVE; /* Check if we are trying to restart CurrentThread * Normally this is an error, but if we are * spinning in supervisor mode it is normal */ if (thisThread == CurrentThread) { fatalError(KVM_MSG_ATTEMPTING_TO_RESUME_CURRENT_THREAD); /* We don't need to do anything else because SwitchThread will be * spinning on the thread state, so we just have to get out * of whatever sort of callback routine we are in, and it will then * be able to proceed */ } else { /* If the new thread has higher priority then */ /* add to head of the wait queue and signal that */ /* it is time to reschedule the processor */ addThreadToQueue(&RunnableThreads, thisThread, AT_END); }}#if ENABLE_JAVA_DEBUGGERvoid resumeSpecificThread(THREAD thisThread){ if (--thisThread->debugSuspendCount <= 0) { thisThread->state &= ~THREAD_DBG_SUSPENDED; thisThread->debugSuspendCount = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -