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

VxWorks

开发平台:

C/C++

  1. /* msgQShow.c - message queue show routines */
  2. /* Copyright 1990-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01v,06nov01,aeg  added display of VxWorks event information.
  8. 01u,26sep01,jws  move vxMP and vxFusion show & info rtn ptrs
  9.                  to funcBind.c (SPR36055)
  10. 01t,18dec00,pes  Correct compiler warnings
  11. 01s,17mar99,jdi  doc: updated w/ info about proj facility (SPR 25727).
  12. 01r,19may98,drm  merged code from 3rd party to add distributed message queue 
  13.                  support  - merged code was originally based on version 01o 
  14. 01q,17apr98,rlp  canceled msgQShow and msgQInfoGet modifications for backward
  15.                  compatibility.
  16. 01p,04nov97,rlp  modified msgQShow and msgQInfoGet for tracking messages sent.
  17. 01o,24jun96,sbs  made windview instrumentation conditionally compiled
  18. 01n,10oct95,jdi  doc: added .tG Shell to SEE ALSO for msgQShow().
  19. 01m,20may94,dvs  added level check for task delay list in msgQShow() (SPR 2966)
  20. 01m,16jan94,c_s  msgQShowInit () now initializes instrumented class.
  21. 01l,03feb93,jdi  changed INCLUDE_SHOW_RTNS to ...ROUTINES.
  22. 01k,02feb93,jdi  another doc tweak.
  23. 01j,02feb93,jdi  documentation tweaks.
  24. 01i,23nov92,jdi  documentation cleanup.
  25. 01h,13nov92,dnw  added include of smObjLib.h
  26. 01g,17sep92,pme  made msgQInfoGet() handle shared message Queue.
  27. 01f,30jul92,smb  changed format for printf to avoid zero padding.
  28. 01e,29jul92,pme  added NULL function pointer check for smObj routines.
  29. 01d,28jul92,jcf  changed msgQShowInit to call msgQLibInit.
  30. 01c,19jul92,pme  added shared message queue support.
  31.                  added #include "errnoLib.h".
  32. 01b,12jul92,jcf  changed level compare to >=
  33. 01a,15jun92,jcf  extracted from v1l of msgQLib.c.
  34. */
  35. /*
  36. DESCRIPTION
  37. This library provides routines to show message queue statistics,
  38. such as the task queuing method, messages queued, receivers blocked, etc.
  39. The routine msgQshowInit() links the message queue show facility into the
  40. VxWorks system.  It is called automatically when the message queue show
  41. facility is configured into VxWorks using either of the
  42. following methods:
  43. .iP
  44. If you use the configuration header files, define
  45. INCLUDE_SHOW_ROUTINES in config.h.
  46. .iP
  47. If you use the Tornado project facility, select INCLUDE_MSG_Q_SHOW.
  48. .LP
  49. INCLUDE FILES: msgQLib.h
  50. SEE ALSO: pipeDrv,
  51. .pG "Basic OS"
  52. */
  53. /* LINTLIBRARY */
  54. #include "vxWorks.h"
  55. #include "errnoLib.h"
  56. #include "intLib.h"
  57. #include "stdlib.h"
  58. #include "stdarg.h"
  59. #include "string.h"
  60. #include "stdio.h"
  61. #include "smObjLib.h"
  62. #include "private/msgQLibP.h"
  63. #include "private/kernelLibP.h"
  64. #include "private/taskLibP.h"
  65. #include "private/msgQSmLibP.h"
  66. #include "private/distObjTypeP.h"
  67. #include "private/eventLibP.h"
  68. #include "vxfusion/private/msgQDistLibP.h"
  69. /* globals */
  70. /* forward declarations */
  71. static BOOL msgQInfoEach (MSG_NODE *pNode, MSG_Q_INFO *pInfo);
  72. /******************************************************************************
  73. *
  74. * msgQShowInit - initialize the message queue show facility
  75. *
  76. * This routine links the message queue show facility into the VxWorks system.
  77. * It is called automatically when the message queue show facility is
  78. * configured into VxWorks using either of the following methods:
  79. * .iP
  80. * If you use the configuration header files, define
  81. * INCLUDE_SHOW_ROUTINES in config.h.
  82. * .iP
  83. * If you use the Tornado project facility, select INCLUDE_MSG_Q_SHOW.
  84. *
  85. * RETURNS: N/A
  86. */
  87. void msgQShowInit (void)
  88.     {
  89.     if (msgQLibInit () == OK)
  90. {
  91.         classShowConnect (msgQClassId, (FUNCPTR)msgQShow);
  92. #ifdef WV_INSTRUMENTATION
  93. classShowConnect (msgQInstClassId, (FUNCPTR)msgQShow);
  94. #endif
  95. }
  96.     }
  97. /*******************************************************************************
  98. *
  99. * msgQInfoEach - support routine for msgQInfoGet
  100. *
  101. * RETURNS: TRUE or FALSE
  102. */
  103. LOCAL BOOL msgQInfoEach
  104.     (
  105.     MSG_NODE *          pNode,
  106.     MSG_Q_INFO *        pInfo
  107.     )
  108.     {
  109.     if (pInfo->msgPtrList != NULL)
  110. pInfo->msgPtrList [pInfo->numMsgs] = MSG_NODE_DATA (pNode);
  111.     if (pInfo->msgLenList != NULL)
  112. pInfo->msgLenList [pInfo->numMsgs] = pNode->msgLength;
  113.     /* bump list count and signal quit (return FALSE) if we're at max */
  114.     return (++pInfo->numMsgs < pInfo->msgListMax);
  115.     }
  116. /*******************************************************************************
  117. *
  118. * msgQInfoGet - get information about a message queue
  119. *
  120. * This routine gets information about the state and contents of a message
  121. * queue.  The parameter <pInfo> is a pointer to a structure of type MSG_Q_INFO
  122. * defined in msgQLib.h as follows:
  123. *
  124. * .CS
  125. *  typedef struct /@ MSG_Q_INFO @/
  126. *     {
  127. *     int     numMsgs; /@ OUT: number of messages queued            @/
  128. *     int     numTasks; /@ OUT: number of tasks waiting on msg q     @/
  129. *     int     sendTimeouts; /@ OUT: count of send timeouts               @/
  130. *     int     recvTimeouts; /@ OUT: count of receive timeouts            @/
  131. *     int     options; /@ OUT: options with which msg q was created @/
  132. *     int     maxMsgs; /@ OUT: max messages that can be queued      @/
  133. *     int     maxMsgLength; /@ OUT: max byte length of each message      @/
  134. *     int     taskIdListMax; /@ IN: max tasks to fill in taskIdList       @/
  135. *     int *   taskIdList; /@ PTR: array of task IDs waiting on msg q   @/
  136. *     int     msgListMax; /@ IN: max msgs to fill in msg lists         @/
  137. *     char ** msgPtrList; /@ PTR: array of msg ptrs queued to msg q    @/
  138. *     int *   msgLenList; /@ PTR: array of lengths of msgs             @/
  139. *     } MSG_Q_INFO;
  140. * .CE
  141. *
  142. * If a message queue is empty, there may be tasks blocked on receiving.
  143. * If a message queue is full, there may be tasks blocked on sending.
  144. * This can be determined as follows:
  145. * .iP "" 4
  146. * If <numMsgs> is 0, then <numTasks> indicates the number of tasks blocked
  147. * on receiving.
  148. * .iP
  149. * If <numMsgs> is equal to <maxMsgs>, then <numTasks> is the number of
  150. * tasks blocked on sending.
  151. * .iP
  152. * If <numMsgs> is greater than 0 but less than <maxMsgs>, then <numTasks> 
  153. * will be 0.
  154. * .LP
  155. *
  156. * A list of pointers to the messages queued and their lengths can be
  157. * obtained by setting <msgPtrList> and <msgLenList> to the addresses of
  158. * arrays to receive the respective lists, and setting <msgListMax> to
  159. * the maximum number of elements in those arrays.  If either list pointer
  160. * is NULL, no data will be returned for that array.
  161. *
  162. * No more than <msgListMax> message pointers and lengths are returned,
  163. * although <numMsgs> will always be returned with the actual number of messages
  164. * queued.
  165. *
  166. * For example, if the caller supplies a <msgPtrList> and <msgLenList>
  167. * with room for 10 messages and sets <msgListMax> to 10, but there are 20
  168. * messages queued, then the pointers and lengths of the first 10 messages in
  169. * the queue are returned in <msgPtrList> and <msgLenList>, but <numMsgs> will
  170. * be returned with the value 20.
  171. *
  172. * A list of the task IDs of tasks blocked on the message queue can be obtained
  173. * by setting <taskIdList> to the address of an array to receive the list, and
  174. * setting <taskIdListMax> to the maximum number of elements in that array.
  175. * If <taskIdList> is NULL, then no task IDs are returned.  No more than
  176. * <taskIdListMax> task IDs are returned, although <numTasks> will always
  177. * be returned with the actual number of tasks blocked.
  178. *
  179. * For example, if the caller supplies a <taskIdList> with room for 10 task IDs
  180. * and sets <taskIdListMax> to 10, but there are 20 tasks blocked on the
  181. * message queue, then the IDs of the first 10 tasks in the blocked queue
  182. * will be returned in <taskIdList>, but <numTasks> will be returned with
  183. * the value 20.
  184. *
  185. * Note that the tasks returned in <taskIdList> may be blocked for either send
  186. * or receive.  As noted above this can be determined by examining <numMsgs>.
  187. *
  188. * The variables <sendTimeouts> and <recvTimeouts> are the counts of the number
  189. * of times msgQSend() and msgQReceive() respectively returned with a timeout.
  190. *
  191. * The variables <options>, <maxMsgs>, and <maxMsgLength> are the parameters
  192. * with which the message queue was created.
  193. *
  194. * WARNING
  195. * The information returned by this routine is not static and may be
  196. * obsolete by the time it is examined.  In particular, the lists of
  197. * task IDs and/or message pointers may no longer be valid.  However,
  198. * the information is obtained atomically, thus it will be an accurate
  199. * snapshot of the state of the message queue at the time of the call.
  200. * This information is generally used for debugging purposes only.
  201. *
  202. * WARNING
  203. * The current implementation of this routine locks out interrupts while
  204. * obtaining the information.  This can compromise the overall interrupt
  205. * latency of the system.  Generally this routine is used for debugging
  206. * purposes only.
  207. *
  208. * RETURNS: OK or ERROR.
  209. *
  210. * ERRNO: S_distLib_NOT_INITIALIZED, S_smObjLib_NOT_INITIALIZED,
  211. *        S_objLib_OBJ_ID_ERROR
  212. *
  213. */
  214. STATUS msgQInfoGet
  215.     (
  216.     MSG_Q_ID       msgQId,         /* message queue to query */
  217.     MSG_Q_INFO *   pInfo           /* where to return msg info */
  218.     )
  219.     {
  220.     int level;
  221.     Q_HEAD * pendQ;
  222.     if (ID_IS_SHARED (msgQId)) /* shared message Q */
  223.         {
  224. if (ID_IS_DISTRIBUTED (msgQId))     /* distributed message Q */
  225. {
  226. if (msgQDistInfoGetRtn == NULL)
  227. {
  228. errno = S_distLib_NOT_INITIALIZED;
  229. return (ERROR);
  230. }
  231. return ((*msgQDistInfoGetRtn) (msgQId, pInfo));
  232. }
  233.         if (msgQSmInfoGetRtn == NULL)
  234.             {
  235.             errno = S_smObjLib_NOT_INITIALIZED;
  236.             return (ERROR);
  237.             }
  238. return ((*msgQSmInfoGetRtn) (SM_OBJ_ID_TO_ADRS (msgQId), pInfo));
  239. }
  240.     /* message queue is local */
  241.     level = intLock (); /* LOCK INTERRUPTS */
  242.     if (OBJ_VERIFY (msgQId, msgQClassId) != OK)
  243. {
  244. intUnlock (level); /* UNLOCK INTERRUPTS */
  245. return (ERROR);
  246. }
  247.     /* tasks can be blocked on either the msg queue (receivers) or
  248.      * on the free queue (receivers), but not both.  Here we determine
  249.      * which queue to get task info from: if there are no msgs queued
  250.      * then there might be receivers pended, otherwise there might be
  251.      * senders pended.
  252.      */
  253.     if (msgQId->msgQ.count == 0)
  254. pendQ = &msgQId->msgQ.pendQ; /* might be receivers pended */
  255.     else
  256. pendQ = &msgQId->freeQ.pendQ; /* might be senders pended */
  257.     if (pInfo->taskIdList != NULL)
  258. {
  259. /* get list of tasks pended on this message queue */
  260. Q_INFO (pendQ, pInfo->taskIdList, pInfo->taskIdListMax);
  261. }
  262.     if ((pInfo->msgPtrList != NULL) || (pInfo->msgLenList != NULL))
  263. {
  264. /* get list of messages queued to this message queue */
  265. /* note: we use numMsgs field to hold count while we are filling
  266.  * in list so msgQInfoEach can remember the current index and
  267.  * know when to stop.  Afterwards, we fill in the actual numMsgs.
  268.  */
  269. pInfo->numMsgs = 0;
  270. if (pInfo->msgListMax > 0)
  271.     (void)Q_EACH (&msgQId->msgQ, msgQInfoEach, pInfo);
  272. }
  273.     pInfo->numMsgs = msgQId->msgQ.count;
  274.     pInfo->numTasks = Q_INFO (pendQ, NULL, 0); /* XXX ? */
  275.     pInfo->options = msgQId->options;
  276.     pInfo->maxMsgs = msgQId->maxMsgs;
  277.     pInfo->maxMsgLength = msgQId->maxMsgLength;
  278.     pInfo->sendTimeouts = msgQId->sendTimeouts;
  279.     pInfo->recvTimeouts = msgQId->recvTimeouts;
  280.     intUnlock (level); /* UNLOCK INTERRUPTS */
  281.     return (OK);
  282.     }
  283. /*******************************************************************************
  284. *
  285. * msgQShow - show information about a message queue
  286. *
  287. * This routine displays the state and optionally the contents of a message
  288. * queue.
  289. *
  290. * A summary of the state of the message queue is displayed as follows:
  291. * .CS
  292. *     Message Queue Id    : 0x3f8c20
  293. *     Task Queuing        : FIFO
  294. *     Message Byte Len    : 150
  295. *     Messages Max        : 50
  296. *     Messages Queued     : 0
  297. *     Receivers Blocked   : 1
  298. *     Send timeouts       : 0
  299. *     Receive timeouts    : 0
  300. *     Options             : 0x1       MSG_Q_FIFO
  301. *
  302. *     VxWorks Events
  303. *     --------------
  304. *     Registered Task     : 0x3f5c70 (t1)
  305. *     Event(s) to Send    : 0x1
  306. *     Options             : 0x7       EVENTS_SEND_ONCE
  307. *                                     EVENTS_ALLOW_OVERWRITE
  308. *                                     EVENTS_SEND_IF_FREE
  309. * .CE
  310. *
  311. * If <level> is 1, then more detailed information will be displayed.
  312. * If messages are queued, they will be displayed as follows:
  313. * .CS
  314. *     Messages queued:
  315. *       #    address length value
  316. *       1 0x123eb204    4   0x00000001 0x12345678
  317. * .CE
  318. *
  319. * If tasks are blocked on the queue, they will be displayed as follows:
  320. * .CS
  321. *     Receivers blocked:
  322. *
  323. *        NAME      TID    PRI DELAY
  324. *     ---------- -------- --- -----
  325. *     tExcTask     3fd678   0   21
  326. * .CE
  327. *
  328. * RETURNS: OK or ERROR.
  329. *
  330. * ERRNO: S_distLib_NOT_INITIALIZED, S_smObjLib_NOT_INITIALIZED
  331. *
  332. * SEE ALSO:
  333. * .pG "Target Shell,"
  334. * windsh,
  335. * .tG "Shell"
  336. */
  337. STATUS msgQShow
  338.     (
  339.     MSG_Q_ID    msgQId,         /* message queue to display */
  340.     int         level           /* 0 = summary, 1 = details */
  341.     )
  342.     {
  343.     MSG_Q_INFO info;
  344.     int taskIdList [20];
  345.     int taskDList [20];
  346.     char * msgPtrList [20];
  347.     int msgLenList [20];
  348.     WIND_TCB * pTcb;
  349.     STATUS status;
  350.     int         lock;
  351.     int         ix;
  352.     int         ix2;
  353.     char * pMsg;
  354.     int         len;
  355.     EVENTS_RSRC msgQEvResource;
  356.     if (ID_IS_SHARED (msgQId)) /* shared message Q */
  357.         {
  358. if (ID_IS_DISTRIBUTED (msgQId))     /* distributed message Q */
  359. {
  360. if (msgQDistShowRtn == NULL)
  361. {
  362. errno = S_distLib_NOT_INITIALIZED;
  363. return (ERROR);
  364. }
  365. return ((*msgQDistShowRtn) (msgQId, level));
  366. }
  367.         if (msgQSmShowRtn == NULL)
  368.             {
  369.             errno = S_smObjLib_NOT_INITIALIZED;
  370.             return (ERROR);
  371.             }
  372. return ((*msgQSmShowRtn) (SM_OBJ_ID_TO_ADRS (msgQId), level));
  373. }
  374.     /* message queue is local */
  375.     bzero ((char *) &info, sizeof (info));
  376.     if (level >= 1)
  377. {
  378. /* for detailed info, fill in array pointers in info structure */
  379. info.taskIdList = taskIdList;
  380. info.taskIdListMax = NELEMENTS (taskIdList);
  381. info.msgPtrList = msgPtrList;
  382. info.msgLenList = msgLenList;
  383. info.msgListMax = NELEMENTS (msgPtrList);
  384. }
  385.     lock = intLock (); /* LOCK INTERRUPTS */
  386.     if ((status = msgQInfoGet (msgQId, &info)) == ERROR)
  387. {
  388. intUnlock (lock); /* UNLOCK INTERRUPTS */
  389. printf ("Invalid message queue id: %#xn", (int)msgQId);
  390. return (ERROR);
  391. }
  392.     if ((info.numTasks > 0) && (level >= 1)) /* record task delays */
  393. {
  394. for (ix = 0; ix < min (info.numTasks, NELEMENTS (taskIdList)); ix++)
  395.     {
  396.     pTcb = (WIND_TCB *)(taskIdList [ix]);
  397.     if (pTcb->status & WIND_DELAY)
  398. taskDList[ix] = Q_KEY (&tickQHead, &pTcb->tickNode, 1);
  399.     else
  400. taskDList[ix] = 0;
  401.     }
  402. }
  403.     msgQEvResource = msgQId->events; /* record event info */ 
  404.     intUnlock (lock); /* UNLOCK INTERRUPTS */
  405.     /* show summary information */
  406.     printf ("n");
  407.     printf ("%-20s: 0x%-10xn", "Message Queue Id", (int)msgQId);
  408.     if ((info.options & MSG_Q_TYPE_MASK) == MSG_Q_FIFO)
  409. printf ("%-20s: %-10sn", "Task Queuing", "FIFO");
  410.     else
  411. printf ("%-20s: %-10sn", "Task Queuing", "PRIORITY");
  412.     printf ("%-20s: %-10dn", "Message Byte Len", info.maxMsgLength);
  413.     printf ("%-20s: %-10dn", "Messages Max", info.maxMsgs);
  414.     printf ("%-20s: %-10dn", "Messages Queued", info.numMsgs);
  415.     if (info.numMsgs == info.maxMsgs) 
  416. printf ("%-20s: %-10dn", "Senders Blocked", info.numTasks);
  417.     else
  418. printf ("%-20s: %-10dn", "Receivers Blocked", info.numTasks);
  419.     printf ("%-20s: %-10dn", "Send timeouts", info.sendTimeouts);
  420.     printf ("%-20s: %-10dn", "Receive timeouts", info.recvTimeouts);
  421.     printf ("%-20s: 0x%xt%s", "Options", info.options,
  422.             (info.options & MSG_Q_TYPE_MASK) == MSG_Q_FIFO ?
  423. "MSG_Q_FIFOn" : "MSG_Q_PRIORITYn");
  424.     if ((info.options & MSG_Q_EVENTSEND_ERR_NOTIFY) != 0)
  425. printf ("ttttMSG_Q_EVENTSEND_ERR_NOTIFYn");
  426.     /* display VxWorks events information */
  427.     eventRsrcShow (&msgQEvResource);
  428.     /* show detailed information */
  429.     if (level >= 1)
  430. {
  431. /* show blocked tasks */
  432. if (info.numTasks > 0)
  433.     {
  434.     printf ("n%s Blocked:n",
  435.     (info.numMsgs == info.maxMsgs) ? "Senders" : "Receivers");
  436.     printf ("n");
  437.     printf ("   NAME      TID    PRI TIMEOUTn");
  438.     printf ("---------- -------- --- -------n");
  439.     for (ix = 0; ix < min (info.numTasks, NELEMENTS (taskIdList)); ix++)
  440. printf ("%-11.11s%8x %3d %7un", 
  441. taskName (taskIdList [ix]),
  442. taskIdList [ix],
  443. ((WIND_TCB *)taskIdList [ix])->priority,
  444. taskDList[ix]);
  445.     }
  446. /* show queued messages */
  447. if (info.numMsgs > 0)
  448.     {
  449.     printf ("nMessages queued:n  #    address length valuen");
  450.     for (ix = 0; ix < min (info.numMsgs, NELEMENTS (msgPtrList)); ix++)
  451. {
  452. pMsg = msgPtrList [ix];
  453. len = msgLenList [ix];
  454. printf ("%3d %#10x  %4d ", ix + 1, (int)pMsg, len);
  455. for (ix2 = 0; ix2 < min (len, 20); ix2++)
  456.     {
  457.     if ((ix2 % 4) == 0)
  458. printf (" 0x");
  459.     printf ("%02x", pMsg [ix2] & 0xff);
  460.     }
  461. if (len > 20)
  462.     printf (" ...");
  463. printf ("n");
  464. }
  465.     }
  466. }
  467.     printf ("n");
  468.     return (OK);
  469.     }