📄 thread.c
字号:
/* * Copyright (c) 1998-2002 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * * Use is subject to license terms. *//*========================================================================= * SYSTEM: KVM * SUBSYSTEM: Thread (concurrency) management * FILE: thread.c * OVERVIEW: This file defines the structures and operations * that are needed for Java-style multithreading. * AUTHOR: Antero Taivalsaari, Sun Labs * Edited by Doug Simon 11/1998 * Edited by Nik Shaylor 09/1999 to allow asynchronous I/O * Frank Yellin (new monitors), Bill Pittore (debugging) *=======================================================================*//*========================================================================= * COMMENTS: * Read the description of thread and monitor structures in thread.h *=======================================================================*//*========================================================================= * Local include files *=======================================================================*/#include "global.h"#include "execute.h"/*========================================================================= * Global variables needed for multitasking *=======================================================================*/THREAD CurrentThread; /* Current thread pointer */THREAD MainThread; /* Global so debugger code can create a name */THREAD AllThreads; /* List of all threads */THREAD RunnableThreads; /* Runnable thread list *//* NOTE: * RunnableThreads is a circular queue of threads. RunnableThreads * is either NULL or points to the >>last<< element of the list. * This makes it easier to add to either end of the list * */int AliveThreadCount; /* Number of alive threads in AllThreads. This count * does >>not<< include threads that haven't yet been * started */int Timeslice; /* Time slice counter for multitasking *//*========================================================================= * Static declarations needed for this file *=======================================================================*/#define QUEUE_ADDED TRUE#define QUEUE_REMOVED FALSE#if INCLUDEDEBUGCODEstatic voidTraceMonitor(THREAD thread, MONITOR monitor, THREAD *queue, bool_t added);static void TraceThread(THREAD thread, char *what);#endif/* Internal monitor operations */static void addMonitorWait(MONITOR monitor, THREAD thread);static void addCondvarWait(MONITOR monitor, THREAD thread);static void removeMonitorWait(MONITOR monitor);static void removeCondvarWait(MONITOR monitor, bool_t notifyAll);static void removePendingAlarm(THREAD thread);/* Internal queue manipulation operations */typedef enum { AT_START, AT_END } queueWhere;static void addThreadToQueue(THREAD *queue, THREAD, queueWhere where);static THREAD removeQueueStart(THREAD *queue);static bool_t removeFromQueue(THREAD *queue, THREAD waiter);static int queueLength(THREAD queue);static void monitorWaitAlarm(THREAD thread);/*========================================================================= * Global multitasking operations *=======================================================================*//*========================================================================= * FUNCTION: storeExecutionEnvironment() * loadExecutionEnvironment() * TYPE: private operations * OVERVIEW: These functions are used for storing and restoring * virtual machine registers upon task switching. * INTERFACE: * parameters: thread pointer * returns: <nothing> *=======================================================================*/void storeExecutionEnvironment(THREAD thisThread){ /* Save the current thread execution environment * (virtual machine registers) to the thread structure. */ thisThread->fpStore = getFP(); thisThread->spStore = getSP(); thisThread->ipStore = getIP();}void loadExecutionEnvironment(THREAD thisThread){ /* Restore the thread execution environment */ /* (VM registers) from the thread structure */ setFP(thisThread->fpStore); setLP(FRAMELOCALS(getFP())); setCP(getFP()->thisMethod->ofClass->constPool); setSP(thisThread->spStore); setIP(thisThread->ipStore);}/*========================================================================= * FUNCTION: SwitchThread() * TYPE: public global operations * OVERVIEW: Fundamental task switching operation: * switches to the next thread to be executed. * INTERFACE: * parameters: <none> * returns: Boolean showing if there is now a current thread * * NOTE: * * On entry to this routine there are three states the current thread * pointer can be in: * * CurrentThread == NIL * * There is no current thread because suspendThread() was called. * * CurrentThread != NIL && CurrentThread->state == THREAD_ACTIVE * * This is the normal case when the current thread's timeslice has * run out. * * CurrentThread != NIL && CurrentThread->state != THREAD_ACTIVE * * This is an atypical condition when suspendThread() was called * while we were in supervisor mode. In this case the routine * must spin until CurrentThread->state == THREAD_ACTIVE. * *=======================================================================*/bool_t SwitchThread(void){ THREAD threadToAdd = NIL; if (CurrentThread != NIL) {#if ASYNCHRONOUS_NATIVE_FUNCTIONS if (CurrentThread->pendingException != NIL) { fatalError(KVM_MSG_BAD_PENDING_EXCEPTION); }#endif if (CurrentThread->state == THREAD_ACTIVE) { /* If there is only one thread, or we can't switch threads then just return */ if (RunnableThreads == NULL) { /* Nothing else to run */ Timeslice = CurrentThread->timeslice; return TRUE; } else { /* Save the VM registers. Indicate that this thread is to */ /* to be added to the dormant thread queue */ storeExecutionEnvironment(CurrentThread); threadToAdd = CurrentThread; CurrentThread = NIL; } } else { fatalError(KVM_MSG_ATTEMPTING_TO_SWITCH_TO_INACTIVE_THREAD); } } /* Try and find a thread */ CurrentThread = removeQueueStart(&RunnableThreads); /* If there was a thread to add then do so */ if (threadToAdd != NIL) { addThreadToQueue(&RunnableThreads, threadToAdd, AT_END); } /* If nothing can run then return FALSE */ if (CurrentThread == NIL) { return FALSE; }#if ENABLEPROFILING ThreadSwitchCounter++;#endif /* Load the VM registers of the new thread */ loadExecutionEnvironment(CurrentThread);#if INCLUDEDEBUGCODE if (tracethreading) { /* Diagnostics */ TraceThread(CurrentThread, "Switching to this thread"); }#endif /* Load new time slice */ Timeslice = CurrentThread->timeslice;#if ASYNCHRONOUS_NATIVE_FUNCTIONS if (CurrentThread->pendingException != NIL) { char *pending = CurrentThread->pendingException; CurrentThread->pendingException = NIL; raiseException(pending); }#endif return TRUE;}/*========================================================================= * Public operations on thread instances *=======================================================================*//*========================================================================= * Constructors and destructors *=======================================================================*//*========================================================================= * FUNCTION: BuildThread() * TYPE: public global operation * OVERVIEW: Build a new VM-level thread by instantiating and * initializing the necessary structures. * INTERFACE: * returns: a new thread instance * NOTE: The created thread is an internal structure that does * not map one-to-one with Java class 'Thread.class'. * One-to-one mapping is implemented by structure * JAVATHREAD. *=======================================================================*/static THREAD BuildThread(JAVATHREAD_HANDLE javaThreadH){ THREAD newThread; JAVATHREAD javaThread; START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(THREAD, newThreadX, (THREAD)callocObject(SIZEOF_THREAD, GCT_THREAD)); STACK newStack = (STACK)callocObject(sizeof(struct stackStruct) / CELL, GCT_EXECSTACK); /* newStack->next = NULL; Already zero from calloc */ newStack->size = STACKCHUNKSIZE; newThreadX->stack = newStack;#if INCLUDEDEBUGCODE if (tracethreading) { TraceThread(newThreadX, "Created"); } if (tracestackchunks) { fprintf(stdout, "Created a new stack (thread: %lx, first chunk: %lx, chunk size: %ld\n", (long)newThreadX, (long)newStack, (long)STACKCHUNKSIZE); }#endif /* INCLUDEDEBUGCODE */ newThread = newThreadX; END_TEMPORARY_ROOTS /* Time slice will be initialized to default value */ newThread->timeslice = BASETIMESLICE; /* Link the THREAD to the JAVATHREAD */ javaThread = unhand(javaThreadH); newThread->javaThread = javaThread; javaThread->VMthread = newThread; /* Initialize the state */ newThread->state = THREAD_JUST_BORN;#if ENABLE_JAVA_DEBUGGER newThread->nextOpcode = NOP;#endif /* Add to the alive thread list */ newThread->nextAliveThread = AllThreads; AllThreads = newThread; return(newThread);}/*========================================================================= * FUNCTION: DismantleThread() * TYPE: public global operation * OVERVIEW: Free off the thread's resources * INTERFACE: * parameters: The thread pointer * returns: <none> *=======================================================================*/voidDismantleThread(THREAD thisThread){ START_TEMPORARY_ROOTS IS_TEMPORARY_ROOT(thisThread, thisThread);#if ENABLE_JAVA_DEBUGGER if (vmDebugReady) { CEModPtr cep; storeExecutionEnvironment(thisThread); cep = GetCEModifier(); cep->threadID = getObjectID((OBJECT)thisThread->javaThread); setEvent_ThreadDeath(cep); FreeCEModifier(cep); }#endif /* ENABLE_JAVA_DEBUGGER */ /* * A side effect of setevent is that the state could change, let's * hammer it home that this thread is DEAD */ thisThread->state = THREAD_DEAD; if (AllThreads == thisThread) { AllThreads = AllThreads->nextAliveThread; } else { THREAD prevThread = AllThreads; /* Remove from alive thread list */ while (prevThread->nextAliveThread != thisThread) { prevThread = prevThread->nextAliveThread; } prevThread->nextAliveThread = thisThread->nextAliveThread; } thisThread->nextAliveThread = NULL; thisThread->stack = NULL; thisThread->fpStore = NULL; thisThread->spStore = NULL; if (inTimerQueue(thisThread)) { removePendingAlarm(thisThread); } END_TEMPORARY_ROOTS}/*========================================================================= * FUNCTION: InitializeThreading() * TYPE: public global operation * OVERVIEW: Create the first low-level system thread and * initialize it properly. Initialize VM registers * accordingly. * INTERFACE: * parameters: method: The main(String[]) method to cal * arguments: String[] argument * returns: <nothing> *=======================================================================*/static voidinitInitialThreadBehaviorFromThread(FRAME_HANDLE);void InitializeThreading(INSTANCE_CLASS mainClass, ARRAY argumentsArg){ START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(ARRAY, arguments, argumentsArg); DECLARE_TEMPORARY_ROOT(JAVATHREAD, javaThread, (JAVATHREAD)instantiate(JavaLangThread)); makeGlobalRoot((cell **)&MainThread); MainThread = NULL; MonitorCache = NULL; makeGlobalRoot((cell **)&CurrentThread); makeGlobalRoot((cell **)&RunnableThreads); makeGlobalRoot((cell **)&TimerQueue); /* Initialize the field of the Java-level thread structure */ javaThread->priority = 5; MainThread = BuildThread(&javaThread); /* AllThreads is initialized to NULL by the garbage collector. * * Ensure that the thread list is properly initialized * and set mainThread as the active (CurrentThread) thread
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -