malloc.c

来自「An complete pmp solution for mattel juic」· C语言 代码 · 共 191 行

C
191
字号

#include "malloc.h"
#include "stdint.h"

//User-defined macros

#define chunkSetSize(ptr,size)  {     \
  (*(((u32*) ptr) - 2)) = (u32) size;      \
  (*(((u32*) ptr) + size)) = (u32) size;   \
  } 

#define chunkSetFreeSize(ptr,size)                              \
  {                                                              \
  *(((u32*) ptr) - 2) = ((u32) size )| (u32)0x10000000;          \
  *(((u32*) ptr) + size) = ((u32) size )| (u32)0x10000000;       \
  } 

#define chunkGetSize(ptr)        (*((u32*) ptr - 2) & 0x7FFFFFFF)
#define chunkID(ptr)   		     (*((u32*) ptr - 1))  
#define chunkNext(ptr) 		     (ptr + *((u32*) ptr - 2) + 3)
#define chunkPrev(ptr) 		     (ptr - *((u32*) ptr - 3) - 3)
#define chunkFreeNext(ptr)       (*((u32*) ptr))
#define chunkFreePrev(ptr)       (*((u32*) ptr - 1))
#define chunkFree(ptr)           (chunkGetSize(ptr) & 0x80000000)

void wMallocInit()
{
  xFreeList = uCRamStart + 2;
  u32 size = uCRamSize;
  chunkSetFreeSize(xFreeList, size);
  chunkFreeNext(xFreeList)=NULL;
  chunkFreePrev(xFreeList)=NULL;
}

void *wMalloc (u32 size)
{
  size = (size+3)>>2;
  
  xTChunk *xChunk = xFreeList;
  xTChunk *xNewChunk;
  xTChunk *xNewFreeChunk;
  
  if ( chunkGetSize(xFreeList) > size + 3)
	  {
	  xNewChunk = xChunk;    
	  chunkSetSize(xNewChunk, size);  
	  //chunkSetID
	  
	  //go to the start of the space left
	  xNewFreeChunk = chunkNext(xNewChunk);
	  //store the size of left area
	  chunkSetFreeSize(xNewFreeChunk, chunkGetSize(xFreeList) - size - 3);
      //now we only have to correct the links within the freelist
      if (xFreeList == xNewChunk) 
		{
		//the case whe we are changing the first item
		chunkFreePrev(xNewFreeChunk) = NULL;
		chunkFreeNext(xNewFreeChunk) = chunkFreeNext(xNewChunk);
		xFreeList = xNewFreeChunk;
		return xNewChunk;
		}
	  }

  while(chunkFreeNext(xChunk))
    {
	u32 currSize = chunkGetSize(xChunk);
	//if we have a chunk larger than we need
	if (currSize > size + 3)
	  {
	  xNewChunk = xChunk;    
	  chunkSetSize(xNewChunk, size);  
	  //chunkSetID
	  
	  //go to the start of the space left
	  xNewFreeChunk = chunkNext(xNewChunk);
	  //store the size of left area
	  chunkSetFreeSize(xNewFreeChunk, currSize - size - 3);
	    
	  //we have to remove the item from freelist anyway
	  //because we are probably writing to list end, we must check it
	  if (chunkFreeNext(xNewChunk))
	    chunkFreePrev(chunkFreeNext(xNewChunk)) = chunkFreePrev(xNewChunk);
	  chunkFreeNext(chunkFreePrev(xNewChunk)) = chunkFreeNext(xNewChunk);
	  
	  //we have removed the item from the list so we now can add it simply
	  wFree (xNewFreeChunk);
	  return xNewChunk;
	  }
	
	if (currSize > size )
	  {
	  chunkSetSize (xChunk, currSize);
	  //we are NOT changing the first item
	  if (chunkFreeNext(xChunk))
	     chunkFreePrev(chunkFreeNext(xChunk)) = chunkFreePrev(xChunk);
      chunkFreeNext(chunkFreePrev(xChunk)) = chunkFreeNext(xChunk);
	  return xChunk;
	  }
	
	xChunk = chunkFreeNext(xChunk);
	}
  
  return NULL;
};
//----------------------------------------------------------
void wFree (u32 *mem)
{
  return;
  if (mem == NULL) return;
  
  xTChunk *xChunk;
  
  u32 size = chunkGetSize(mem);
  xChunk = chunkPrev(mem);
  //check the block before the freed region
  if (chunkFree(xChunk))
    {
	//remove it from freelist
	if (chunkFreeNext(xChunk))
	  chunkFreePrev(chunkFreeNext(xChunk)) = chunkFreePrev(xChunk);
	if (chunkFreePrev(xChunk))
      chunkFreeNext(chunkFreePrev(xChunk)) = chunkFreeNext(xChunk);
	  else
        {
		if (chunkFreeNext(xChunk))
    	  xFreeList = chunkFreeNext(xChunk);
		  else
		    {
			size += chunkSize(xChunk) + 3;
        	chunkSetFreeSize(xChunk, size);
			xFreeList = xChunk;
			return;
			}
	    }
	size += chunkSize(xChunk) + 3;
	chunkSetFreeSize(xChunk, size);
	mem = xChunk;
	}
    
  xChunk = chunkNext(mem);
  //check the block next to the freed region
  if (chunkFree(xChunk))
    {
	//remove it from freelist
	if (chunkFreeNext(xChunk))
	  chunkFreePrev(chunkFreeNext(xChunk)) = chunkFreePrev(xChunk);
	if (chunkFreePrev(xChunk))
      chunkFreeNext(chunkFreePrev(xChunk)) = chunkFreeNext(xChunk);
	  else 
	    {
		if (chunkFreeNext(xChunk))
    	  xFreeList = chunkFreeNext(xChunk);
		  else
		    {
			size += chunkGetSize(xChunk) + 3;
        	chunkSetFreeSize(mem, size);
			xFreeList = mem;
			return;
			}
	    }
	size += chunkGetSize(xChunk) + 3;
	chunkSetFreeSize(mem, size);
	}
	
  if(chunkGetSize(xFreeList)>size)
    {
	if (chunkFreeNext(xFreeList))
	  chunkFreePrev(chunkFreeNext(xFreeList)) = mem;
	chunkFreePrev(mem) = NULL;
	xFreeList = mem;
	return;
	}
	
  xChunk = xFreeList;
  
  while ((chunkGetSize(xChunk)<size)&&(chunkFreeNext(xChunk)))
    {
	xChunk = chunkFreeNext(xChunk);
	}
  if (chunkFreeNext(xFreeList))
    {
	chunkFreePrev(chunkFreeNext(xFreeList)) = mem;
	chunkFreeNext(mem) = chunkFreeNext(xFreeList);
	}
  chunkFreeNext(chunkFreePrev(xFreeList)) = mem;
  chunkFreePrev(mem) = chunkFreePrev(xFreeList);
  return;
}

//--------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?