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

VxWorks

开发平台:

C/C++

  1. /* msgQSmShow.c - shared message queue show utility (VxMP Option) */
  2. /* Copyright 1990-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01k,06may02,mas  cache flush and volatile fix (SPR 68334); bridge flush fix
  7.  (SPR 68844)
  8. 01j,24oct01,mas  doc update (SPR 71149)
  9. 01i,17apr98,rlp  canceled msgQSmShow and msgQSmInfoGet modifications for
  10.                  backward compatibility.
  11. 01h,04nov97,rlp  modified msgQSmShow and msgQSmInfoGet for tracking messages
  12.                  sent.
  13. 01g,03feb93,jdi  changed INCLUDE_SHOW_RTNS to ...ROUTINES.
  14. 01f,29jan93,pme  added little endian support.
  15. 01e,13nov92,dnw  added include of smObjLib.h and smObjLibP.h
  16. 01d,02oct92,pme  added SPARC support. documentation cleanup.
  17. 01c,17sep92,pme  added msgQSmInfoGet and msgQSmInfoEach.
  18.                  implemented msgQSmShow.
  19. 01b,28jul92,jcf  changed msgQSmShowInit to call msgQLibInit.
  20. 01a,19jul92,pme  written
  21. */
  22. /*
  23. DESCRIPTION
  24. This library provides routines to show shared message queue statistics,
  25. such as task queueing method, messages queued, receivers blocked,
  26. and so forth.
  27. These routines are included automatically by including the component
  28. INCLUDE_SM_OBJ.
  29. There are no user callable routines.
  30. AVAILABILITY: This module is distributed as a component of the unbundled shared
  31. objects memory support option, VxMP.
  32. INCLUDE FILE: msgQSmLib.h
  33. SEE ALSO: msgQSmLib msgQLib smObjLib
  34. tb VxWorks Programmer's Guide: Shared Memory Objects",
  35. tb VxWorks Programmer's Guide: Basic OS
  36. NOROUTINES
  37. */
  38. /* LINTLIBRARY */
  39. #include "vxWorks.h"
  40. #include "string.h"
  41. #include "stdio.h"
  42. #include "stdlib.h"
  43. #include "cacheLib.h"
  44. #include "smObjLib.h"
  45. #include "netinet/in.h"
  46. #include "private/smObjLibP.h"
  47. #include "private/msgQSmLibP.h"
  48. /* forward declarations */
  49. LOCAL BOOL msgQSmInfoEach (SM_MSG_NODE * pNode, MSG_Q_INFO * pInfo);
  50. /*****************************************************************************
  51. *
  52. * msgQSmShowInit - initialize shared message queues show routine
  53. *
  54. * This routine links the shared memory message queues show and information get
  55. * routines into the VxWorks system.
  56. *
  57. * RETURNS: N/A
  58. *
  59. * NOMANUAL
  60. */
  61. void msgQSmShowInit (void)
  62.     {
  63.     if (msgQLibInit () == OK)
  64. {
  65. /*
  66.  * Initialize info and show routine pointer to allow msgQShow and
  67.  * msgQInfo to handle shared message queues ids.
  68.  */
  69. msgQSmShowRtn    = (FUNCPTR) msgQSmShow;
  70. msgQSmInfoGetRtn = (FUNCPTR) msgQSmInfoGet;
  71. }
  72.     }
  73. /*****************************************************************************
  74. *
  75. * msgQSmInfoEach - support routine for msgQSmInfoGet
  76. *
  77. * This routine fills the info structure at <pInfo> with the pointer to message
  78. * and message length.  It is called by smDllEach() for each message in the
  79. * message Queue.
  80. *
  81. * RETURNS: TRUE or FALSE
  82. *
  83. * NOMANUAL
  84. */
  85. LOCAL BOOL msgQSmInfoEach
  86.     (
  87.     SM_MSG_NODE * pNode,
  88.     MSG_Q_INFO * pInfo
  89.     )
  90.     {
  91.     if (pInfo->msgPtrList != NULL)
  92.         {
  93.         pInfo->msgPtrList [pInfo->numMsgs] = SM_MSG_NODE_DATA (pNode);
  94.         }
  95.     if (pInfo->msgLenList != NULL)
  96.         {
  97.         pInfo->msgLenList [pInfo->numMsgs] = ntohl (pNode->msgLength);
  98.         }
  99.     /* bump list count and signal quit (return FALSE) if we're at max */
  100.     return (++pInfo->numMsgs < pInfo->msgListMax);
  101.     }
  102. /*****************************************************************************
  103. *
  104. * msgQSmInfoGet - get information about a shared message queue
  105. *
  106. * This routine gets information about the state and contents of a shared
  107. * message queue.  The parameter <pInfo> is a pointer to a structure of type 
  108. * MSG_Q_INFO defined in msgQLib.h as follows:
  109. *
  110. * cs
  111. *  typedef struct               /@ MSG_Q_INFO @/
  112. *     {
  113. *     int     numMsgs;          /@ OUT: number of messages queued @/
  114. *     int     numTasks;         /@ OUT: number of tasks waiting on msg q @/
  115. *     int     sendTimeouts;     /@ OUT: count of send timeouts @/
  116. *     int     recvTimeouts;     /@ OUT: count of receive timeouts @/
  117. *     int     options;          /@ OUT: options with which msg q was created @/
  118. *     int     maxMsgs;          /@ OUT: max messages that can be queued @/
  119. *     int     maxMsgLength;     /@ OUT: max byte length of each message @/
  120. *     int     taskIdListMax;    /@ IN: max tasks to fill in taskIdList @/
  121. *     int *   taskIdList;       /@ PTR: array of task IDs waiting on msg q @/
  122. *     int     msgListMax;       /@ IN: max msgs to fill in msg lists @/
  123. *     char ** msgPtrList;       /@ PTR: array of msg ptrs queued to msg q @/
  124. *     int *   msgLenList;       /@ PTR: array of lengths of msgs @/
  125. *    } MSG_Q_INFO;
  126. * ce
  127. *
  128. * If a message queue is empty, there may be tasks blocked on receiving.
  129. * If a message queue is full, there may be tasks blocked on sending.
  130. * This can be determined as follows:
  131. * is
  132. * i `If'
  133. * <numMsgs> is 0, then <numTasks> indicates the number of tasks blocked
  134. * on receiving.
  135. * i `Else If'
  136. * <numMsgs> is equal to <maxMsgs>, then <numTasks> is the number of
  137. * tasks blocked on sending.
  138. * i `Else If'
  139. * <numMsgs> is greater than 0 but less than <maxMsgs>, <numTasks> will be 0.
  140. * ie
  141. *
  142. * A list of pointers to the messages queued and their lengths can be
  143. * obtained by setting <msgPtrList> and <msgLenList> to the addresses of
  144. * arrays to receive the respective lists, and setting <msgListMax> to
  145. * the maximum number of elements in those arrays.  If either list pointer
  146. * is NULL, no data will be returned for that array.
  147. *
  148. * No more than <msgListMax> message pointers and lengths are returned,
  149. * although <numMsgs> will always be returned with the actual number of messages
  150. * queued.
  151. *
  152. * For example, if the caller supplies a <msgPtrList> and <msgLenList>
  153. * with room for 10 messages and sets <msgListMax> to 10, but there are 20
  154. * messages queued, then the pointers and lengths of the first 10 messages in
  155. * the queue are returned in <msgPtrList> and <msgLenList>, but <numMsgs> will
  156. * be returned with the value 20.
  157. *
  158. * A list of the task IDs of tasks blocked on the message queue can be obtained
  159. * by setting <taskIdList> to the address of an array to receive the list, and
  160. * setting <taskIdListMax> to the maximum number of elements in that array.
  161. * If <taskIdList> is NULL, then no task IDs are returned.  No more than
  162. * <taskIdListMax> task IDs are returned, although <numTasks> will always
  163. * be returned with the actual number of tasks blocked.
  164. *
  165. * For example, if the caller supplies a <taskIdList> with room for 10 task IDs
  166. * and sets <taskIdListMax> to 10, but there are 20 tasks blocked on the
  167. * message queue, then the IDs of the first 10 tasks in the blocked queue
  168. * will be returned in <taskIdList>, but <numTasks> will be returned with
  169. * the value 20.
  170. *
  171. * Note that the tasks returned in <taskIdList> may be blocked for either send
  172. * or receive.  As noted above this can be determined by examining <numMsgs>.
  173. *
  174. * The variables <sendTimeouts> and <recvTimeouts> are the counts of the number
  175. * of times msgQSend() and msgQReceive() respectively returned with a timeout.
  176. *
  177. * The variables <options>, <maxMsgs>, and <maxMsgLength> are the parameters
  178. * with which the message queue was created.
  179. *
  180. * WARNING
  181. *
  182. * The information returned by this routine is not static and may be
  183. * obsolete by the time it is examined.  In particular, the lists of
  184. * task IDs and/or message pointers may no longer be valid.  However,
  185. * the information is obtained atomically, thus it will be an accurate
  186. * snapshot of the state of the message queue at the time of the call.
  187. * This information is generally used for debugging purposes only.
  188. *
  189. * WARNING
  190. * The current implementation of this routine locks out interrupts while
  191. * obtaining the information.  This can compromise the overall interrupt
  192. * latency of the system.  Generally this routine is used for debugging
  193. * purposes only.
  194. *
  195. * RETURNS: OK or ERROR.
  196. *
  197. * ERRNO: S_objLib_OBJ_ID_ERROR, S_smObjLib_LOCK_TIMEOUT
  198. *
  199. * NOMANUAL
  200. */
  201. STATUS msgQSmInfoGet
  202.     (
  203.     SM_MSG_Q_ID    smMsgQId, /* shared message queue to query */
  204.     MSG_Q_INFO *   pInfo /* where to return msg info */
  205.     )
  206.     {
  207.     int                  level;           /* interrupt lock return value */
  208.     SM_SEM_ID            pendSem;         /* shared sem on which tasks pend */
  209.     int                  numPendTasks;    /* number of pended tasks */
  210.     int                  smTcbList [100]; /* shared TCBs pending on msg Q */
  211.     SM_MSG_Q_ID volatile smMsgQIdv = (SM_MSG_Q_ID volatile) smMsgQId;
  212.     int                  temp;            /* temp storage */
  213.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  214.     temp = smMsgQIdv->verify;                   /* PCI bridge bug [SPR 68844]*/
  215.     if (SM_OBJ_VERIFY (smMsgQIdv) != OK)
  216. {
  217. return (ERROR);
  218. }
  219.     /* 
  220.      * Tasks can be blocked on either the msg queue (receivers) or
  221.      * on the free queue (receivers), but not both.  Here we determine
  222.      * which queue to get task info from: if there are no msgs queued
  223.      * then there might be receivers pended on the msg Q semaphore,
  224.      * otherwise there might be senders pended on the free Q semaphore.
  225.      */
  226.     
  227.     temp = smMsgQIdv->msgQSem.state.count;      /* PCI bridge bug [SPR 68844]*/
  228.     if (ntohl (smMsgQIdv->msgQSem.state.count) == 0)
  229.         {
  230. pendSem = &smMsgQId->msgQSem; /* might be receivers pended */
  231.         }
  232.     else
  233.         {
  234. pendSem = &smMsgQId->freeQSem; /* might be senders pended */
  235.         }
  236.     /* 
  237.      * Get number and list of pended tasks by calling semSmInfo() on
  238.      * the appropriate semaphore embedded in the message Queue.
  239.      * If only the number of tasks is needed we use an internal
  240.      * list, smTcbList, to call semSmInfo().
  241.      */
  242.      
  243.     if (pInfo->taskIdList != NULL)
  244. {
  245. numPendTasks = semSmInfo (pendSem, pInfo->taskIdList, 
  246.      pInfo->taskIdListMax);
  247. }
  248.     else 
  249. {
  250. numPendTasks = semSmInfo (pendSem, smTcbList, 100);
  251. }
  252.     /* 
  253.      * There is a possible inconsistency in the returned information
  254.      * if another CPU sends or receives a message between the time
  255.      * we get the number of tasks pended on the shared semaphore
  256.      * and the time we go through the list of messages.
  257.      * We can live with this problem since this routine
  258.      * is only here to give a snapshot of the status of the message
  259.      * queue and ID used only for debug.
  260.      */
  261.     if ((pInfo->msgPtrList != NULL) || (pInfo->msgLenList != NULL))
  262. {
  263. /* 
  264.  * Get list of messages queued to this message queue, before
  265.  * going through the message list we lock it access to avoid
  266.  * another CPU modifying the list.
  267.  */
  268. /* ENTER LOCKED SECTION */
  269.      if (SM_OBJ_LOCK_TAKE (&smMsgQId->msgQLock, &level) != OK)
  270.             {
  271.             smObjTimeoutLogMsg ("msgQInfoGet", (char *) &smMsgQId->msgQLock);
  272.             return (ERROR);                         /* can't take lock */
  273.             }
  274.         /* 
  275.  * Note: we use numMsgs field to hold count while we are filling
  276.          * in list so msgQSmInfoEach() can remember the current index and
  277.          * know when to stop.  Afterwards, we fill in the actual numMsgs.
  278.          */
  279. pInfo->numMsgs = 0;
  280. if (pInfo->msgListMax > 0)
  281.     {
  282.     (void) smDllEach (&smMsgQId->msgQ, (FUNCPTR) msgQSmInfoEach, 
  283.       (int) pInfo);
  284.     }
  285. /* EXIT LOCKED SECTION */
  286.      SM_OBJ_LOCK_GIVE (&smMsgQId->msgQLock, level);/* release lock */
  287. }
  288.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  289.     temp = smMsgQIdv->msgQSem.state.count;      /* PCI bridge bug [SPR 68844]*/
  290.     pInfo->numMsgs = ntohl (smMsgQIdv->msgQSem.state.count);
  291.     pInfo->numTasks = numPendTasks;
  292.     pInfo->options = ntohl (smMsgQIdv->options);
  293.     pInfo->maxMsgs = ntohl (smMsgQIdv->maxMsgs);
  294.     pInfo->maxMsgLength = ntohl (smMsgQIdv->maxMsgLength);
  295.     pInfo->sendTimeouts = ntohl (smMsgQIdv->sendTimeouts);
  296.     pInfo->recvTimeouts = ntohl (smMsgQIdv->recvTimeouts);
  297.     return (OK);
  298.     }
  299. /*****************************************************************************
  300. *
  301. * msgQSmShow - show information about a message queue
  302. *
  303. * This routine displays the state and optionally the contents of a shared 
  304. * message queue <smMsgQId>.
  305. *
  306. * A summary of the state of the message queue is displayed as follows:
  307. * cs
  308. *
  309. * Message Queue Id    : 0x7f8c21
  310. * Task Queuing        : FIFO
  311. * Message Byte Len    : 128
  312. * Messages Max        : 10
  313. * Messages Queued     : 0
  314. * Receivers Blocked   : 1
  315. * Send timeouts       : 0
  316. * Receive timeouts    : 0
  317. *
  318. * ce
  319. *
  320. * If <level> is 1, then more detailed information will be displayed.
  321. * If messages are queued, they will be displayed as follows:
  322. * cs
  323. *
  324. * Messages queued:
  325. *   #  local adrs length value
  326. *   1  0x123eb204    4   0x00000001 0x12345678
  327. * ce
  328. *
  329. * If tasks are blocked on the queue, they will be displayed as follows:
  330. * cs
  331. *
  332. * Receivers blocked:
  333. *
  334. * TID        CPU Number Shared TCB
  335. * ---------- ---------- ----------
  336. * 0xd0618        1      0x1364204
  337. *
  338. * ce
  339. *
  340. * RETURNS: OK or ERROR.
  341. *
  342. * ERRNO: S_objLib_OBJ_ID_ERROR, S_smObjLib_LOCK_TIMEOUT
  343. *
  344. * NOMANUAL
  345. */
  346. STATUS msgQSmShow 
  347.     (
  348.     SM_MSG_Q_ID smMsgQId, /* message queue to display */
  349.     int         level /* 0 = summary, 1 = details */
  350.     )
  351.     {
  352.     MSG_Q_INFO info; /* where to put msg Q informations */
  353.     int  smTcbList [40]; /* array of shared TCB pending on msg Q */
  354.     int msgPtrList [40];/* array of pointer to messages */
  355.     int  msgLenList [40];/* array of message length */
  356.     int ix; /* useful counter */
  357.     int ix2; /* useful counter */
  358.     char * pMsg; /* pointer to message content */
  359.     int len; /* message length */
  360.     bzero ((char *) &info, sizeof (info));
  361.     if (level >= 1)
  362.         {
  363.         /* for detailed info, fill in array pointers in info structure */
  364.         info.msgPtrList  = (char **) msgPtrList;
  365.         info.msgLenList  = msgLenList;
  366.         info.msgListMax  = NELEMENTS (msgPtrList);
  367.         }
  368.     /* 
  369.      * Even if we don't want a detailed list of tasks pended we need
  370.      * to fill taskIdList pointer to use semSmInfoGet to get the
  371.      * number of pended tasks.
  372.      */
  373.     info.taskIdList  = smTcbList;
  374.     info.taskIdListMax  = NELEMENTS (smTcbList);
  375.     /* get informations about message queue */
  376.     if (msgQSmInfoGet (smMsgQId, &info) == ERROR)
  377.         {
  378.         printf ("Invalid message queue id: %#xn", (unsigned int) smMsgQId);
  379.         return (ERROR);
  380.         }
  381.     /* show summary information */
  382.     printf ("n");
  383.     printf ("%-20s: 0x%-10xn", "Message Queue Id", 
  384.     SM_OBJ_ADRS_TO_ID (smMsgQId));
  385.     if ((info.options & MSG_Q_TYPE_MASK) == MSG_Q_FIFO)
  386.         {
  387.         printf ("%-20s: %-10sn", "Task Queuing", "FIFO");
  388.         }
  389.     else
  390.         {
  391.         printf ("%-20s: %-10sn", "Task Queuing", "PRIORITY");
  392.         }
  393.     printf ("%-20s: %-10dn", "Message Byte Len", info.maxMsgLength);
  394.     printf ("%-20s: %-10dn", "Messages Max", info.maxMsgs);
  395.     printf ("%-20s: %-10dn", "Messages Queued", info.numMsgs);
  396.     if (info.numMsgs == info.maxMsgs)
  397.         {
  398.         printf ("%-20s: %-10dn", "Senders Blocked", info.numTasks);
  399.         }
  400.     else
  401.         {
  402.         printf ("%-20s: %-10dn", "Receivers Blocked", info.numTasks);
  403.         }
  404.     printf ("%-20s: %-10dn", "Send timeouts", info.sendTimeouts);
  405.     printf ("%-20s: %-10dn", "Receive timeouts", info.recvTimeouts);
  406.     printf ("n");
  407.     /* show detailed information */
  408.     if (level >= 1)
  409.         {
  410.         /* show blocked tasks */
  411.         if (info.numTasks > 0)
  412.             {
  413.             printf ("%s Blocked:n",
  414.                     (info.numMsgs == info.maxMsgs) ? "Senders" : "Receivers");
  415.             printf ("n");
  416.             printf ("   TID     CPU Number Shared TCBn");
  417.             printf ("---------- ---------- ----------n");
  418.             for (ix = 0; ix < min (info.numTasks, NELEMENTS (smTcbList)); ix++)
  419.                 {
  420.                 printf ("%#-10x    %2d      %#-10xn",
  421.                         ntohl ((int)(((SM_OBJ_TCB *)smTcbList [ix])->localTcb)),
  422.                         ntohl (((SM_OBJ_TCB *)smTcbList [ix])->ownerCpu),
  423.                         (unsigned int) smTcbList[ix]);
  424.                 }
  425.     printf ("n");
  426.             }
  427.         /* show queued messages */
  428.         if (info.numMsgs > 0)
  429.             {
  430.             printf ("Messages queued:n  # local adrs length valuen");
  431.             for (ix = 0; ix < min (info.numMsgs, NELEMENTS (msgPtrList)); ix++)
  432.                 {
  433.                 pMsg = (char *) msgPtrList [ix];
  434.                 len  = msgLenList [ix];
  435.                 printf ("%3d %#10x  %4d   ", ix + 1, (unsigned int) pMsg, len);
  436.                 for (ix2 = 0; ix2 < min (len, 20); ix2++)
  437.                     {
  438.                     if ((ix2 % 4) == 0)
  439.                         {
  440.                         printf (" 0x");
  441.                         }
  442.                     printf ("%02x", pMsg [ix2] & 0xff);
  443.                     }
  444.                 if (len > 20)
  445.                     {
  446.                     printf (" ...");
  447.                     }
  448.                 printf ("n");
  449.                 }
  450.             }
  451.         }
  452.     printf ("n");
  453.     return (OK);
  454.     }