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

VxWorks

开发平台:

C/C++

  1. /* workQLib.c - wind work queue library */
  2. /* Copyright 1988-1998 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01u,09nov01,dee  add CPU_FAMILY != COLDFIRE
  8. 01t,03mar00,zl   merged SH support into T2
  9. 01u,18dec00,pes  Correct compiler warnings
  10. 01t,09oct00,pai  added Ping's (pfl) fix for scheduler problem, spr 28648
  11. 01s,29oct97,cth  removed references to scrPad for WV2.0 for real
  12. 01r,31jul97,nps  WindView 2.0 - remove reference to scratchPad.
  13. 01t,18feb98,cdp  undo 01s: put ARM back in list of optimised CPUs.
  14. 01s,21oct97,kkk  undo 01r, take out ARM from list of optimized CPUs.
  15. 01r,22apr97,jpd  added ARM to list of non-portable CPUs.
  16. 01q,24jun96,sbs  made windview instrumentation conditionally compiled
  17. 01n,21mar95,dvs  removed tron references.
  18. 01m,09jun93,hdn  added a support for I80X86
  19. 01p,03nov94,rdc  changed where interrupts get locked in workQDoWork.
  20. 01o,01sep94,rdc  fixed spr 3442 (scratch pad mismanagement in portable version)
  21. 01n,10dec93,smb  added instrumentation for windview
  22. 01l,04jul92,jcf  private header files.
  23. 01k,26may92,rrr  the tree shuffle
  24. 01j,15oct91,ajm  added MIPS to list of optimized CPU's.
  25. 01i,04oct91,rrr  passed through the ansification filter
  26.                   -changed functions to ansi style
  27.   -changed includes to have absolute path from h/
  28.   -fixed #else and #endif
  29.   -changed TINY and UTINY to INT8 and UINT8
  30.   -changed VOID to void
  31.   -changed copyright notice
  32. 01h,26sep91,hdn  added TRON to list of non-portable CPU's.
  33. 01g,24jul91,del  added I960 to list of non-portable CPU's.
  34. 01f,29dec90,gae  added forward declaration of workQPanic.
  35. 01e,28sep90,jcf  documentation.
  36. 01d,01aug90,jcf  added queue overflow panic.
  37. 01c,15jul90,jcf  made workQDoWork () callable from itself, for watchdogs
  38. 01b,11may90,jcf  fixed up PORTABLE definition.
  39. 01a,14jun89,jcf  written.
  40. */
  41. /*
  42. DESCRIPTION
  43. The VxWorks kernel provides tasking control services to an application.  The
  44. libraries kernelLib, taskLib, semLib, tickLib, and wdLib comprise the kernel
  45. functionality.  This library is internal to the VxWorks kernel and contains
  46. no user callable routines.
  47. INTERNAL
  48. These routines manage the wind work queue.  The work queue is used to queue
  49. kernel work that must be deferred because the kernel is already engaged by
  50. another request.  Kernel work deferred to the work queue must originate
  51. from an interrupt service routine.
  52. The work queue is an example of a single reader/multiple writer queue.
  53. The reader is always the first task or interrupt that enters the kernel, and
  54. that reader is responsible for emptying the work queue before leaving.  The
  55. work queue writers are from interrupt service routines so the interrupts must
  56. be locked during work queue write manipulations, but need not be locked during
  57. read operations.
  58. The work queue is implemented is implemented as a 1K byte ring buffer.  Each
  59. ring entry, or JOB, is 16 bytes in size.  So the ring has 64 entries.  The
  60. selection of this size is based on the efficiency of indexing the work queue
  61. with a single byte index.  To advance the index, all we have to do is add four
  62. to the index, and if our arithmatic is 8 bit, the overflow will be discarded.
  63. The efficiency lies in the fact that we have no conditionals to test for ring
  64. wrap around.
  65. This library should be optimized whenever possible, because the work queue
  66. should scream.
  67. CAVEATS
  68. Two constraints make the future of this library somewhat cloudy.  The
  69. limits of 64 jobs and 16 byte jobs are pretty much hard coded in.  So its
  70. likely that this implementation will give way someday to meet future needs.
  71. It remains the most efficient mechanism for the work queue today.
  72. SEE ALSO: workALib, windLib, and windALib.
  73. NOMANUAL
  74. */
  75. #include "vxWorks.h"
  76. #include "intLib.h"
  77. #include "sysLib.h"
  78. #include "errno.h"
  79. #include "rebootLib.h"
  80. #include "private/workQLibP.h"
  81. #include "private/funcBindP.h"
  82. /*
  83.  * optimized version available for 680X0, I960, MIPS, I80X86, SH,
  84.  * ARM (excluding Thumb)
  85.  */
  86. #if (defined(PORTABLE) || 
  87.      ((CPU_FAMILY != MC680X0) && 
  88.       (CPU_FAMILY != I960) && 
  89.       (CPU_FAMILY != MIPS) && 
  90.       (CPU_FAMILY != I80X86) && 
  91.       (CPU_FAMILY != SH) && 
  92.       (CPU_FAMILY != COLDFIRE) && 
  93.       (CPU_FAMILY != ARM)) || 
  94.      ((CPU_FAMILY == ARM) && ARM_THUMB))
  95. #define workLib_PORTABLE
  96. #endif
  97. /* globals */
  98. volatile UINT8 workQReadIx; /* circular work queue read index */
  99. volatile UINT8 workQWriteIx; /* circular work queue read index */
  100. volatile BOOL  workQIsEmpty; /* TRUE if work queue is empty */
  101. int   pJobPool [WIND_JOBS_MAX * 4]; /* pool of memory for jobs */
  102. /*******************************************************************************
  103. *
  104. * workQInit - initialize the wind work queue
  105. *
  106. * This routine sets the read and write index to their initial values of zero.
  107. */
  108. void workQInit (void)
  109.     {
  110.     workQReadIx  = workQWriteIx = 0; /* initialize the indexes */
  111.     workQIsEmpty = TRUE; /* the work queue is empty */
  112.     }
  113. #ifdef workLib_PORTABLE
  114. /*******************************************************************************
  115. *
  116. * workQAdd0 - add work with no parameters to the wind work queue
  117. *
  118. * When the kernel is interrupted, new kernel work must be queued to an internal
  119. * work queue.  The work queue is emptied by whatever task or interrupt service
  120. * routine that entered the kernel first.  The work is emptied as the last
  121. * code of reschedule().
  122. *
  123. * INTERNAL
  124. * The work queue is single reader, multiple writer, so we should have to lock
  125. * out interrupts while the writer is copying into the ring, but because the
  126. * reader can never interrupt a writer, interrupts need only be locked while
  127. * we advance the write queue pointer.
  128. *
  129. * RETURNS: OK
  130. *
  131. * SEE ALSO: reschedule().
  132. *
  133. * NOMANUAL
  134. */
  135. void workQAdd0
  136.     (
  137.     FUNCPTR func        /* function to invoke */
  138.     )
  139.     {
  140.     int level = intLock (); /* LOCK INTERRUPTS */
  141.     FAST JOB *pJob = (JOB *) &pJobPool [workQWriteIx];
  142.     workQWriteIx += 4; /* advance write index */
  143.     if (workQWriteIx == workQReadIx)
  144. workQPanic (); /* leave interrupts locked */
  145.     intUnlock (level); /* UNLOCK INTERRUPTS */
  146.     workQIsEmpty = FALSE; /* we put something in it */
  147.     pJob->function = func; /* fill in function */
  148.     }
  149. /*******************************************************************************
  150. *
  151. * workQAdd1 - add work with one parameter to the wind work queue
  152. *
  153. * When the kernel is interrupted, new kernel work must be queued to an internal
  154. * work queue.  The work queue is emptied by whatever task or interrupt service
  155. * routine that entered the kernel first.  The work is emptied as the last
  156. * code of reschedule().
  157. *
  158. * INTERNAL
  159. * The work queue is single reader, multiple writer, so we should have to lock
  160. * out interrupts while the writer is copying into the ring, but because the
  161. * reader can never interrupt a writer, interrupts need only be locked while
  162. * we advance the write queue pointer.
  163. *
  164. * RETURNS: OK
  165. *
  166. * SEE ALSO: reschedule()
  167. *
  168. * NOMANUAL
  169. */
  170. void workQAdd1
  171.     (
  172.     FUNCPTR func,       /* function to invoke */
  173.     int arg1            /* parameter one to function */
  174.     )
  175.     {
  176.     int level = intLock (); /* LOCK INTERRUPTS */
  177.     FAST JOB *pJob = (JOB *) &pJobPool [workQWriteIx];
  178.     workQWriteIx += 4; /* advance write index */
  179.     if (workQWriteIx == workQReadIx)
  180. workQPanic (); /* leave interrupts locked */
  181.     intUnlock (level); /* UNLOCK INTERRUPTS */
  182.     workQIsEmpty = FALSE; /* we put something in it */
  183.     pJob->function = func; /* fill in function */
  184.     pJob->arg1 = arg1; /* fill in argument */
  185.     }
  186. /*******************************************************************************
  187. *
  188. * workQAdd2 - add work with two parameters to the wind work queue
  189. *
  190. * When the kernel is interrupted, new kernel work must be queued to an internal
  191. * work queue.  The work queue is emptied by whatever task or interrupt service
  192. * routine that entered the kernel first.  The work is emptied as the last
  193. * code of reschedule().
  194. *
  195. * INTERNAL
  196. * The work queue is single reader, multiple writer, so we should have to lock
  197. * out interrupts while the writer is copying into the ring, but because the
  198. * reader can never interrupt a writer, interrupts need only be locked while
  199. * we advance the write queue pointer.
  200. *
  201. * RETURNS: OK
  202. *
  203. * SEE ALSO: reschedule().
  204. *
  205. * NOMANUAL
  206. */
  207. void workQAdd2
  208.     (
  209.     FUNCPTR func,       /* function to invoke */
  210.     int arg1,           /* parameter one to function */
  211.     int arg2            /* parameter two to function */
  212.     )
  213.     {
  214.     int level = intLock (); /* LOCK INTERRUPTS */
  215.     FAST JOB *pJob = (JOB *) &pJobPool [workQWriteIx];
  216.     workQWriteIx += 4; /* advance write index */
  217.     if (workQWriteIx == workQReadIx)
  218. workQPanic (); /* leave interrupts locked */
  219.     intUnlock (level); /* UNLOCK INTERRUPTS */
  220.     workQIsEmpty = FALSE; /* we put something in it */
  221.     pJob->function = func; /* fill in function */
  222.     pJob->arg1 = arg1; /* fill in arguments */
  223.     pJob->arg2 = arg2;
  224.     }
  225. /*******************************************************************************
  226. *
  227. * workQDoWork - execute all the work in the work queue
  228. *
  229. * When the kernel is interrupted, new kernel work must be queued to an internal
  230. * work queue.  The work queue is emptied by whatever task or interrupt service
  231. * routine that entered the kernel first.  The work is emptied by calling this
  232. * routine as the last code of reschedule().
  233. *
  234. * INTERNAL
  235. * The work queue is single reader, multiple writer, so we should have to lock
  236. * out interrupts while the writer is copying into the ring, but because the
  237. * reader can never interrupt a writer, interrupts need only be locked while
  238. * we advance the write queue pointer.
  239. *
  240. * SEE ALSO: reschedule().
  241. *
  242. * NOMANUAL
  243. */
  244. void workQDoWork (void)
  245.     {
  246.     FAST JOB *pJob;
  247.     int oldErrno = errno; /* save errno */
  248.     while (workQReadIx != workQWriteIx)
  249. {
  250.         pJob = (JOB *) &pJobPool [workQReadIx]; /* get job */
  251. /* increment read index before calling function, because work function
  252.  * could be windTickAnnounce () that calls this routine as well.
  253.  */
  254. workQReadIx += 4;
  255.         (FUNCPTR *)(pJob->function) (pJob->arg1, pJob->arg2);
  256. workQIsEmpty = TRUE; /* leave loop with empty TRUE */
  257. }
  258.     errno = oldErrno; /* restore _errno */
  259.     }
  260. #endif /* workLib_PORTABLE */
  261. /*******************************************************************************
  262. *
  263. * workQPanic - work queue has overflowed so reboot system
  264. *
  265. * The application has really botched things up if we get here, so we reboot
  266. * the system.  An overflow can be detected if the read index is one greater than
  267. * the write index.
  268. *
  269. * NOMANUAL
  270. */
  271. void workQPanic (void)
  272.     {
  273.     static char *pWorkQMsg = "nworkQPanic: Kernel work queue overflow.n";
  274.     while ((*(sysExcMsg++) = *(pWorkQMsg++)) != EOS)
  275. ;
  276.     
  277.     sysExcMsg --;
  278.     reboot (BOOT_WARM_AUTOBOOT);
  279.     }