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

VxWorks

开发平台:

C/C++

  1. /* qLib.c - queue library */
  2. /* Copyright 1984-1992 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01m,19jul92,pme  made qRemove return STATUS.
  8. 01l,26may92,rrr  the tree shuffle
  9. 01k,04dec91,rrr  removed VARARG_OK, no longer needed with ansi c.
  10. 01j,19nov91,rrr  shut up some ansi warnings.
  11. 01i,04oct91,rrr  passed through the ansification filter
  12.                   -changed functions to ansi style
  13.   -changed includes to have absolute path from h/
  14.   -fixed #else and #endif
  15.   -changed VOID to void
  16.   -changed copyright notice
  17. 01h,14aug91,del  changed qCreate/qInit interfaces to take fixed number
  18.  of args for I960 case only.
  19. 01g,18may91,gae  fixed typo in 01f.
  20. 01f,18may91,gae  fixed varargs for 960 with conditional VARARG_OK,
  21.  namely: qCreate() & qInit().
  22. 01e,28sep90,jcf  documentation.
  23. 01d,10aug90,dnw  changed qCalibrate() to not return value since it is void.
  24. 01c,05jul90,jcf  added qCalibrate().
  25. 01b,26jun90,jcf  added qResort().
  26. 01a,14jun89,jcf  written.
  27. */
  28. /*
  29. DESCRIPTION
  30. This queue management library implements the multi-way queue data structures.
  31. Queues which utilize the data structures Q_HEAD, and Q_NODE are shareable
  32. queues.  The routines of this library perform generic operation on the queue
  33. by dereferencing the queue class pointer to invode the correct method for
  34. the operation selected.  All kernel queues are implemented as multi-way queues,
  35. and thus may be configured to utilize any queue that conforms to this library.
  36. SEE ALSO: qFifoLib, qPriBMapLib, qPriDeltaLib, qPriHeapLib, qPriListLib.
  37. */
  38. #include "vxWorks.h"
  39. #include "errno.h"
  40. #include "stdarg.h"
  41. #include "qClass.h"
  42. #include "qLib.h"
  43. #include "stdlib.h"
  44. #define MAX_ARGS 10 /* number of variable arguments */
  45. /*******************************************************************************
  46. *
  47. * qCreate - allocate and initialize a multi-way queue
  48. *
  49. * This routine allocates a Q_HEAD structure from the free memory pool.  The
  50. * queue head is initialized to the specified multi-way queue class.  Additional
  51. * arguments are passed to the queue classes underlying initialization routine.
  52. *
  53. * RETURNS: Pointer to a queue head, or NULL if queue could not be created.
  54. *
  55. * ERRNO: S_qLib_Q_CLASS_ID_ERROR
  56. *
  57. */
  58. Q_HEAD *qCreate
  59.     (
  60.     Q_CLASS *pQClass,   /* pointer to queue class */
  61.     ...              /* optional arguments to create routine */
  62.     )
  63.     {
  64.     va_list pArg; /* traverses argument list */
  65.     Q_HEAD *pQHead; /* pointer to queue head */
  66.     int ix; /* handy index */
  67.     int arg[MAX_ARGS]; /* indigenous variables */
  68.     if (Q_CLASS_VERIFY (pQClass) != OK)
  69. {
  70. errno = S_qLib_Q_CLASS_ID_ERROR;
  71. return (NULL);
  72. }
  73.     va_start (pArg, pQClass);
  74.     for (ix = 0; ix < MAX_ARGS; ++ix)
  75. arg[ix] = va_arg (pArg, int); /* put args in local vars */
  76.     va_end (pArg);
  77.     pQHead = (Q_HEAD *) malloc (sizeof (Q_HEAD));
  78.     if ((pQHead != NULL) && qInit (pQHead, pQClass, arg[0], arg[1], arg[2],
  79.    arg[3], arg[4], arg[5], arg[6], arg[7],
  80.    arg[8], arg[9]) != OK)
  81. {
  82. /* XXX MAX_ARGS */
  83. free ((char *) pQHead);
  84. return (NULL);
  85. }
  86.     return (pQHead);
  87.     }
  88. /*******************************************************************************
  89. *
  90. * qInit - initialize multi-way queue head
  91. *
  92. * This routine initializes the multi-way queue head to the specified queue
  93. * class.  Additional arguments are passed to the underlying queue class
  94. * initialization routine.
  95. *
  96. * RETURNS OK, or ERROR if initialiazation fails.
  97. *
  98. * ERRNO: S_qLib_Q_CLASS_ID_ERROR
  99. *
  100. */
  101. STATUS qInit
  102.     (
  103.     Q_HEAD *pQHead,     /* pointer to queue head to initialize */
  104.     Q_CLASS *pQClass,   /* pointer to queue class */
  105.     ...              /* optional arguments to create routine */
  106.     )
  107.     {
  108.     va_list pArg; /* traverses argument list */
  109.     int ix; /* handy index */
  110.     int arg[MAX_ARGS]; /* indigenous variables */
  111.     if (Q_CLASS_VERIFY (pQClass) != OK)
  112. {
  113. errno = S_qLib_Q_CLASS_ID_ERROR;
  114. return (ERROR);
  115. }
  116.     va_start (pArg, pQClass);
  117.     for (ix = 0; ix < MAX_ARGS; ++ix)
  118. arg[ix] = va_arg (pArg, int); /* put args in local vars */
  119.     va_end (pArg);
  120.     pQHead->pQClass = pQClass; /* store pointer to q class */
  121.     return ((* (pQClass->initRtn)) (pQHead, arg[0], arg[1], arg[2], arg[3],
  122.     arg[4], arg[5], arg[6], arg[7], arg[8],
  123.     arg[9])); /* XXX MAX_ARGS */
  124.     }
  125. /*******************************************************************************
  126. *
  127. * qDelete - deallocate a multi-way queue head
  128. *
  129. * This routine deallocates the multi-way queue head.  All queued nodes are
  130. * lost.
  131. *
  132. * RETURNS OK, or ERROR if queue deallocation fails.
  133. */
  134. STATUS qDelete
  135.     (
  136.     Q_HEAD *pQHead
  137.     )
  138.     {
  139.     if (qTerminate (pQHead) != OK)
  140. return (ERROR);
  141.     pQHead->pQClass = NULL; /* invalidate q class */
  142.     free ((char *) pQHead);
  143.     return OK;
  144.     }
  145. /*******************************************************************************
  146. *
  147. * qTerminate - terminate a multi-way queue head
  148. *
  149. * This routine terminates a multi-way queue head.  All queued nodes will be
  150. * lost.
  151. *
  152. * RETURNS OK, or ERROR if termination fails.
  153. */
  154. STATUS qTerminate
  155.     (
  156.     Q_HEAD *pQHead
  157.     )
  158.     {
  159.     if (((* (pQHead->pQClass->terminateRtn)) (pQHead)) != OK)
  160. return (ERROR);
  161.     pQHead->pQClass = NULL; /* invalidate q class */
  162.     return (OK);
  163.     }
  164. /*******************************************************************************
  165. *
  166. * qFirst - return first node in multi-way queue
  167. *
  168. * This routine returns a pointer to the first node in the specified multi-way
  169. * queue head.  If the queue is empty, NULL is returned.
  170. *
  171. * RETURNS Pointer to first queue node in queue head, or NULL if queue is empty.
  172. */
  173. Q_NODE *qFirst
  174.     (
  175.     Q_HEAD *pQHead
  176.     )
  177.     {
  178.     return (Q_FIRST (pQHead));
  179.     }
  180. /*******************************************************************************
  181. *
  182. * qPut - insert a node into a multi-way queue
  183. *
  184. * This routine inserts a node into a multi-way queue.  The insertion is based
  185. * on the key and the underlying queue class.
  186. */
  187. void qPut
  188.     (
  189.     Q_HEAD *pQHead,
  190.     Q_NODE *pQNode,
  191.     ULONG   key
  192.     )
  193.     {
  194.     Q_PUT (pQHead, pQNode, key);
  195.     }
  196. /*******************************************************************************
  197. *
  198. * qGet - remove and return first node in multi-way queue
  199. *
  200. * This routine removes and returns the first node in a multi-way queue.  If
  201. * the queue is empty, NULL is returned.
  202. *
  203. * RETURNS Pointer to first queue node in queue head, or NULL if queue is empty.
  204. */
  205. Q_NODE *qGet
  206.     (
  207.     Q_HEAD *pQHead
  208.     )
  209.     {
  210.     return (Q_GET (pQHead));
  211.     }
  212. /*******************************************************************************
  213. *
  214. * qRemove - remove a node from a multi-way queue
  215. *
  216. * This routine removes a node from the specified multi-way queue.
  217. */
  218. STATUS qRemove
  219.     (
  220.     Q_HEAD *pQHead,
  221.     Q_NODE *pQNode
  222.     )
  223.     {
  224.     return (Q_REMOVE (pQHead, pQNode));
  225.     }
  226. /*******************************************************************************
  227. *
  228. * qResort - resort a node to a new position based on a new key
  229. *
  230. * This routine resorts a node to a new position based on a new key.  It can
  231. * be used to change the priority of a queued element, for instance.
  232. */
  233. void qResort
  234.     (
  235.     Q_HEAD *pQHead,
  236.     Q_NODE *pQNode,
  237.     ULONG   newKey
  238.     )
  239.     {
  240.     Q_RESORT (pQHead, pQNode, newKey);
  241.     }
  242. /*******************************************************************************
  243. *
  244. * qAdvance - advance a queues concept of time (timer queues only)
  245. *
  246. * Multi-way queues that keep nodes prioritized by time-to-fire utilize this
  247. * routine to advance time.  It is usually called from within a clock-tick
  248. * interrupt service routine.
  249. */
  250. void qAdvance
  251.     (
  252.     Q_HEAD *pQHead
  253.     )
  254.     {
  255.     Q_ADVANCE (pQHead);
  256.     }
  257. /*******************************************************************************
  258. *
  259. * qGetExpired - return a time-to-fire expired node
  260. *
  261. * This routine returns a time-to-fire expired node in a multi-way timer queue.
  262. * Expired nodes result from a qAdvance(2) advancing a node beyond its delay.
  263. * As many nodes may expire on a single qAdvance(2), this routine should be
  264. * called inside a while loop until NULL is returned.  NULL is returned when
  265. * there are no expired nodes.
  266. *
  267. * RETURNS: Pointer to first queue node in queue head, or NULL if queue is empty.
  268. */
  269. Q_NODE *qGetExpired
  270.     (
  271.     Q_HEAD *pQHead
  272.     )
  273.     {
  274.     return (Q_GET_EXPIRED (pQHead));
  275.     }
  276. /*******************************************************************************
  277. *
  278. * qKey - return the key of a node
  279. *
  280. * This routine returns the key of a node currently in a multi-way queue.  The
  281. * keyType determines key style on certain queue classes.
  282. *
  283. * RETURNS: Node's key.
  284. */
  285. ULONG qKey
  286.     (
  287.     Q_HEAD *pQHead,
  288.     Q_NODE *pQNode,
  289.     int     keyType
  290.     )
  291.     {
  292.     return (Q_KEY (pQHead, pQNode, keyType));
  293.     }
  294. /*******************************************************************************
  295. *
  296. * qCalibrate - offset every node in a queue by some delta
  297. *
  298. * This routine offsets every node in a multi-way queue by some delta.  The
  299. * offset may either by positive or negative.
  300. */
  301. void qCalibrate
  302.     (
  303.     Q_HEAD *pQHead,
  304.     ULONG   keyDelta
  305.     )
  306.     {
  307.     Q_CALIBRATE (pQHead, keyDelta);
  308.     }
  309. /*******************************************************************************
  310. *
  311. * qInfo - gather information on a multi-way queue
  312. *
  313. * This routine fills up to maxNodes elements of a nodeArray with nodes
  314. * currently in a multi-way queue.  The actual number of nodes copied to the
  315. * array is returned.  If the nodeArray is NULL, then the number of nodes in
  316. * the multi-way queue is returned.
  317. *
  318. * RETURNS: Number of node pointers copied to the nodeArray, or nodes in
  319. *    multi-way queue if nodeArray is NULL.
  320. */
  321. int qInfo
  322.     (
  323.     Q_HEAD *pQHead,
  324.     Q_NODE *nodeArray[],
  325.     int    maxNodes
  326.     )
  327.     {
  328.     return (Q_INFO (pQHead, nodeArray, maxNodes));
  329.     }
  330. /*******************************************************************************
  331. *
  332. * qEach - call a routine for each node in a queue
  333. *
  334. * This routine calls a user-supplied routine once for each node in the
  335. * queue.  The routine should be declared as follows:
  336. * .CS
  337. *  BOOL routine (pQNode, arg)
  338. *      Q_NODE *pQNode; /@ pointer to a queue node          @/
  339. *      int arg; /@ arbitrary user-supplied argument @/
  340. * .CE
  341. * The user-supplied routine should return TRUE if qEach() is to continue
  342. * calling it for each entry, or FALSE if it is done and qEach can exit.
  343. *
  344. * RETURNS: NULL if traversed whole queue, or pointer to Q_NODE that
  345. *          qEach ended with.
  346. */
  347. Q_NODE *qEach
  348.     (
  349.     Q_HEAD      *pQHead,        /* queue head of queue to call routine for */
  350.     FUNCPTR     routine,        /* the routine to call for each queue node */
  351.     int         routineArg      /* arbitrary user-supplied argument */
  352.     )
  353.     {
  354.     return (Q_EACH (pQHead, routine, routineArg));
  355.     }