Resources | developer.brewmp.com Resources | developer.brewmp.com

Developer

resources

Stress Heap utility

Stress Heap is a stress testing utility application. Stress Heap hogs the available heap space, and fragments it. Fragmentation uses either a minimum and maximum block size, or a heap dump log file (depending on the .ini file settings you provide). The default version uses the log file bclog1.log to hog the heap space. Stress Heap continues to run if you launch other applications on top of it.

Creating a heap analysis log file

To create your own heap analysis log file to use with Stress Heap, use the Heap Analyzer Tool. See the Tools Reference for more information.

Note: The Heap1Wrapper and OEM NotifyListener (components of Heap Analyzer) work only with Brew MP Platform 1.0.2.410 or higher.

Command-line parameters

Stress Heap command line parameters have two modes and are specified by the first parameter:

  • If the first parameter is a 1, then Stress Heap runs in file mode and the second parameter is a Heap Analyzer filename.
  • If the first parameter is a 0, then three more parameters must follow that.
These three parameters are large block size in bytes, small block size in bytes, and total free memory to be left in KB.

Requirements

To run the c_basicapp sample code, you need the following:

  • Brew MP 1.0 SDK rev 7.11.1 or higher
  • Brew MP-enabled device or a Simulator target
  • Installed copy of Sample Code from the SDK Manager

Sample code location

Filename

Location

Run application

stressheap

Sample code installation folder

  • Open the stressheap.sln in Visual Studio.
  • Compile the applet.
  • Click the Click2Run icon.

Event handling

Stress Heap is designed to run as a background application and has minimal event handling.

Example

The heap is filled with synthetic fragmentation information. When this information is set to be read from a file (.ini settings), it is reproduced node by node. For each entry in the log, a node is allocated on the heap of that size. This includes free blocks. If a block is intended to be on the small heap, but is too large, it is split into several smaller blocks. After all nodes are allocated or the device runs out of memory, a second pass is made, freeing the free blocks.
void FragmentHeapWithInputFile(StressHeap* pMe) 
{
   int iStart = GETUPTIMEMS();
   int iTime;

   if (!pMe->m_tModelStruct.m_bPartOneIsDone)
   {
      while (!pMe->m_tModelStruct.m_tFileData.m_bAddressIndexFound || 
         !pMe->m_tModelStruct.m_tFileData.m_bFreeIndexFound || 
         !pMe->m_tModelStruct.m_tFileData.m_bSizeIndexFound) 
      {
        char szElement[MAX_LINE_LENGTH];
        uint32 uElementIndex = 0;
        if (!ReadLine(&pMe->m_tModelStruct.m_tFileData.m_buffer, 
           pMe->m_tModelStruct.m_tFileData.m_szLine, MAX_LINE_LENGTH)) 
        {
          goto cleanup;  // empty or corrupt log?
        }
        while (ParseLineElement(pMe->m_tModelStruct.m_tFileData.m_szLine, 
           uElementIndex, szElement)) 
        {
          if (0 == STRNCMP(szElement, "Address", MAX_LINE_LENGTH)) 
          {
            pMe->m_tModelStruct.m_tFileData.m_bAddressIndexFound = TRUE;
            pMe->m_tModelStruct.m_tFileData.m_uAddressIndex = uElementIndex;
          } 
          else if (0 == STRNCMP(szElement, "free", MAX_LINE_LENGTH)) 
          {
            pMe->m_tModelStruct.m_tFileData.m_bFreeIndexFound = TRUE;
            pMe->m_tModelStruct.m_tFileData.m_uFreeIndex = uElementIndex;
          } 
          else if (0 == STRNCMP(szElement, "dwSize", MAX_LINE_LENGTH)) 
          {
            pMe->m_tModelStruct.m_tFileData.m_bSizeIndexFound = TRUE;
            pMe->m_tModelStruct.m_tFileData.m_uSizeIndex = uElementIndex;
          }
          else if (0 != STRSTR(szElement, "NodeCnt"))
          {
             pMe->m_tViewStruct.m_iTotalNodes = ATOI(STRSTR(szElement, ":") + 1);
          }

          ++uElementIndex;
        }
      }
      pMe->m_tModelStruct.m_bPartOneIsDone = TRUE; 
   }

   // Read and create nodes
   while (ReadNextNode(&pMe->m_tModelStruct.m_tFileData.m_buffer, 
      pMe->m_tModelStruct.m_tFileData.m_uAddressIndex, 
      pMe->m_tModelStruct.m_tFileData.m_uSizeIndex, 
      pMe->m_tModelStruct.m_tFileData.m_uFreeIndex,
      &pMe->m_tModelStruct.m_tFileData.m_uAddress, 
      &pMe->m_tModelStruct.m_tFileData.m_uSize, 
      &pMe->m_tModelStruct.m_tFileData.m_bAllocated))
   {
      if (pMe->m_tModelStruct.m_tFileData.m_bInSmallHeap && 
        pMe->m_tModelStruct.m_tFileData.m_pNode && 
        !StillInSmallHeap(pMe->m_tModelStruct.m_tFileData.m_uPrevEndAddress, 
        pMe->m_tModelStruct.m_tFileData.m_uAddress)) 
     {
        pMe->m_tModelStruct.m_tFileData.m_bInSmallHeap = FALSE;
     }
      pMe->m_tModelStruct.m_tFileData.m_uPrevEndAddress = 
         pMe->m_tModelStruct.m_tFileData.m_uAddress + 
         pMe->m_tModelStruct.m_tFileData.m_uSize;

      if (pMe->m_tModelStruct.m_tFileData.m_bInSmallHeap && 
          pMe->m_tModelStruct.uSmallHeapThreshold > 0 && 
          pMe->m_tModelStruct.m_tFileData.m_uSize > 
          pMe->m_tModelStruct.uSmallHeapThreshold) 
      {
         while (pMe->m_tModelStruct.m_tFileData.m_uSize > 0) 
         {
            uint32 uNodeSize = pMe->m_tModelStruct.m_tFileData.m_uSize 
            < pMe->m_tModelStruct.uSmallHeapThreshold ? 
            pMe->m_tModelStruct.m_tFileData.m_uSize 
            : pMe->m_tModelStruct.uSmallHeapThreshold;
            pMe->m_tModelStruct.m_tFileData.m_pNode = CreateNode(uNodeSize, 
            pMe->m_tModelStruct.m_tFileData.m_bAllocated);

         if (!pMe->m_tModelStruct.m_tFileData.m_pNode) 
         {
            goto cleanup;  // out of memory
         }
         pMe->m_tViewStruct.m_iNodesCompleted++;

       if (pMe->m_tModelStruct.m_tFileData.m_bAllocated)
       {
         UpdateDisplayValues(pMe, uNodeSize/4, 0);
       }
       else
       {
         UpdateDisplayValues(pMe, 0, uNodeSize/4);
       }
         
         AttachNode(pMe, pMe->m_tModelStruct.m_tFileData.m_pNode, 
            &pMe->m_tModelStruct.m_tFileData.m_pTailNode);
         pMe->m_tModelStruct.m_tFileData.m_uSize -= uNodeSize;
         }
      } 
     else 
     {
         pMe->m_tModelStruct.m_tFileData.m_pNode = 
            CreateNode(pMe->m_tModelStruct.m_tFileData.m_uSize, 
            pMe->m_tModelStruct.m_tFileData.m_bAllocated);
       if (!pMe->m_tModelStruct.m_tFileData.m_pNode) 
       {
            goto cleanup;  // out of memory
         }
      
       pMe->m_tViewStruct.m_iNodesCompleted++;

       if (pMe->m_tModelStruct.m_tFileData.m_bAllocated)
       {
         UpdateDisplayValues(pMe, pMe->m_tModelStruct.m_tFileData.m_uSize/4, 
              0);
       }
       else
       {
         UpdateDisplayValues(pMe, 0, pMe->m_tModelStruct.m_tFileData.m_uSize/4);
       }
       
       AttachNode(pMe, 
          pMe->m_tModelStruct.m_tFileData.m_pNode, 
          &pMe->m_tModelStruct.m_tFileData.m_pTailNode);
      }

     DrawCurrentMeter(pMe);
     iTime = GETUPTIMEMS();
     if ((iTime - iStart) > 1000 ||  (pMe->m_tViewStruct.m_iNodesCompleted%100 == 0) ) 
                                     
     {
#ifdef AEE_SIMULATOR
      ISHELL_SetTimer(pMe->piShell, 33, (PFNNOTIFY)FragmentHeapWithInputFile, pMe);
#else
      ISHELL_SetTimer(pMe->piShell, 10, (PFNNOTIFY)FragmentHeapWithInputFile, pMe);
#endif
      IRootContainer_Invalidate(pMe->m_pRoot, NULL, NULL, 0);
      return; //leave the function - will be called again when the timer triggers
     }
   }

cleanup: 
   ISHELL_CancelTimer(pMe->piShell, (PFNNOTIFY)FragmentHeapWithInputFile, pMe);
   FreeUnallocatedNodes(pMe);
   pMe->m_tViewStruct.m_iNodesCompleted = pMe->m_tViewStruct.m_iTotalNodes;
   UpdateDisplayValues(pMe, 0, 0);
   DrawCurrentMeter(pMe);
   IRootContainer_Invalidate(pMe->m_pRoot, NULL, NULL, 0);

   IQI_RELEASEIF(pMe->m_tModelStruct.m_tFileData.m_piLogFile);
   IQI_RELEASEIF(pMe->m_tModelStruct.m_tFileData.m_piFileMgr);
   return;
}

When the application is finished the nodes are freed (in the reverse order).

void FreeUnallocatedNodes(StressHeap *pMe) 
{
   Node *pNode = pMe->m_tModelStruct.pFirstNode;
   Node *pPrevNode = NULL;
   while (pNode) {
      if (!pNode->bAllocated) {
         Node *pNextNode = pNode->pNext;
         if (pPrevNode) {
            pPrevNode->pNext = pNextNode;
         }
         if (pMe->m_tModelStruct.pFirstNode == pNode) {
            pMe->m_tModelStruct.pFirstNode = pNextNode;
         }
         FREE(pNode);
         pNode = pNextNode;
         pMe->m_tModelStruct.uBlockCount -= 1;
      } else {
         pPrevNode = pNode;
         pNode = pNode->pNext;
      }
   }
}

Error handling

The Utility Panel application uses the following macros for error handling.

#define ERR_CATCH   __errcatch
#define ERR_TRY(x)  do{nErr = (x); if(AEE_SUCCESS != nErr) goto ERR_CATCH;} while(0)
#define ERR_THROW(e) do { nErr = (e); goto ERR_CATCH; } while(0)
#define ERR_CHECK_PTR(p)   if (NULL == p) ERR_THROW(AEE_EFAILED);