IPC@CHIP® RTOS-PPC – API Documentation

Header image

Main page


RTX_Resources.c

This example demonstrates how to use the RTX_Count_Resources() and RTX_Wait_Queue() API to read out RTX resource usage information.

//
//  RTX_Resources.c  -  Example usage of RTX_Count_Resources()
//                     and RTX_Wait_Queue() API.

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <clib.h>

// Allocate a bit extra for buffers to cover for possible
//  new objects being added to system between calls.
#define ALLOC_PAD  (512)

// Append NIL char to the 4 character RTX object name.
static char * getObjName(char *buf, const char *name4)
{
  memcpy(buf, name4, 4) ;
  buf[4] = 0 ;
  return buf ;
}

// Make use of the report from RTX_Wait_Queue(RTX_FILT_TASK)
static void showTaskTree(RTX_DETAILS d, int objCnt)
{
  int frame_idx ;
  char name[5];
  printf("  %s task's calling tree depth: %d frames\r\n",
      getObjName(name, d.pTask->dtName),
      objCnt - 1) ;
  // Important for compatibility with future @Chip-RTOS versions!
  // Advance RTX_DETAIL_TASK object pointer by the number of
  //  bytes in @CHIP-RTOS's current RTX_DETAIL_TASK data structures,
  //  which might be larger than our concept of this structure.
  d.pByte += d.pTask->dtStructSize ;

  // Now d.pFrame reference an array of (objCnt -1) stack frame objects.
  for (frame_idx = 1 ; frame_idx < objCnt ; frame_idx++)
    {
      printf("  Stack frame %d) IP = 0x%08lX, Stack Frame Ptr = 0x%08lX\r\n",
          frame_idx, d.pFrame->rfIp, d.pFrame->rfIp) ;
      d.pFrame++ ;
    }
}       // showTaskTree()

// Apply the report from RTX_Wait_Queue() for objects with task queue.
static void
showWaitQ(RTX_DETAILS d, int objCnt)
{
  int idx;
  char name[5];
  // This may not be a Semaphore type object, but
  //  all names are at the same structure offset.
  printf("  %u task(s) waiting at %s\r\n", objCnt - 1,
      getObjName(name, d.pSem->dsName));

  // Advance pointer past the main RTX object.
  switch(d.pSem->dsType)
    {
      case KRTX_SEM_TYPE:
      d.pSem++;
      break;

      case KRTX_EVENT_GROUP_TYPE:
      d.pEvent++;
      break;

      case KRTX_MSG_XCHG_TYPE:
      d.pMsgXchg++;
      break;

      default:
      printf("ERROR: Invalid object type at showWaitQ()\r\n");
      return;
    }

  // Now d.pTask reference the array of RTX_DETAIL_TASK for
  //  the task's waiting on the above RTX object.
  for (idx = 1; idx < objCnt; idx++)
    {
      printf("  Queue pos %d) Task %s, handle 0x%X\r\n",
          idx,
          getObjName(name, d.pTask->dtName),
          d.pTask->dtHandle) ;

      // Important for compatibility with future @Chip-RTOS versions!
      // Advance RTX_DETAIL_TASK object pointer by the number of
      //  bytes in @CHIP-RTOS's current RTX_DETAIL_TASK data structures,
      //  which might be larger than our concept of this structure.
      d.pByte += d.pTask->dtStructSize ;
    }
}    // showWaitQ()

//  Demonstrate usage of RTX_Wait_Queue() API.
static void getWaitQ(RTX_ID handle, unsigned int filter)
{
  int retval ;
  size_t allocSize = 512 ;     // Size for first trial call.
  RTX_DETAILS details ;
  details.pBuf = NULL ;
  do
  {
    if (details.pBuf != NULL)
      {
        free(details.pBuf) ;
      }
    details.pBuf = malloc(allocSize) ;
    if (details.pBuf == NULL)
      {
        printf("malloc() failed in showWaitQ()\r\n") ;
        return ;                // Failure.
      }
    retval = RTX_Wait_Queue  ( handle,
                               details.pBuf,
                               allocSize,
                               filter  ) ;
    if (retval < 0)
      {
        // Need to re-allocate.
        allocSize = -retval + ALLOC_PAD ;
      }
  }
  while (retval < 0) ;

  if (retval == 0)
    {
      printf("RTX_Wait_Queue() call failed \r\n") ;
    }
  else if (filter == RTX_FILT_TASK)  // Special case?
    {
      showTaskTree(details, retval) ;
    }
  else
    {
      showWaitQ(details, retval) ;
    }
  free(details.pBuf) ;
}       // getWaitQ()


// Scan through array of RTX  objects reported by RTX_Count_Resources().
static void
parseRtxReport(RTX_DETAILS d, int objExpected, int byte_cnt)
{
  int objCnt = 0;
  char objName[5];
  while (byte_cnt > 0)
    {
      objCnt++ ;
      // Each RTX object report type has its 'dXtype' member at the same
      //  offset.  This allows us to use this for our switch prior to
      //  knowing exactly what type we have here.
      switch (d.pSem->dsType)
      {
      case KRTX_SEM_TYPE:
        byte_cnt -= sizeof(RTX_DETAIL_SEM);
        if (byte_cnt >= 0)
          {
            printf("Semaphore %s, handle 0x%X\r\n", getObjName(objName,
                d.pSem->dsName), d.pSem->dsHandle);
            getWaitQ(d.pSem->dsHandle, RTX_FILT_SEM) ;
          }
        d.pSem++;
        break;
      case KRTX_TIMER_TYPE:
        byte_cnt -= sizeof(RTX_DETAIL_TMR);
        if (byte_cnt >= 0)
          {
            printf("Timer: Period %lu ticks, callback 0x%lX\r\n",
                d.pTimer->drPeriod, (DWORD) d.pTimer->drCallback);
            // There is no "wait Q" concept for these objects.
          }
        d.pTimer++;
        break;

      case KRTX_EVENT_GROUP_TYPE:
        byte_cnt -= sizeof(RTX_DETAIL_EVENT);
        if (byte_cnt >= 0)
          {
            printf("Event Group %s\r\n", getObjName(objName, d.pEvent->deName));
            getWaitQ(d.pEvent->deHandle, RTX_FILT_EVENT_GROUP) ;
          }
        d.pEvent++;
        break;

      case KRTX_MSG_XCHG_TYPE:
        byte_cnt -= sizeof(RTX_DETAIL_MSGXCHG);
        if (byte_cnt >= 0)
          {
            printf("Message Exchange %s\r\n", getObjName(objName,
                d.pMsgXchg->dmName));
            getWaitQ(d.pMsgXchg->dmHandle, RTX_FILT_MSGXCHG) ;
          }
        d.pMsgXchg++;
        break;

      case KRTX_TASK_TYPE:
        if (byte_cnt < sizeof(RTX_DETAIL_TASK)) // Minimum size check.
          {
            printf("ERROR: incomplete RTX_DETAIL_TASK object\r\n");
            return;
          }
        byte_cnt -= d.pTask->dtStructSize; // Actual size.
        printf("Task %s\r\n", getObjName(objName, d.pTask->dtName));
        getWaitQ(d.pTask->dtHandle, RTX_FILT_TASK) ;

        // To allow for different size RTX_DETAIL_TASK objects
        //  in future RTOS releases, increment the array scanner
        //  by the reported structure byte count.
        d.pByte += d.pTask->dtStructSize;
        break;

      default:
        printf("ERROR: Invalid object type found\r\n");
        return;
        }
    }
  if (byte_cnt != 0)
    {
      printf("ERROR: unexpected number of bytes in object array\r\n");
    }
  if (objExpected != objCnt)
    {
      printf("ERROR: See %u objects, expected %u\r\n", objCnt, objExpected);
    }

} // parseRtxReport()



// Top level procedure here to demonstrate
//  use of RTX_Count_Resources() API.
void rtxResourceReadout(void)
{
  int objCnt ;
  size_t listBytes ;
  size_t allocSize = 1024 ;     // Size for first trial call.
  RTX_COUNTS counts ;
  RTX_DETAILS details ;
  details.pBuf = NULL ;
  do
  {
    if (details.pBuf != NULL)
      {
        free(details.pBuf) ;
      }
    details.pBuf = malloc(allocSize) ;
    if (details.pBuf == NULL)
      {
        printf("malloc() failed\r\n") ;
        return ;                // Failure.
      }
    listBytes = allocSize ;
    objCnt = RTX_Count_Resources ( &counts,
                                   details.pBuf,
                                   listBytes,
                                   0) ;  // Report all types
    allocSize = counts.nReport_Bytes + ALLOC_PAD ;
  }
  while ( listBytes < counts.nReport_Bytes ) ;

  if (objCnt < 0)
    {
      printf("RTX_Count_Resources() failed\r\n") ;
    }
  else
    {
      printf("RTX_Count_Resources() reported %u RTX objects\r\n",
              objCnt) ;
      parseRtxReport(details, objCnt, counts.nReport_Bytes) ;
    }
  free(details.pBuf) ;

}       // rtxResourceReadout()

// End RTX_Resources.c





Top of page | Main page

Copyright © 2017 Beck IPC GmbH
Generated on Thu Jan 26 16:21:35 2017 by Doxygen 1.6.1