⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 threads.c

📁 专业汽车级嵌入式操作系统OSEK的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "types.h"#include "trace.h"#include "platform_hooks.h"#include "constants.h"#include "specialsignatures.h"#include "specialclasses.h"#include "threads.h"#include "classes.h"#include "language.h"#include "configure.h"#include "interpreter.h"#include "memory.h"#include "exceptions.h"#include "stack.h"#define NO_OWNER 0x00#define get_stack_frame() ((StackFrame *) (currentThread->currentStackFrame))/** * Thread currently being executed by engine(). Threads exist in an * intrinsic circular list. */Thread* currentThread;/** * Priority queue of threads. Entry points at the last thread in the queue. */Thread *threadQ[10];/** * Thread id generator, always increasing. */byte gThreadCounter;/** * Current program number, i.e. number of 'main()'s hanging around */byte gProgramNumber;StackFrame *current_stackframe(){  byte arraySize;  arraySize = currentThread->stackFrameArraySize;  if (arraySize == 0)    return null;  return stackframe_array() + (arraySize - 1);}void update_stack_frame (StackFrame *stackFrame){  stackFrame->stackTop = stackTop;  stackFrame->pc = pc;}  void update_registers (StackFrame *stackFrame){  pc = stackFrame->pc;  stackTop = stackFrame->stackTop;  localsBase = stackFrame->localsBase;}/* Turns out inlines aren't really inlined.inline byte get_thread_id (Object *obj){  return obj->threadId;}inline void set_thread_id (Object *obj, byte threadId){  obj->threadId = threadId;}inline void inc_monitor_count (Object *obj){  obj->monitorCount++;}inline void set_monitor_count (Object *obj, byte count){  obj->monitorCount = count;}*/#define get_thread_id(obj) ((obj)->threadId)#define set_thread_id(obj,_threadId) ((obj)->threadId = (_threadId))#define inc_monitor_count(obj) ((obj)->monitorCount++)#define set_monitor_count(obj,count) ((obj)->monitorCount = (count))/** * Allocate stack frames * Allocate ID * Insert into run list * Mark thread as STARTED */boolean init_thread (Thread *thread){  thread->threadId = gThreadCounter + 1;    // Catch the primordial thread  if (currentThread == null)    thread->priority = NORM_PRIORITY;    #if DEBUG_THREADS  printf("Setting intial priority to %d\n", thread->priority);  #endif  if (thread->state != NEW)  {    throw_exception(illegalStateException);    return false;  }    // Allocate space for stack frames.  thread->stackFrameArray = ptr2word (new_primitive_array (T_STACKFRAME, INITIAL_STACK_FRAMES));  if (thread->stackFrameArray == JNULL)    return false;      // Allocate actual stack storage (INITIAL_STACK_SIZE * 4 bytes)  thread->stackArray = ptr2word (new_primitive_array (T_INT, INITIAL_STACK_SIZE));  if (thread->stackArray == JNULL)  {    free_array (ref2obj(thread->stackFrameArray));    thread->stackFrameArray = JNULL;    return false;      }    gThreadCounter++;    #ifdef VERIFY  assert (is_array (word2obj (thread->stackFrameArray)), THREADS0);  assert (is_array (word2obj (thread->stackArray)), THREADS1);  #endif  thread->stackFrameArraySize = 0;  thread->state = STARTED;  if (currentThread == null)    currentThread = thread;      enqueue_thread(thread);  return true;}/** * Switches to next thread: * * do *   get next thread *   if waiting, grab monitor and run *   if sleeping and timer expired, run *   if DEAD, clean up and use current thread *   if started, initialize and run * until selected thread can run *   * @return false iff there are no live threads *         to switch to. */ boolean switch_thread(){  Thread *anchorThread, *previousThread, *candidate;  Thread **pThreadQ;  boolean nonDaemonRunnable = false;  StackFrame *stackFrame = null;  short i;  #if DEBUG_THREADS || DEBUG_BYTECODE  printf ("------ switch_thread: currentThread at %d\n", (int) currentThread);  #endif  if (currentThread != null)  {    // Only current threads can die. Tidy up dead threads    if (currentThread->state == DEAD)    {      #if DEBUG_THREADS      printf ("Tidying up DEAD thread %d: %d\n", (int) currentThread, (int)currentThread->threadId);      #endif        #if REMOVE_DEAD_THREADS      // This order of deallocation is actually crucial to avoid leaks      free_array ((Object *) word2ptr (currentThread->stackArray));      free_array ((Object *) word2ptr (currentThread->stackFrameArray));      #ifdef SAFE      currentThread->stackFrameArray = JNULL;      currentThread->stackArray = JNULL;      #endif // SAFE      #endif // REMOVE_DEAD_THREADS          // Remove thread from queue.      dequeue_thread(currentThread);    }    else { // Save context information      stackFrame = current_stackframe();#if DEBUG_THREADS      printf ("switchThread: current stack frame: %d\n", (int) stackFrame);#endif        if (stackFrame != null) {        update_stack_frame (stackFrame);      }    }  }  currentThread = null;    // Loop until a frame is found that can be made to run.  for (i=MAX_PRIORITY-1; i >= 0; i--) {    pThreadQ = &threadQ[i];    previousThread = anchorThread = *pThreadQ;    if (!previousThread)      continue;    do    {      candidate = word2ptr(previousThread->nextThread);      #if DEBUG_THREADS      printf ("Checking state of thread %d(%d)(s=%d,p=%d,i=%d,d=%d)\n",      	(int)candidate,      	(int)candidate->threadId,      	(int)candidate->state,      	(int)candidate->priority,      	(int)candidate->interruptState,      	(int)candidate->daemon             );      #endif            // See if we can move a thread to the running state. Used to not do this if we      // had already found one, but turns out to be easiest if we are avoiding      // priority inversion.      switch (candidate->state)      {        case CONDVAR_WAITING:          // We are waiting to be notified          if ((candidate->sleepUntil > 0) && (get_sys_time() >= (FOURBYTES) candidate->sleepUntil))          {#if DEBUG_MONITOR      printf ("Waking up waiting thread %d: %d\n", (int) candidate, candidate->threadId);#endif            // We will drop through to mon waiting.          }          else if (candidate->interruptState == INTERRUPT_CLEARED)            break;          else            candidate->interruptState = INTERRUPT_GRANTED;          // candidate->state = MON_WAITING;          // drop through        case MON_WAITING:          {            Object *pObj = word2obj(candidate->waitingOn);            byte threadId = get_thread_id(pObj);            // We are waiting to enter a synchronized block            #ifdef VERIFY            assert (pObj != JNULL, THREADS6);            #endif                         if (threadId == NO_OWNER)            {              // NOW enter the monitor (guaranteed to succeed)              enter_monitor(candidate, pObj);                            // Set the monitor depth to whatever was saved.              set_monitor_count(pObj, candidate->monitorCount);                            // Let the thread run.              candidate->state = RUNNING;                #ifdef SAFE              candidate->waitingOn = JNULL;              #endif            }#if PI_AVOIDANCE            // Only avoid priority inversion if we don't already have a thread to run.            else if (currentThread == null)            {            	Thread *pOwner;            	int j;            	            	// Track down who owns this monitor and run them instead.            	            	// Could be 'waiting' in a native method, or we could be deadlocked!find_next:            	if (candidate->threadId != threadId)            	{                    for (j=MAX_PRIORITY-1; j >= 0; j--)                    {                      pOwner = threadQ[j];                      if (!pOwner)                        continue;                                              do {                        // Remember threadQ[j] is the last thread on the queue                        pOwner = word2ptr(pOwner->nextThread);                        if (pOwner->threadId == threadId)                        {            		      if (pOwner->state == RUNNING)            		      {            			    currentThread = pOwner;            			    goto done_pi;            			  }            			              		      // if owner is waiting too, iterate down.            		      if (pOwner->state == MON_WAITING)            		      {            			    threadId = get_thread_id(word2obj(pOwner->waitingOn));            			    if (threadId != NO_OWNER)            				  goto find_next;            		      }                        }                      } while (pOwner != threadQ[j]);                    }                                       // If we got here, we're in trouble, just drop through.            	}            }done_pi:		break;	    ;#endif // PI_AVOIDANCE                    }          break;        case SLEEPING:          if (candidate->interruptState != INTERRUPT_CLEARED              || (get_sys_time() >= (FOURBYTES) candidate->sleepUntil))          {      #if DEBUG_THREADS      printf ("Waking up sleeping thread %d: %d\n", (int) candidate, candidate->threadId);      #endif            candidate->state = RUNNING;            if (candidate->interruptState != INTERRUPT_CLEARED)          	candidate->interruptState = INTERRUPT_GRANTED;            #ifdef SAFE  	    candidate->sleepUntil = JNULL;            #endif // SAFE          }          break;        case STARTED:          if (currentThread == null)          {                  // Put stack ptr at the beginning of the stack so we can push arguments            // to entry methods. This assumes set_top_word or set_top_ref will            // be called immediately below.        #if DEBUG_THREADS        printf ("Starting thread %d: %d\n", (int) candidate, candidate->threadId);        #endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -