📄 mem.c
字号:
/*
* Copyright 2006 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
* @(#) TCP/IP_Network_Developers_Kit 1.91.00.08 08-22-2006 (ndk-a08)
*/
//----------------------------------------------------------------------
// OS Demonstration Software
//----------------------------------------------------------------------
// File: mem.c
//
// Block Oriented Memory Manager
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//----------------------------------------------------------------------
#include <netmain.h>
#include <_oskern.h>
//-------------------------------------------------
// Raw Memory Configuration
//
// Total MAX Memory Allocation
#define RAW_PAGE_SIZE 3072
#define RAW_PAGE_COUNT 16
//-------------------------------------------------
// Memory Block Structures
//
// Memory Block
typedef struct {
uint Flags;
#define MBF_BUSY 0x8000
#define MBF_INDEXMASK 0x03FF
UINT8 bData[1];
} MEMORYBLOCK;
// P.I.T. Entry
typedef struct {
UINT8 *pPageStart;
uint PageSize;
uint BlockSize;
uint BlockSizeIdx;
uint BlocksPerPage;
uint AllocCount;
uint IdxFreeCheck;
} PITENTRY;
// P.I.T.
#pragma DATA_SECTION(pit, ".far:NDK_MMBUFFER");
PITENTRY pit[RAW_PAGE_COUNT];
#pragma DATA_SECTION(pitBuffer, ".far:NDK_MMBUFFER");
UINT8 pitBuffer[RAW_PAGE_SIZE*RAW_PAGE_COUNT];
// P.I.T. Info
uint PITCount = 0;
uint PITUsed = 0;
uint PITHigh = 0;
//-------------------------------------------------
// Memory Bucket Information
//
#define MEMORY_ID_COUNT 7
#define SMALLEST 48
#define LARGEST (RAW_PAGE_SIZE)
// Memory Slot Tracking
#pragma DATA_SECTION(Id2Size, ".far:NDK_MMBUFFER");
uint Id2Size[] = { SMALLEST, 96, 128, 256, 512, 1536, LARGEST };
// High Water Mark Tracking
int BlockMax[ MEMORY_ID_COUNT ];
int BlockCount[ MEMORY_ID_COUNT ];
int PageMax[ MEMORY_ID_COUNT ];
int PageCount[ MEMORY_ID_COUNT ];
static UINT32 mmCalls = 0;
static UINT32 mmFrees = 0;
static UINT32 mmFails = 0;
static UINT32 mmBulkCalls = 0;
static UINT32 mmBulkFails = 0;
static UINT32 mmBulkFrees = 0;
//-------------------------------------------------
// Code Start
//
// Initialize the Memory System
int _mmInit()
{
uint w;
// Init PIT
PITCount = RAW_PAGE_COUNT;
PITCount = PITHigh = PITUsed = 0;
for(w=0; w<RAW_PAGE_COUNT; w++)
{
pit[w].PageSize = RAW_PAGE_SIZE;
pit[w].pPageStart = pitBuffer + (RAW_PAGE_SIZE*w);
pit[w].BlockSize = 0;
PITCount++;
}
// Init Block Statistics
for(w=0; w<MEMORY_ID_COUNT; w++)
{
BlockMax[w] = 0;
BlockCount[w] = 0;
PageMax[w] = 0;
PageCount[w] = 0;
}
return(1);
}
// Initialize a new Page, subdividing into blocks
static void mmInitPage( uint PitIdx, uint SizeIdx )
{
uint w;
uint Inc;
UINT8* pb;
// Init the PIT Entry
pit[PitIdx].BlockSize = Id2Size[SizeIdx];
pit[PitIdx].BlockSizeIdx = SizeIdx;
pit[PitIdx].BlocksPerPage = pit[PitIdx].PageSize / Id2Size[SizeIdx];
pit[PitIdx].AllocCount = 0;
pit[PitIdx].IdxFreeCheck = 0;
// Init the Memory Blocks in the New Page
pb = pit[PitIdx].pPageStart;
Inc = pit[PitIdx].BlockSize;
for( w=0; w<pit[PitIdx].BlocksPerPage; w++ )
{
((MEMORYBLOCK *)pb)->Flags = PitIdx;
pb += Inc;
}
// Bump used count
PITUsed++;
if( PITUsed > PITHigh )
PITHigh = PITUsed;
// Maintian Page Block Statistics
w = pit[PitIdx].BlockSizeIdx;
PageCount[ w ]++;
if( PageCount[ w ] > PageMax[ w ] )
PageMax[ w ] = PageCount[ w ];
}
// Uninit an sub-divided Page
static void mmUnInitPage( uint PitIdx )
{
// Init the PIT Entry
pit[PitIdx].BlockSize = 0;
// Dec used count
PITUsed--;
// Maintian Page Block
PageCount[ pit[PitIdx].BlockSizeIdx ]--;
}
// Allocate Memory
void *mmAlloc( uint Size )
{
uint UseSizeIdx,UseSize;
uint PitIdx, PitFree, tmp1, tmp2;
MEMORYBLOCK* pmb;
uint CritState;
// Get index to bucket size, including memory block rsvd uint
UseSize = Size+sizeof(uint);
// Verify size request at boundary conditions first
if( UseSize <= SMALLEST )
UseSizeIdx = 0;
else if( UseSize > LARGEST )
return(0);
else
{
UseSizeIdx = MEMORY_ID_COUNT/2;
if( Id2Size[UseSizeIdx] >= UseSize )
{
while( Id2Size[UseSizeIdx-1] >= UseSize )
UseSizeIdx--;
}
else
{
while( Id2Size[UseSizeIdx] < UseSize )
UseSizeIdx++;
}
}
CritState = OEMSysCritOn();
mmCalls++;
// Look for a PIT already using this size
PitIdx = 0; // Index
tmp1 = 0; // Number of PITs examined
PitFree = PITCount; // Set "free" to invalid
while( PitIdx < PITCount )
{
// Only examined blocks currently in use
if( !pit[PitIdx].BlockSize )
PitFree = PitIdx;
else
{
// Bump the "examined" count of USED entries
tmp1++;
// See if we can use this page. It must be our size,
// plus have an entry available
if( pit[PitIdx].BlockSizeIdx == UseSizeIdx &&
pit[PitIdx].AllocCount < pit[PitIdx].BlocksPerPage )
goto MMA_PITVALID;
}
// If we've checked all the used entries and have a free entry,
// then use the free entry now
if( tmp1 == PITUsed && PitFree != PITCount )
{
// Set Free Page
PitIdx = PitFree;
// Initialize free page
mmInitPage( PitIdx, UseSizeIdx );
goto MMA_PITVALID;
}
// Nothing found yet - try next entry
PitIdx++;
}
// Here we didn't find a free or usable PIT, so we have an OOM
// error or a fatal error
if( PITUsed != PITCount )
DbgPrintf(DBG_ERROR,"mmAlloc: PIT Used Sync");
goto MMA_ERROR;
MMA_PITVALID:
// Allocate the Memory
UseSize = Id2Size[UseSizeIdx];
// Init our search point (tmp1) to the most likely free block
tmp1 = tmp2 = pit[PitIdx].IdxFreeCheck;
pmb = (MEMORYBLOCK *)(pit[PitIdx].pPageStart+(tmp1*UseSize));
// Find a free memory page
while( pmb->Flags & MBF_BUSY )
{
// Bump the pmb
if( ++tmp1 == pit[PitIdx].BlocksPerPage )
{
tmp1 = 0;
pmb = (MEMORYBLOCK *)(pit[PitIdx].pPageStart);
}
else
pmb = (MEMORYBLOCK *)((UINT8 *)pmb + UseSize );
// Check for error (tmp1 wrapped)
if( tmp1 == tmp2 )
{
// FATAL
DbgPrintf(DBG_ERROR,"mmAlloc: PIT FreeBlk Sync");
goto MMA_ERROR;
}
}
// Allocate the memory page
pmb->Flags |= MBF_BUSY;
pit[PitIdx].AllocCount++;
// Setup next possible free idx
if( ++tmp1 == pit[PitIdx].BlocksPerPage )
tmp1 = 0;
pit[PitIdx].IdxFreeCheck = tmp1;
// Maintain Block Statistics
BlockCount[ UseSizeIdx ]++;
if( BlockCount[ UseSizeIdx ] > BlockMax[ UseSizeIdx ] )
BlockMax[ UseSizeIdx ] = BlockCount[ UseSizeIdx ];
OEMSysCritOff( CritState );
return( pmb->bData );
MMA_ERROR:
mmFails++;
OEMSysCritOff( CritState );
return( 0 );
}
// Free Memory
void mmFree( void *p )
{
MEMORYBLOCK* pmb;
uint PitIdx;
uint CritState;
pmb = (MEMORYBLOCK *)((UINT8 *)p - sizeof(uint));
// Check for double free
if( !(pmb->Flags & MBF_BUSY) )
{
// FATAL
DbgPrintf(DBG_WARN,"mmFree: Double Free");
return;
}
// Get the index
PitIdx = (uint)(pmb->Flags & MBF_INDEXMASK);
CritState = OEMSysCritOn();
mmFrees++;
// Unallocate the block
pmb->Flags &= ~MBF_BUSY;
// Maintain Block
BlockCount[ pit[PitIdx].BlockSizeIdx ]--;
// Free the page if no blocks in use
if( !(--pit[PitIdx].AllocCount) )
mmUnInitPage( PitIdx );
OEMSysCritOff( CritState );
return;
}
// Memory Copy
void mmCopy( void* pDst, void* pSrc, uint len )
{
UINT32 *pSrc32, *pDst32;
UINT8 *pSrc8, *pDst8;
// Fast Case
if( !(((uint)pDst)&0x3) && !(((uint)pSrc)&0x3) )
{
pSrc32 = pSrc;
pDst32 = pDst;
while( len > 3 )
{
*pDst32++ = *pSrc32++;
len -= 4;
}
if( len )
{
pSrc8 = (UINT8 *)pSrc32;
pDst8 = (UINT8 *)pDst32;
while( len-- )
*pDst8++ = *pSrc8++;
}
}
else
{
pSrc8 = pSrc;
pDst8 = pDst;
while( len-- )
*pDst8++ = *pSrc8++;
}
}
// Memory Clear
void mmZeroInit( void *pDst, uint len )
{
UINT32 *pDst32;
UINT8 *pDst8;
pDst8 = pDst;
// Copy 'till aligned
while( (((uint)pDst8)&0x3) && len > 0 )
{
*pDst8++ = 0;
len--;
}
if( len )
{
pDst32 = (UINT32 *)pDst8;
// Copy 'till less than 4 bytes
while( len > 3 )
{
*pDst32++ = 0;
len -= 4;
}
if( len )
{
pDst8 = (UINT8 *)pDst32;
// Copy 'till done
while( len-- )
*pDst8++ = 0;
}
}
}
static uint BulkSegId = 0;
//-------------------------------------------------------------
// _mmBulkAllocSeg
//
// This function is used to change the default segment for
// mmBulkAlloc() and mmBulkFree(). This function will only
// work if no calls to mmBulkAlloc() have been made.
//-------------------------------------------------------------
void _mmBulkAllocSeg( uint segId )
{
uint CritState;
CritState = OEMSysCritOn();
if( !mmBulkCalls )
BulkSegId = segId;
OEMSysCritOff( CritState );
}
//-------------------------------------------------------------
// mmBulkAlloc
//
// This function is used to allocate memory larger than
// 3000 bytes
//-------------------------------------------------------------
void *mmBulkAlloc( INT32 Size )
{
UINT32 *ptr;
mmBulkCalls++;
Size += 8;
ptr = (UINT32 *)MEM_alloc( BulkSegId, Size, 4 );
if( ptr != MEM_ILLEGAL )
{
*ptr = 0x87654321;
*(ptr+1) = (UINT32)Size;
return( (void *)(ptr+2) );
}
mmBulkFails++;
return(0);
}
//-------------------------------------------------------------
// mmBulkFree
//
// This function is used to free memory allocated with
// mmBulkAlloc()
//-------------------------------------------------------------
void mmBulkFree( void *pMemory )
{
UINT32 *ptr = (UINT32 *)pMemory;
if( !ptr )
{
DbgPrintf(DBG_ERROR,"mmBulkFree: NULL pointer");
return;
}
ptr -= 2;
if( *ptr != 0x87654321 )
{
DbgPrintf(DBG_ERROR,"mmBulkFree: Corrupted mem or bad ptr (%08x)",ptr);
return;
}
mmBulkFrees++;
MEM_free( BulkSegId, ptr, *(ptr+1) );
}
//-------------------------------------------------------------
// Memory Check
//
// CallMode MMCHECK_MAP : Map out allocated memory, but
// don't dump ID's
// MMCHECK_DUMP : Dump allocated block ID's
// MMCHECK_SHUTDOWN : Dump allocated block's & free
//-------------------------------------------------------------
void _mmCheck( uint CallMode, int (*pPrn)(const char *,...) )
{
uint w;
UINT32 tmp;
uint SizeIdx;
UINT32 Total;
uint PitIdx;
if( !pPrn )
goto SHUTDOWN;
// Memory Usage
SizeIdx = 0;
Total = 0;
while( SizeIdx < MEMORY_ID_COUNT )
{
if( !(SizeIdx&3) )
(*pPrn)("\n");
(*pPrn)("%4u:%-4u ",BlockMax[SizeIdx],Id2Size[SizeIdx]);
tmp = (UINT32)(BlockMax[SizeIdx]) * (UINT32)(Id2Size[SizeIdx]);
Total += tmp;
if(tmp)
(*pPrn)("(%3d%%) ",
(tmp*100)/((UINT32)PageMax[SizeIdx]*(UINT32)RAW_PAGE_SIZE));
else
(*pPrn)(" ");
SizeIdx++;
}
(*pPrn)("\n(%u/", PITHigh*(UINT32)RAW_PAGE_SIZE);
(*pPrn)("%u", PITCount*(INT32)RAW_PAGE_SIZE);
(*pPrn)(" mmAlloc: %u/%u/%u,",mmCalls,mmFails,mmFrees);
(*pPrn)(" mmBulk: %u/%u/%u)\n",mmBulkCalls,mmBulkFails,mmBulkFrees);
// Walk Memory
if( PITUsed )
{
(*pPrn)("\n");
for( PitIdx=0; PitIdx<PITCount; PitIdx++ )
{
if( pit[PitIdx].BlockSize )
{
MEMORYBLOCK *pmb;
if( !pit[PitIdx].AllocCount )
(*pPrn)("IE: No blocks in alloced page\n");
else
(*pPrn)("%d blocks alloced in %d byte page\n",
pit[PitIdx].AllocCount, pit[PitIdx].BlockSize );
if( CallMode != MMCHECK_MAP )
{
w = 0;
while( w < pit[PitIdx].BlocksPerPage )
{
pmb = (MEMORYBLOCK *) (pit[PitIdx].pPageStart +
(w*pit[PitIdx].BlockSize));
if( pmb->Flags & MBF_BUSY )
(*pPrn)("(%04X) ", *((uint *)pmb->bData));
w++;
}
(*pPrn)("\n");
}
}
}
}
(*pPrn)("\n");
SHUTDOWN:
if( CallMode == MMCHECK_SHUTDOWN )
PITCount = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -