GUIAlloc.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:11k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/GUI
  4. *                        Universal graphic software for embedded applications
  5. *
  6. *                       (c) Copyright 2002, Micrium Inc., Weston, FL
  7. *                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
  8. *
  9. *              礐/GUI is protected by international copyright laws. Knowledge of the
  10. *              source code may not be used to write a similar product. This file may
  11. *              only be used in accordance with a license and should not be redistributed
  12. *              in any way. We appreciate your understanding and fairness.
  13. *
  14. ----------------------------------------------------------------------
  15. File        : GUIAlloc.C
  16. Purpose     : emWin dynamic memory management
  17. ----------------------------------------------------------------------
  18. Version-Date---Author-Explanation
  19. ----------------------------------------------------------------------
  20. 1.00    000107 RS     First version
  21. ----------------------------------------------------------------------
  22. Known problems:
  23. None.
  24. ----------------------------------------------------------------------
  25. Open issues:
  26. None.
  27. ----------------------------------------------------------------------
  28. Todo:
  29. Nothing.
  30. */
  31. #include <stddef.h>           /* needed for definition of NULL */
  32. #include <string.h>           /* for memcpy, memset */
  33. #include "GUI_Protected.H"
  34. #include "GUIDebug.h"
  35. #if GUI_ALLOC_SIZE==0
  36.   #error GUI_ALLOC_SIZE needs to be > 0 when using this module
  37. #endif
  38. /*
  39.   *****************************************************************
  40.   *
  41.   *              Config defaults
  42.   *
  43.   *****************************************************************
  44. */
  45. /* Permit automatic defragmentation when necessary */
  46. #ifndef GUI_ALLOC_AUTDEFRAG
  47.   #define GUI_ALLOC_AUTDEFRAG 1
  48. #endif
  49. #ifndef GUI_BLOCK_ALIGN
  50.   #define GUI_BLOCK_ALIGN 2    /* 2 means 4 bytes, 1 means 2 bytes */
  51.                               /* 1 can be used on 16-bit CPUs and
  52.                                  CPUs which do not require aligned
  53.                                  32-bit values (such as x86) */ 
  54. #endif
  55. #ifndef GUI_MAXBLOCKS
  56.   #define GUI_MAXBLOCKS (2+GUI_ALLOC_SIZE/32)
  57. #endif
  58. /*
  59.   *****************************************************************
  60.   *
  61.   *              Internal types and declarations
  62.   *
  63.   *****************************************************************
  64. */
  65. #if GUI_ALLOC_SIZE <32767
  66.   #define tALLOCINT I16
  67. #else
  68.   #define tALLOCINT I32
  69. #endif
  70. #if GUI_MAXBLOCKS >= 256
  71.   #define HANDLE U16
  72. #else
  73.   #define HANDLE U8
  74. #endif
  75. typedef struct {
  76.   tALLOCINT Off;       /* Offset of memory area */
  77.   tALLOCINT Size;      /* usable size of allocated block */
  78.   HANDLE Next;      /* next handle in linked list */
  79.   HANDLE Prev;
  80. } tBlock;
  81. /****************************************************************
  82. *
  83. *              Static data
  84. *
  85. *****************************************************************
  86. */
  87. GUI_HEAP GUI_Heap;       /* Public for debugging only */
  88. static tBlock aBlock[GUI_MAXBLOCKS];
  89. struct {
  90.   int       NumUsedBlocks, NumFreeBlocks, NumFreeBlocksMin;        /* For statistical purposes only */
  91.   tALLOCINT NumUsedBytes,  NumFreeBytes,  NumFreeBytesMin;
  92. } GUI_ALLOC;
  93. static char   IsInitialized =0;
  94. /*
  95.   ********************************************************************
  96.   *
  97.   *                 Macros for internal use
  98.   *
  99.   ********************************************************************
  100. */
  101. #define Min(v0,v1) ((v0>v1) ? v1 : v0)
  102. #define Max(v0,v1) ((v0>v1) ? v0 : v1)
  103. #define ASSIGN_IF_LESS(v0,v1) if (v1<v0) v0=v1
  104. #define HMEM2PTR(hMem) (void*)&GUI_Heap.abHeap[aBlock[hMem].Off]
  105. /*
  106.   ********************************************************************
  107.   *
  108.   *                    Internal routines
  109.   *
  110.   ********************************************************************
  111. */
  112. /*
  113.   *************************************************
  114.   *
  115.   *                 Size2LegalSize
  116.   *
  117.   *************************************************
  118.   returns: Legal allocation size
  119. */
  120. static int Size2LegalSize(int size) {
  121.   return (size + ((1<<GUI_BLOCK_ALIGN)-1)) & ~((1<<GUI_BLOCK_ALIGN)-1);
  122. }
  123.   
  124. /*
  125.   *************************************************
  126.   *
  127.   *                 FindFreeHandle
  128.   *
  129.   *************************************************
  130.   returns: Free handle
  131. */
  132. static GUI_HMEM FindFreeHandle(void) {
  133.   int i;
  134.   for (i=1; i< GUI_MAXBLOCKS; i++) {
  135.     if (aBlock[i].Size ==0)
  136.   return i;
  137.   }
  138.   GUI_DEBUG_ERROROUT1("Insufficient memory handles configured (GUI_MAXBLOCKS == %d (See GUIConf.h))", GUI_MAXBLOCKS);
  139.   return GUI_HMEM_NULL;
  140. }
  141. /*
  142.   *************************************************
  143.   *
  144.   *               Find hole in heap area
  145.   *
  146.   *************************************************
  147.   returns: Offset to the memory hole (if available)
  148.            -1 if not available
  149. */
  150. static GUI_HMEM FindHole(int Size) {
  151.   int i, iNext;
  152.   for (i=0; (iNext = aBlock[i].Next) != 0; i = iNext) {
  153.     int NumFreeBytes = aBlock[iNext].Off- (aBlock[i].Off+aBlock[i].Size);
  154.     if (NumFreeBytes>=Size)
  155.       return i;
  156.   }
  157. /* Check last block */
  158.   if (GUI_ALLOC_SIZE - (aBlock[i].Off+aBlock[i].Size) >= Size)
  159.     return i;
  160.   return -1;
  161. }
  162. /*
  163.   *************************************************
  164.   *
  165.   *             Create hole in heap area
  166.   *
  167.   *************************************************
  168.   returns: Offset to the memory hole (if available)
  169.            -1 if not available
  170. */
  171. static GUI_HMEM CreateHole(int Size) {
  172.   int i, iNext;
  173.   int r = -1;
  174.   for (i=0; (iNext =aBlock[i].Next) !=0; i= iNext) {
  175.     int NumFreeBytes = aBlock[iNext].Off- (aBlock[i].Off+aBlock[i].Size);
  176.     if (NumFreeBytes < Size) {
  177.       int NumBytesBeforeBlock = aBlock[iNext].Off - (aBlock[i].Off+aBlock[i].Size);
  178.       if (NumBytesBeforeBlock) {
  179.         U8* pData = &GUI_Heap.abHeap[aBlock[iNext].Off];
  180.         memmove(pData-NumBytesBeforeBlock, pData, aBlock[iNext].Size);
  181.         aBlock[iNext].Off -=NumBytesBeforeBlock;
  182.       }
  183.     }
  184.   }
  185. /* Check last block */
  186.   if (GUI_ALLOC_SIZE - (aBlock[i].Off+aBlock[i].Size) >= Size)
  187.     r = i;
  188.   return r;
  189. }
  190. static void CheckInit(void) {
  191.   if (!IsInitialized)
  192.     GUI_ALLOC_Init();
  193. }
  194. /*
  195.   ********************************************************************
  196.   *
  197.   *                  Exported routines
  198.   *
  199.   ********************************************************************
  200. */
  201. void GUI_ALLOC_Init(void) {
  202.   GUI_DEBUG_LOG("nGUI_ALLOC_Init...");
  203.   GUI_ALLOC.NumFreeBlocksMin = GUI_ALLOC.NumFreeBlocks = GUI_MAXBLOCKS-1;
  204.   GUI_ALLOC.NumFreeBytesMin  = GUI_ALLOC.NumFreeBytes  = GUI_ALLOC_SIZE;
  205.   GUI_ALLOC.NumUsedBlocks = 0;
  206.   GUI_ALLOC.NumUsedBytes = 0;
  207.   memset(&aBlock,0,sizeof(aBlock[0])*GUI_MAXBLOCKS);/////self
  208.   aBlock[0].Size = (1<<GUI_BLOCK_ALIGN);  /* occupy minimum for a block */
  209.   aBlock[0].Off  = 0;
  210.   aBlock[0].Next = 0;
  211.   IsInitialized =1;
  212. }
  213. static GUI_HMEM _Alloc(int size) {
  214.   GUI_HMEM hMemNew, hMemIns;
  215.   CheckInit();
  216.   size = Size2LegalSize(size);
  217.   /* Check if memory is available at all ...*/
  218.   if (size > GUI_ALLOC.NumFreeBytes) {
  219.     GUI_DEBUG_WARN1("GUI_ALLOC_Alloc: Insufficient memory configured (Trying to alloc % bytes)", size);
  220.     return 0;
  221.   }
  222.   /* Locate free handle */
  223.   if ((hMemNew = FindFreeHandle()) == 0)
  224.     return 0;
  225.   /* Locate or Create hole of sufficient size */
  226.   hMemIns = FindHole(size);
  227.   #if GUI_ALLOC_AUTDEFRAG
  228.     if (hMemIns == -1) {
  229.       hMemIns = CreateHole(size);
  230.     }
  231.   #endif
  232. /* Occupy hole */
  233.   if (hMemIns==-1) {
  234.     GUI_DEBUG_ERROROUT1("GUI_ALLOC_Alloc: Could not allocate %d bytes",size);
  235.     return 0;
  236. }
  237.   {
  238.     int Off = aBlock[hMemIns].Off+aBlock[hMemIns].Size;
  239.     int Next = aBlock[hMemIns].Next;
  240.     aBlock[hMemNew].Size  = size;
  241.     aBlock[hMemNew].Off   = Off;
  242.     if ((aBlock[hMemNew].Next  = Next) >0) {
  243.       aBlock[Next].Prev = hMemNew;  
  244.     }
  245.     aBlock[hMemNew].Prev  = hMemIns;
  246.     aBlock[hMemIns].Next  = hMemNew;
  247.   }
  248. /* Keep track of number of blocks and av. memory */
  249.   GUI_ALLOC.NumUsedBlocks++;
  250.   GUI_ALLOC.NumFreeBlocks--;
  251.   if (GUI_ALLOC.NumFreeBlocksMin > GUI_ALLOC.NumFreeBlocks) {
  252.     GUI_ALLOC.NumFreeBlocksMin = GUI_ALLOC.NumFreeBlocks;
  253.   }
  254.   GUI_ALLOC.NumUsedBytes += size;
  255.   GUI_ALLOC.NumFreeBytes -= size;
  256.   if (GUI_ALLOC.NumFreeBytesMin > GUI_ALLOC.NumFreeBytes) {
  257.     GUI_ALLOC.NumFreeBytesMin = GUI_ALLOC.NumFreeBytes;
  258.   }
  259. /* In order to be on the safe side, zeroinit ! */
  260.   memset(HMEM2PTR(hMemNew), 0, size);
  261.   return hMemNew;
  262. }
  263. GUI_HMEM GUI_ALLOC_Alloc(int size) {
  264.   GUI_HMEM hMem;
  265.  /* First make sure that init has been called */
  266.   GUI_LOCK();
  267.   GUI_DEBUG_LOG2("nGUI_ALLOC_Alloc... requesting %d, %d avail", size, GUI_ALLOC.NumFreeBytes);
  268.   hMem = _Alloc(size);
  269.   GUI_DEBUG_LOG1("nGUI_ALLOC_Alloc : Handle", hMem);
  270.   GUI_UNLOCK();
  271.   return hMem;
  272. }
  273. void GUI_ALLOC_Free(GUI_HMEM hMem) {
  274.   int Size;
  275.   if (hMem == GUI_HMEM_NULL)  /* Note: This is not an error, it is permitted */
  276.     return;
  277.   GUI_LOCK();
  278.   GUI_DEBUG_LOG1("nGUI_ALLOC_Free(%d)", hMem);
  279.   /* Do some error checking ... */
  280.   #if GUI_DEBUG_LEVEL>0
  281.     /* Block not allocated ? */
  282.     if (aBlock[hMem].Size==0) {
  283.       GUI_DEBUG_ERROROUT("GUI_ALLOC_Free(): Invalid hMem");
  284.       return;
  285.     }
  286.   #endif
  287.   Size = aBlock[hMem].Size;
  288.   #ifdef WIN32
  289.     memset(&GUI_Heap.abHeap[aBlock[hMem].Off], 0xcc, Size);
  290.   #endif
  291.   GUI_ALLOC.NumFreeBytes += Size;
  292.   GUI_ALLOC.NumUsedBytes -= Size;
  293.   aBlock[hMem].Size = 0;
  294.   {
  295.     int Next = aBlock[hMem].Next;
  296.     int Prev = aBlock[hMem].Prev;
  297.     aBlock[Prev].Next = Next;
  298.     if (Next)
  299.       aBlock[Next].Prev = Prev;
  300.   }  
  301.   GUI_ALLOC.NumFreeBlocks++;
  302.   GUI_ALLOC.NumUsedBlocks--;
  303.   GUI_UNLOCK();
  304. }
  305. void*       GUI_ALLOC_h2p   (GUI_HMEM  hMem) {
  306.   #if GUI_DEBUG_LEVEL>0
  307.     if (!hMem) {
  308.       GUI_DEBUG_ERROROUT("n"__FILE__ " GUI_ALLOC_h2p: illegal argument (0 handle)");
  309.       return 0;
  310.     }
  311.   #endif
  312.   return HMEM2PTR(hMem);
  313. }
  314. void GUI_ALLOC_FreePtr(GUI_HMEM *ph) {
  315.   GUI_LOCK();
  316.   GUI_ALLOC_Free(*ph);
  317.   *ph =0;
  318.   GUI_UNLOCK();
  319. }
  320. /*
  321.   ********************************************************************
  322.   *
  323.   *                  Exported info routines
  324.   *
  325.   ********************************************************************
  326. */
  327. int GUI_GetUsedMem(void) {
  328.   int NumUsedBytes=0;
  329.   int i;
  330.   GUI_LOCK();
  331.   CheckInit();
  332.   for (i=1; i; i = aBlock[i].Next) {
  333.     NumUsedBytes += aBlock[i].Size;
  334.   }
  335.   GUI_UNLOCK();
  336.   return NumUsedBytes;
  337. }
  338. int GUI_ALLOC_GetNumFreeBytes(void) {
  339.   CheckInit();
  340.   return GUI_ALLOC.NumFreeBytes;  
  341. }
  342. /*
  343.   *************************************************
  344.   *
  345.   *       GetMaxSize
  346.   *
  347.   *************************************************
  348.   Returns the biggest available blocksize
  349.   (without relocation)
  350. */
  351. int GUI_ALLOC_GetMaxSize(void) {
  352.   int r=0;
  353.   int NumFreeBytes;
  354.   int i, iNext;
  355.   GUI_LOCK();
  356.   CheckInit();
  357.   for (i=0; (iNext =aBlock[i].Next) !=0; i= iNext) {
  358.     NumFreeBytes = aBlock[iNext].Off- (aBlock[i].Off+aBlock[i].Size);
  359.     if (NumFreeBytes > r) {
  360.       r = NumFreeBytes;
  361.     }
  362.   }
  363. /* Check last block */
  364.   NumFreeBytes = (GUI_ALLOC_SIZE - (aBlock[i].Off+aBlock[i].Size));
  365.   if (NumFreeBytes > r) {
  366.     r = NumFreeBytes;
  367.   }
  368.   GUI_UNLOCK();
  369.   return r;
  370. }