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

VxWorks

开发平台:

C/C++

  1. /* qPriBMapLib.c - bit mapped priority queue management library */
  2. /* Copyright 1984-1998 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02o,16nov98,cdp  make ARM CPUs with ARM_THUMB==TRUE use portable routines.
  8. 02m,06jan98,cym  added simnt support
  9. 02n,22apr97,jpd  removed ARM from PORTABLE list.
  10. 02m,29jan97,elp  added ARM support
  11. 02l,12jul95,ism  added simsolaris support
  12. 02l,04nov94,yao  added PPC support.
  13. 02k,11aug93,gae  vxsim hppa from rrr.
  14. 02j,12jun93,rrr  vxsim.
  15. 02i,27jul92,jcf  all architectures now utilize this library.
  16.                  added nPriority selection for memory conservation.
  17. 02h,19jul92,pme  made qPriBMapRemove return STATUS.
  18. 02g,18jul92,smb  Changed errno.h to errnoLib.h
  19. 02f,26may92,rrr  the tree shuffle
  20. 02e,22apr92,jwt  converted CPU==SPARC to CPU_FAMILY==SPARC; copyright.
  21. 02d,19nov91,rrr  shut up some ansi warnings.
  22. 02c,04oct91,rrr  passed through the ansification filter
  23.                   -changed functions to ansi style
  24.   -fixed #else and #endif
  25.   -changed TINY and UTINY to INT8 and UINT8
  26.   -changed VOID to void
  27.   -changed copyright notice
  28. 02b,25mar91,del  added I960 to portable checklist.
  29. 02a,10jan91,jcf  changed BMAP_LIST for portability to other architectures.
  30. 01e,20dec90,gae  added declaration of qPriBMapSet and qPriBMapClear.
  31. 01d,28sep90,jcf  documentation.
  32. 01c,05jul90,jcf  added null routine for calibrateRtn field in Q_CLASS.
  33. 01b,10may90,jcf  fixed PORTABLE definition.
  34.  changed ffs () to ffsMsb ().
  35. 01a,14jun89,jcf  written.
  36. */
  37. /*
  38. DESCRIPTION
  39. This library contains routines to manage a priority queue.  The queue is
  40. maintained in priority order with no sorting time, so its performance is
  41. constant.  Its restrictions are that it requires a 2K byte bit map, and it
  42. can only prioritize nodes with keys in the range 0 to 255.
  43. This queue complies with the multi-way queue data structures and thus may be
  44. utilized by any multi-way queue.  The priority bit mapped multi-way queue
  45. class is accessed by the global id qPriBMapClassId.
  46. SEE ALSO: qLib()
  47. */
  48. #include "vxWorks.h"
  49. #include "qClass.h"
  50. #include "qPriBMapLib.h"
  51. #include "memLib.h"
  52. #include "errnoLib.h"
  53. #include "string.h"
  54. #include "stdlib.h"
  55. #if (defined(PORTABLE) || 
  56.      (CPU_FAMILY == SIMNT) || (CPU_FAMILY == SPARC) || (CPU_FAMILY == I960) || 
  57.      (CPU_FAMILY == SIMSPARCSUNOS) || (CPU_FAMILY == SIMHPPA) || 
  58.      (CPU_FAMILY == SIMSPARCSOLARIS) || ((CPU_FAMILY == ARM) && ARM_THUMB))
  59. #define qPriBMapLib_PORTABLE
  60. #endif
  61. #if     (CPU_FAMILY == PPC)
  62. #define qPriBMapLib_PORTABLE
  63. #endif  /* (CPU_FAMILY == PPC) */
  64. #if defined(PORTABLE)
  65. #define qPriBMapLib_PORTABLE
  66. #endif /* PORTABLE */
  67. /* forward static functions */
  68. static STATUS qPriBMapNullRtn (void);
  69. #ifdef qPriBMapLib_PORTABLE
  70. static void qPriBMapSet (BMAP_LIST *pBMapList, int priority);
  71. static void qPriBMapClear (BMAP_LIST *pBMapList, int priority);
  72. static int qPriBMapHigh (BMAP_LIST *pBMapList);
  73. #endif /* qPriBMapLib_PORTABLE */
  74. /* locals */
  75. LOCAL Q_CLASS qPriBMapClass =
  76.     {
  77.     (FUNCPTR)qPriBMapCreate,
  78.     (FUNCPTR)qPriBMapInit,
  79.     (FUNCPTR)qPriBMapDelete,
  80.     (FUNCPTR)qPriBMapNullRtn,
  81.     (FUNCPTR)qPriBMapPut,
  82.     (FUNCPTR)qPriBMapGet,
  83.     (FUNCPTR)qPriBMapRemove,
  84.     (FUNCPTR)qPriBMapResort,
  85.     (FUNCPTR)qPriBMapNullRtn,
  86.     (FUNCPTR)qPriBMapNullRtn,
  87.     (FUNCPTR)qPriBMapKey,
  88.     (FUNCPTR)qPriBMapNullRtn,
  89.     (FUNCPTR)qPriBMapInfo,
  90.     (FUNCPTR)qPriBMapEach,
  91.     &qPriBMapClass
  92.     };
  93. /* globals */
  94. Q_CLASS_ID qPriBMapClassId = &qPriBMapClass;
  95. /******************************************************************************
  96. *
  97. * qPriBMapListCreate - create and initialized a bit mapped priority queue
  98. *
  99. * Create a bit mapped priority queue.  Initialize the specified queue header.
  100. *
  101. * RETURNS: OK or ERROR if not enough memory to create queue.
  102. *
  103. * SEE ALSO: qPriBMapInit().
  104. */
  105. BMAP_LIST *qPriBMapListCreate 
  106.     (
  107.     UINT nPriority /* 1 priority to 256 priorities */
  108.     )
  109.     {
  110.     UINT size;
  111.     if ((nPriority < 1) || (nPriority > 256))
  112. return (NULL);
  113.     
  114.     size = sizeof (BMAP_LIST) - (sizeof (DL_LIST) * (256 - nPriority));
  115.     return ((BMAP_LIST *) malloc (size));
  116.     }
  117. /******************************************************************************
  118. *
  119. * qPriBMapListDelete - deallocate a bit mapped list
  120. *
  121. * This routine returns an allocated BMAP_LIST to the free memory pool.
  122. *
  123. * RETURNS: OK, or ERROR if bit mapped list could not be deallocated.
  124. */
  125. STATUS qPriBMapListDelete
  126.     (
  127.     BMAP_LIST *pBMapList
  128.     )
  129.     {
  130.     free ((char *)pBMapList);
  131.     return (OK);
  132.     }
  133. /******************************************************************************
  134. *
  135. * qPriBMapCreate - create and initialized a bit mapped priority queue
  136. *
  137. * Create a bit mapped priority queue.  Initialize the specified queue header.
  138. *
  139. * RETURNS: OK, or ERROR if not enough memory to create queue.
  140. *
  141. * SEE ALSO: qPriBMapInit()
  142. */
  143. Q_PRI_BMAP_HEAD *qPriBMapCreate
  144.     (
  145.     BMAP_LIST * pBMapList,
  146.     UINT nPriority /* 1 priority to 256 priorities */
  147.     )
  148.     {
  149.     Q_PRI_BMAP_HEAD *pQPriBMapHead;
  150.     if ((nPriority < 1) || (nPriority > 256))
  151. return (NULL);
  152.     pQPriBMapHead = (Q_PRI_BMAP_HEAD *) malloc (sizeof (Q_PRI_BMAP_HEAD));
  153.     if (pQPriBMapHead == NULL)
  154. return (NULL);
  155.     if (qPriBMapInit (pQPriBMapHead, pBMapList, nPriority) != OK)
  156. {
  157. free ((char *)pQPriBMapHead);
  158. return (NULL);
  159. }
  160.     return (pQPriBMapHead);
  161.     }
  162. /******************************************************************************
  163. *
  164. * qPriBMapInit - initialize a bit mapped priority queue
  165. *
  166. * Initialize the bit mapped priority queue pointed to by the specified queue
  167. * header.
  168. *
  169. * RETURNS: OK or ERROR
  170. *
  171. * ERRNO: S_qPriBMapLib_NULL_BMAP_LIST
  172. *
  173. */
  174. STATUS qPriBMapInit
  175.     (
  176.     Q_PRI_BMAP_HEAD * pQPriBMapHead,
  177.     BMAP_LIST * pBMapList,
  178.     UINT nPriority /* 1 priority to 256 priorities */
  179.     )
  180.     {
  181.     FAST int ix;
  182.     if ((nPriority < 1) || (nPriority > 256))
  183. return (ERROR);
  184.     if (pBMapList == NULL)
  185. {
  186. errnoSet (S_qPriBMapLib_NULL_BMAP_LIST);
  187. return (ERROR);
  188. }
  189.     pQPriBMapHead->pBMapList = pBMapList; /* store bmap list pointer */
  190.     /* initialize the q */
  191.     for (ix = 0; ix < nPriority; ++ix)
  192. dllInit (&pBMapList->listArray[ix]);
  193.     pQPriBMapHead->highNode = NULL; /* zero the highest node */
  194.     pQPriBMapHead->nPriority = nPriority; /* higest legal priority */
  195.     /* zero the bit maps */
  196.     pBMapList->metaBMap = 0;
  197.     bzero ((char *) pBMapList->bMap, sizeof (pBMapList->bMap));
  198.     return (OK);
  199.     }
  200. /******************************************************************************
  201. *
  202. * qPriBMapDelete - deallocate a bit mapped queue head
  203. *
  204. * This routine deallocates a bit mapped queue head.  All queued nodes will
  205. * be lost.
  206. *
  207. * RETURNS: OK, or ERROR in bit mapped queue head could not be deallocated.
  208. */
  209. STATUS qPriBMapDelete
  210.     (
  211.     Q_PRI_BMAP_HEAD *pQPriBMapHead
  212.     )
  213.     {
  214.     free ((char *)pQPriBMapHead);
  215.     return (OK);
  216.     }
  217. #ifdef qPriBMapLib_PORTABLE
  218. /*******************************************************************************
  219. *
  220. * qPriBMapPut - insert a node into a priority bit mapped queue
  221. *
  222. * This routine inserts a node into a priority bit mapped queue.  The insertion
  223. * is based on the specified priority key which is constrained to the range
  224. * 0 to 255.  The highest priority is zero.
  225. */
  226. void qPriBMapPut
  227.     (
  228.     Q_PRI_BMAP_HEAD     *pQPriBMapHead,
  229.     Q_PRI_NODE          *pQPriNode,
  230.     ULONG                key
  231.     )
  232.     {
  233.     pQPriNode->key = key;
  234.     if ((pQPriBMapHead->highNode == NULL) ||
  235.         (key < pQPriBMapHead->highNode->key))
  236. {
  237. pQPriBMapHead->highNode = pQPriNode;
  238. }
  239.     qPriBMapSet (pQPriBMapHead->pBMapList, key);
  240.     dllAdd (&pQPriBMapHead->pBMapList->listArray[key], &pQPriNode->node);
  241.     }
  242. /*******************************************************************************
  243. *
  244. * qPriBMapGet - remove and return first node in priority bit-mapped queue
  245. *
  246. * This routine removes and returns the first node in a priority bit-mapped
  247. * queue.  If the queue is empty, NULL is returned.
  248. *
  249. * RETURNS Pointer to first queue node in queue head, or NULL if queue is empty.
  250. */
  251. Q_PRI_NODE *qPriBMapGet
  252.     (
  253.     Q_PRI_BMAP_HEAD *pQPriBMapHead
  254.     )
  255.     {
  256.     Q_PRI_NODE *pQPriNode = pQPriBMapHead->highNode;
  257.     if (pQPriNode != NULL)
  258. qPriBMapRemove (pQPriBMapHead, pQPriNode);
  259.     return (pQPriNode);
  260.     }
  261. /*******************************************************************************
  262. *
  263. * qPriBMapRemove - remove a node from a priority bit mapped queue
  264. *
  265. * This routine removes a node from the specified bit mapped queue.
  266. */
  267. STATUS qPriBMapRemove
  268.     (
  269.     Q_PRI_BMAP_HEAD *pQPriBMapHead,
  270.     Q_PRI_NODE *pQPriNode
  271.     )
  272.     {
  273.     dllRemove (&pQPriBMapHead->pBMapList->listArray[pQPriNode->key],
  274.        &pQPriNode->node);
  275.     if (DLL_EMPTY (&pQPriBMapHead->pBMapList->listArray[pQPriNode->key]))
  276.         {
  277. qPriBMapClear (pQPriBMapHead->pBMapList, pQPriNode->key);
  278. if (pQPriNode == pQPriBMapHead->highNode)
  279.     pQPriBMapHead->highNode =
  280.       (Q_PRI_NODE *) DLL_FIRST(&pQPriBMapHead->pBMapList->
  281.       listArray[qPriBMapHigh(pQPriBMapHead->pBMapList)]);
  282. }
  283.     else if (pQPriNode == pQPriBMapHead->highNode)
  284. pQPriBMapHead->highNode =
  285.   (Q_PRI_NODE *) DLL_FIRST (&pQPriBMapHead->pBMapList->
  286.   listArray[pQPriBMapHead->highNode->key]);
  287.     return (OK);
  288.     }
  289. #endif /* qPriBMapLib_PORTABLE */
  290. /*******************************************************************************
  291. *
  292. * qPriBMapResort - resort a node to a new position based on a new key
  293. *
  294. * This routine resorts a node to a new position based on a new priority key.
  295. */
  296. void qPriBMapResort
  297.     (
  298.     Q_PRI_BMAP_HEAD *pQPriBMapHead,
  299.     Q_PRI_NODE      *pQPriNode,
  300.     ULONG            newKey
  301.     )
  302.     {
  303.     if (pQPriNode->key != newKey)
  304. {
  305. qPriBMapRemove (pQPriBMapHead, pQPriNode);
  306. qPriBMapPut (pQPriBMapHead, pQPriNode, newKey);
  307. }
  308.     }
  309. /*******************************************************************************
  310. *
  311. * qPriBMapKey - return the key of a node
  312. *
  313. * This routine returns the key of a node currently in a multi-way queue.  The
  314. * keyType is ignored.
  315. *
  316. * RETURNS: Node's key.
  317. *
  318. * ARGSUSED
  319. */
  320. ULONG qPriBMapKey
  321.     (
  322.     Q_PRI_NODE  *pQPriNode      /* node to get key for */
  323.     )
  324.     {
  325.     return (pQPriNode->key); /* return key */
  326.     }
  327. /*******************************************************************************
  328. *
  329. * qPriBMapInfo - gather information on a bit mapped queue
  330. *
  331. * This routine fills up to maxNodes elements of a nodeArray with nodes
  332. * currently in a multi-way queue.  The actual number of nodes copied to the
  333. * array is returned.  If the nodeArray is NULL, then the number of nodes in
  334. * the multi-way queue is returned.
  335. *
  336. * RETURNS: Number of node pointers copied into the nodeArray, or number of
  337. *    nodes in bit mapped queue if nodeArray is NULL
  338. */
  339. int qPriBMapInfo
  340.     (
  341.     Q_PRI_BMAP_HEAD *pQPriBMapHead,     /* bmap q to gather list for */
  342.     FAST int nodeArray[],               /* array of node pointers for filling */
  343.     FAST int maxNodes                   /* max node pointers for nodeArray */
  344.     )
  345.     {
  346.     FAST Q_PRI_NODE *pNode;
  347.     FAST int *pElement = nodeArray;
  348.     FAST int ix;
  349.     int count = 0;
  350.     if (nodeArray == NULL)
  351. {
  352. for (ix = 0; ix < pQPriBMapHead->nPriority; ++ix)
  353.     count += dllCount (&pQPriBMapHead->pBMapList->listArray[ix]);
  354. return (count);
  355. }
  356.     for (ix = 0; ix < pQPriBMapHead->nPriority; ++ix) /* search the array */
  357. {
  358. pNode=(Q_PRI_NODE *)DLL_FIRST(&pQPriBMapHead->pBMapList->listArray[ix]);
  359. while ((pNode != NULL) && (--maxNodes >= 0)) /* anybody left? */
  360.     {
  361.     *(pElement++) = (int)pNode; /* fill in table */
  362.     pNode = (Q_PRI_NODE *) DLL_NEXT (&pNode->node);  /* next node */
  363.     }
  364. if (maxNodes < 0) /* out of room? */
  365.     break;
  366. }
  367.     return (pElement - nodeArray); /* return count of active tasks */
  368.     }
  369. /*******************************************************************************
  370. *
  371. * qPriBMapEach - call a routine for each node in a queue
  372. *
  373. * This routine calls a user-supplied routine once for each node in the
  374. * queue.  The routine should be declared as follows:
  375. * .CS
  376. *  BOOL routine (pQNode, arg)
  377. *      Q_PRI_NODE *pQNode; /@ pointer to a queue node          @/
  378. *      int    arg; /@ arbitrary user-supplied argument @/
  379. * .CE
  380. * The user-supplied routine should return TRUE if qPriBMapEach() is to
  381. * continue calling it for each entry, or FALSE if it is done and
  382. * qPriBMapEach() can exit.
  383. *
  384. * RETURNS: NULL if traversed whole queue, or pointer to Q_PRI_NODE that
  385. *          qPriBMapEach stopped on.
  386. */
  387. Q_PRI_NODE *qPriBMapEach
  388.     (
  389.     Q_PRI_BMAP_HEAD *pQHead,     /* queue head of queue to call routine for */
  390.     FUNCPTR          routine,    /* the routine to call for each table entry */
  391.     int              routineArg  /* arbitrary user-supplied argument */
  392.     )
  393.     {
  394.     FAST int      ix;
  395.     FAST Q_PRI_NODE *pNode = NULL;
  396.     for (ix = 0; ix < pQHead->nPriority; ++ix) /* search array */
  397. {
  398. pNode = (Q_PRI_NODE *)
  399. DLL_FIRST (&pQHead->pBMapList->listArray[ix]);
  400. while (pNode != NULL)
  401.     {
  402.     if (!((* routine) (pNode, routineArg)))
  403. goto done; /* bail out */
  404.     pNode = (Q_PRI_NODE *) DLL_NEXT (&pNode->node);
  405.     }
  406. }
  407. done:
  408.     return (pNode); /* return node we ended with */
  409.     }
  410. /*******************************************************************************
  411. *
  412. * qPriBMapNullRtn - null routine returns OK
  413. *
  414. * This routine does nothing and returns OK.  It is used by the queue class
  415. * structure for operations not supported by this queue type.
  416. */
  417. LOCAL STATUS qPriBMapNullRtn (void)
  418.     {
  419.     return (OK);
  420.     }
  421. #ifdef qPriBMapLib_PORTABLE
  422. /*******************************************************************************
  423. *
  424. * qPriBMapSet - set the bits in the bit map for the specified priority
  425. *
  426. * This routine sets the bits in the bit map to reflect the addition of a node
  427. * of the specified priority.
  428. */
  429. LOCAL void qPriBMapSet
  430.     (
  431.     BMAP_LIST *pBMapList,
  432.     int priority
  433.     )
  434.     {
  435.     priority = 255 - priority;
  436.     pBMapList->metaBMap |= (1 << (priority >> 3));
  437.     pBMapList->bMap [priority >> 3] |= (1 << (priority & 0x7));
  438.     }
  439. /*******************************************************************************
  440. *
  441. * qPriBMapClear - clear the bits in the bit map for the specified priority
  442. *
  443. * This routine clears the bits in the bit map to reflect the removal of a node
  444. * of the specified priority.
  445. */
  446. LOCAL void qPriBMapClear
  447.     (
  448.     BMAP_LIST *pBMapList,
  449.     int priority
  450.     )
  451.     {
  452.     priority = 255 - priority;
  453.     pBMapList->bMap [priority >> 3] &= ~(1 << (priority & 0x7));
  454.     if (pBMapList->bMap [priority >> 3] == 0)
  455. pBMapList->metaBMap &= ~(1 << (priority >> 3));
  456.     }
  457. /*******************************************************************************
  458. *
  459. * qPriBMapHigh - return highest priority in ready queue
  460. *
  461. * This routine utilizes the bit map structure to determine the highest active
  462. * priority group.
  463. *
  464. * RETURNS: Priority of highest active priority group.
  465. */
  466. LOCAL int qPriBMapHigh
  467.     (
  468.     BMAP_LIST *pBMapList
  469.     )
  470. {
  471. UINT8 highBits = (UINT8) ffsMsb ((int)pBMapList->metaBMap) - 1;
  472. UINT8 lowBits  = (UINT8) ffsMsb ((int)pBMapList->bMap[highBits]) - 1;
  473. return (255 - (((highBits << 3) | lowBits) & 0xff));
  474. }
  475. #endif /* qPriBMapLib_PORTABLE */