schedLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:11k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* schedLib.c - internal VxWorks kernel scheduler library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02p,25mar02,kab  SPR 74651: PPC & SH can idle w/ work queued
  8. 02o,09nov01,dee  add CPU_FAMILY is/not COLDFIRE
  9. 02n,11oct01,cjj  removed Am29k support and removed #include asm.h
  10. 02m,07sep01,h_k  added _func_vxIdleLoopHook for power control support for the
  11.                  SH processors (SPR #69838).
  12. 02l,19apr01,jmp  fixed scheduling bug on SIMNT, workQDoWork() must be performed
  13.  after the simulator enter in idle mode, not before (SPR#64900).
  14. 02l,03mar00,zl   merged SH support into T2
  15. 02k,31mar98,cjtc exclude portable scheduler for I960
  16. 02j,22jan98,pr   replaced EVT_CTX_SCHED with EVT_CTX_IDLE. Cleanup.
  17. 02i,02jan98,jmb  name change for Win32 externals.
  18. 02h,27oct97,pr   replaced WV code with macros
  19.  added trgLibP.h
  20. 02g,21oct97,cym  added intUnlock() to the idle loop for SIMNT.
  21. 02f,18jul97,pr   replaced evtLogTIsOn with evtInstMode
  22. 02e,28nov96,cdp  added ARM support.
  23. 02d,30aug96,ism  added floating point save code for SIMSPARCSOLARIS
  24. 02c,23oct96,tam  added call to vxPowerDown() in the iddle loop for PowerPC. 
  25.  added #include of vxLib.h for PowerPC only.
  26. 02b,24jun96,sbs  made windview instrumentation conditionally compiled
  27. 02a,04nov94,yao  added PPC support.
  28. 01x,25jan96,ism  cleanup from vxsim
  29. 01w,03nov95,ism  vxsim solaris
  30. 01v,09mar94,caf  use PORTABLE version for R3000 (SPR #2523).
  31. 01u,09jun93,hdn  added a support for I80X86
  32. 01s,12may94,ms   fixed vxsim hppa version of reschedule to save errno.
  33. 01r,11aug93,gae  vxsim hppa.
  34. 01q,22jun93,gae  vxsim.
  35. 01v,09nov94,rdc  locked interrupts while calling _func_evtLogTSched.
  36. 01u,03jun94,smb  merged with VxWorks for SPARC (marc shepard's version of 
  37.  reschedule)
  38. 01t,19may94,pad  merged with VxWorks for Am29K.
  39.                  added evtLogTIsOn test.
  40.     pme  added Am29K family support and #include "asm.h"
  41.  added evetsched() prototype
  42. 01s,05may94,smb  WindView porting
  43. 01r,24jan94,smb  added instrumentation for priority inheritance
  44. 01q,10dec93,smb  added instrumentation for windview
  45. 01p,16mar93,jcf  removed NULL assignment of taskIdCurrent from while loop.
  46. 01o,06jul92,jwt  fixed reschedule() (wouldn't compile) for SPARC kernel.
  47. 01n,04jul92,jcf  private header files.
  48. 01m,04jun92,ajm  now uses global taskSrDefault instead of macro
  49. 01l,26may92,rrr  the tree shuffle
  50. 01k,22jan92,shl  fixed typo introduced in 01j.
  51. 01j,14jan92,jwt  merged 5.0.2b SPARC release; copyright message to 1992.
  52. 01i,15oct91,ajm  mips version is now optimized
  53. 01h,04oct91,rrr  passed through the ansification filter
  54.                   -changed functions to ansi style
  55.                   -fixed #else and #endif
  56.                   -changed VOID to void
  57.                   -changed copyright notice
  58. 01g,06Sep91,wmd  move line clearing kernelIsIdle.
  59. 01f,19aug91,ajm  imported kernelIsIdle for idle state consistency.
  60.                  made kernel idle loop always use default SR just as
  61.                  optimized version does.
  62. 01e,15feb91,jwt  passed taskIdCurrent as a parameter to reschedule().
  63.            +hvh  set/cleared kernelIsIdle flag in reschedule().
  64. 01d,29aug90,jcf  documentation.
  65. 01c,26jun90,jcf  fixed up, fixed up PORTABLE version.
  66. 01b,11may90,jcf  fixed up PORTABLE definition.
  67. 01a,17jun89,jcf  written.
  68. */
  69. /*
  70. DESCRIPTION
  71. The VxWorks kernel provides tasking control services to an application.  The
  72. libraries kernelLib, taskLib, semLib, tickLib, and wdLib comprise the kernel
  73. functionality.  This library is internal to the VxWorks kernel and contains
  74. no user callable routines.
  75. INTERNAL
  76. This module contains the portable version of the rescheduler of the VxWorks
  77. kernel.  An optimized version is desirable and usually found in windALib.
  78. At the time reschedule() is called, taskIdCurrent must contain the current
  79. executing task.  That task's context has been saved as part of the execution of
  80. windExit().  Execution continues to be in kernel space so mutual exclusion to
  81. all queues is guaranteed.
  82. We must simply make taskIdCurrent equal to whatever task is first in the ready
  83. queue and load its context.  But nothing is simple.  The first complicating
  84. factor is we must call the switch and swap hooks, if any.  Also, we must
  85. remember to empty the kernel work queue before loading the context of the new
  86. taskIdCurrent.  The testing of more work to do and the loading of the context
  87. must be executed with interrupts locked out.  Otherwise interrupt service
  88. routines may add work that gets forgotten.  An optimized version of this
  89. routine should load as much of the context as possible before locking
  90. interrupts, thus reducing interrupt latency.
  91. Finally we consider the case of going idle, which will occur when the
  92. ready queue is empty.  In such a case we loop waiting for work to be added
  93. to the work queue, because an ISR waking some task up is the only way the
  94. machine can stop idling.
  95. .CS
  96. windview INSTRUMENTATION
  97. -------------------------
  98.  level 3 events
  99. EVENT_WIND_EXIT_DISPATCH
  100. EVENT_WIND_EXIT_NODISPATCH
  101. EVENT_WIND_EXIT_DISPATCH_PI
  102. EVENT_WIND_EXIT_NODISPATCH_PI
  103. EVENT_WIND_EXIT_IDLE
  104. .CE
  105. SEE ALSO: "Basic OS", windALib
  106. NOMANUAL
  107. */
  108. #include "vxWorks.h"
  109. #include "taskLib.h"
  110. #include "private/workQLibP.h"
  111. #include "private/windLibP.h"
  112. #include "private/taskLibP.h"
  113. #include "private/funcBindP.h"
  114. #include "private/trgLibP.h"
  115. #include "intLib.h"
  116. #include "errno.h"
  117. #if     (CPU_FAMILY == PPC) || (CPU_FAMILY == SH)
  118. #include "vxLib.h"
  119. #endif  /* (CPU_FAMILY == PPC) */
  120. IMPORT ULONG taskSrDefault;
  121. IMPORT Q_HEAD readyQHead;
  122. IMPORT void windLoadContext (void);
  123. #if (CPU_FAMILY == SIMNT)
  124. #include "win_Lib.h"
  125. IMPORT  WIN_HANDLE simIntIdleSem;
  126. #endif
  127. #if     (CPU_FAMILY == PPC)
  128. IMPORT  _RType  taskMsrDefault;
  129. #endif  /* (CPU_FAMILY == PPC) */
  130. /* optimized version available for 680X0, MIPS, I80X86, and SH */
  131. #if (defined(PORTABLE) || ((CPU_FAMILY != MC680X0) && (CPU_FAMILY != MIPS) && 
  132. (CPU_FAMILY != I80X86) && (CPU_FAMILY != ARM) && 
  133. (CPU_FAMILY != COLDFIRE) && 
  134. (CPU_FAMILY != I960) && (CPU_FAMILY != SH)))
  135. #define schedLib_PORTABLE
  136. #endif
  137. #ifdef schedLib_PORTABLE
  138. /*******************************************************************************
  139. *
  140. * reschedule - portable version of the scheduler
  141. *
  142. * This routine determines the appropriate task to execute, then calls any
  143. * switch and swap hooks, then loads its context.  The complicating factor
  144. * is that the kernel work queue must be checked before leaving.  In the
  145. * portable version the checking of the work queue and the loading of the
  146. * task's context is done at interrupt lock out level to avoid races with
  147. * ISRs.  An optimized version ought to load as much of the context as is
  148. * possible before locking interrupts and checking the work queue.  This will
  149. * reduce interrupt latency considerably.
  150. *
  151. * If no task is ready, the machine will idle looking for more work in the
  152. * work queue.  The idle state is not in a task context and therefore
  153. * no switch or swap hooks are called when the machine goes idle.  Upon leaving
  154. * the idle state, switch and swap hooks will be called if the new task is
  155. * different than the task that was executing when the machine went idle.
  156. *
  157. * NOMANUAL
  158. */
  159. void reschedule (void)
  160.     {
  161.     FAST WIND_TCB *taskIdPrevious;
  162.     FAST int       ix;
  163.     FAST UINT16    mask;
  164.     int    oldLevel;
  165. unlucky:
  166.     taskIdPrevious = taskIdCurrent; /* remember old task */
  167.     workQDoWork (); /* execute all queued work */
  168.     /* idle here until someone is ready to execute */
  169.     kernelIsIdle = TRUE;                        /* idle flag for spy */
  170.     /* windview conditions */
  171. #ifdef WV_INSTRUMENTATION
  172.     EVT_CTX_IDLE(EVENT_WIND_EXIT_IDLE, &readyQHead);
  173. #endif
  174.     while (((WIND_TCB *) Q_FIRST (&readyQHead)) == NULL)
  175.         {
  176. #if CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA
  177. {
  178. int mask=0;
  179.         taskIdCurrent->errorStatus = errno;
  180. u_sigsuspend (&mask);
  181.         errno = taskIdCurrent->errorStatus;
  182. }
  183. #endif /* CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA */
  184. #if CPU_FAMILY==SIMSPARCSOLARIS
  185. {
  186. int mask[4]={0, 0, 0, 0};
  187. extern void u_sigsuspend ();
  188. extern WIND_TCB *pTaskLastFpTcb;
  189. extern void fppSave();
  190. /*
  191.  * u_sigsuspend() hoses the fpp registers, so save them now if they
  192.  * are active.  Then set the Last FP TCB to NULL, so we won't try to
  193.  * save them again.
  194.  */
  195. if (pTaskLastFpTcb!=(WIND_TCB *)NULL)
  196. {
  197. fppSave (pTaskLastFpTcb->pFpContext);
  198. pTaskLastFpTcb = (WIND_TCB *)NULL;
  199. }
  200.         taskIdCurrent->errorStatus = errno;
  201. u_sigsuspend (&mask[0]);
  202.         errno = taskIdCurrent->errorStatus;
  203. }
  204. #endif /* CPU_FAMILY==SIMSPARCSOLARIS */
  205. #if  CPU_FAMILY == SIMNT
  206. intUnlock(0);
  207.     /* Don't busy wait, let Windoze run.  This semaphore is given when 
  208.      * a message is received by the process, aka an interrupt shows up.
  209.      */
  210. win_SemTake(simIntIdleSem);
  211. #endif /* CPU_FAMILY == SIMNT */
  212. workQDoWork ();
  213. #if     CPU_FAMILY==MIPS
  214.     /* Let the idle loop look like a real task by turning all ints on.
  215.      * Without this if a task locks interrupts and suspends itself, and
  216.      * there are no ready tasks, we will lockup.
  217.      */
  218. intSRSet (taskSrDefault);
  219. #endif  /* CPU_FAMILY == MIPS */
  220. #if     (CPU_FAMILY == PPC)
  221.         intUnlock (taskMsrDefault);
  222. /* 
  223.  * SPR 74651: if the previous workQDoWork() had added jobs,
  224.  * vxPowerDown still ran until the *next* interrupt.
  225.  */
  226. if (((WIND_TCB *) Q_FIRST (&readyQHead)) != NULL)
  227.     break;
  228. vxPowerDown ();
  229. #endif  /* (CPU_FAMILY == PPC) */
  230. #if (CPU_FAMILY == SH) /* Unlock interrupts */
  231. intLevelSet (0);
  232. /* 
  233.  * SPR 74651: if the previous workQDoWork() had added jobs,
  234.  * the idleLoopHook was still run until the *next* interrupt.
  235.  */
  236. if (((WIND_TCB *) Q_FIRST (&readyQHead)) != NULL)
  237.     break;
  238. if (_func_vxIdleLoopHook != NULL)
  239.     (* _func_vxIdleLoopHook) ();
  240. #endif
  241. #if (CPU_FAMILY == SPARC)
  242. intLevelSet (0);                        /* Unlock interrupts */
  243. #endif
  244. #if     (CPU_FAMILY == ARM)
  245.         intUnlock(0);                           /* Unlock interrupts */
  246. #endif
  247. }
  248.     taskIdCurrent = (WIND_TCB *) Q_FIRST (&readyQHead);
  249.     kernelIsIdle = FALSE;                       /* idle flag for spy */
  250.     /* taskIdCurrent now has some task to run.  If it is different from
  251.      * taskIdPrevious we execute the switch and swap hooks.
  252.      */
  253.     if (taskIdCurrent != taskIdPrevious) /* switching in a new task? */
  254. {
  255. /* do swap hooks */
  256. mask = taskIdCurrent->swapInMask | taskIdPrevious->swapOutMask;
  257. for (ix = 0; mask != 0; ix++, mask = mask << 1)
  258.     if (mask & 0x8000)
  259. (* taskSwapTable[ix]) (taskIdPrevious, taskIdCurrent);
  260. /* do switch hooks */
  261. for (ix = 0;
  262.      (ix < VX_MAX_TASK_SWITCH_RTNS) && (taskSwitchTable[ix] != NULL);
  263.      ++ix)
  264.     {
  265.     (* taskSwitchTable[ix]) (taskIdPrevious, taskIdCurrent);
  266.     }
  267. }
  268.     oldLevel = intLock (); /* LOCK INTERRUPTS */
  269.     if (!workQIsEmpty)
  270. {
  271. intUnlock (oldLevel); /* UNLOCK INTERRUPTS */
  272. goto unlucky; /* take it from the top... */
  273. }
  274.     else
  275. {
  276. #ifdef WV_INSTRUMENTATION
  277.         /* log the dispatch event */
  278.         EVT_CTX_DISP (EVENT_WIND_EXIT_DISPATCH_PI, (int) taskIdCurrent, 
  279.               taskIdCurrent->priority, taskIdCurrent->priNormal);
  280. #endif
  281. kernelState = FALSE; /* KERNEL EXIT */
  282. /* Now we load context and schedule the selected task in.  Note that
  283.  * interrupts are locked out until the task is switched in.  An
  284.  * optimized version of this routine should load the context just
  285.  * before locking interrupts above, then after locking interrupts,
  286.  * check the work queue to see if we missed any deferred.
  287.  */
  288. windLoadContext (); /* dispatch the selected task */
  289. }
  290.     }
  291. #endif /* schedLib_PORTABLE */