📄 tmshmem.c
字号:
/*----------------------------------------------------------------------------
COPYRIGHT (c) 1995 by Philips Semiconductors
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED AND COPIED IN
ACCORDANCE WITH THE TERMS AND CONDITIONS OF SUCH A LICENSE AND WITH THE
INCLUSION OF THE THIS COPY RIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES
OF THIS SOFTWARE MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER
PERSON. THE OWNERSHIP AND TITLE OF THIS SOFTWARE IS NOT TRANSFERRED.
THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT ANY PRIOR NOTICE
AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY Philips Semiconductor.
PHILIPS ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE
ON PLATFORMS OTHER THAN THE ONE ON WHICH THIS SOFTWARE IS FURNISHED.
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
FILE /rtos/microkernel/memory.cpp
#define TR Tilakraj Roy
940424 TR Created
940827 TR Documented new algorithms
960925 TR Pulled in sources for tmman
960927 TR Created interfaces for tmman
ABOUT
This file contains the dynamic memory allocation
routines required by the application to allocate
and free memory as and when required. With the
current implementation the kernel data structures
are statically allocated. This is done to maintain
alogorithm simplicity. Since we are manipulating
linked lists. These functions have to acquire the
lock to the memory manager data structure.This is
not implemented currently.
MEM_BLOCK
+----------+ <--------MEM_MGR_OBJECT.pHead
+------>| pPrev |---> NULL
| | pNext |---+
| +--| pData | |
| | | Length | |
| | +----------+ |
| +->| | |
| | | |
| | Allocated| |
| | Block | |
| | | |
| | | |
| +----------+ |
+-------| pPrev |<--+
| pNext |---> NULL
+--| pData |
| | Length |
| +----------+
+->| |
| |
| Free |
| Block |
| |
| |
+----------+
The above diagram shows the me memory layout after the calls to memCreate()
and memAlloc().
MEM_MGR_OBJECT points to the first SHMEM_BLOCK after the call to
memCreate(). SHMEM_BLOCK points to the entire free memory.
After the first call to memAllocate() a new memory block is created that
points to the remaining free space and the original SHMEM_BLOCK points
to the memory that was allocated as a result of this call to memAlloc().
----------------------------------------------------------------------------*/
#define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <vxdwraps.h>
/*----------------------------------------------------------------------------
DRIVER SPECIFIC INCLUDE FILES
----------------------------------------------------------------------------*/
#include "vxstd.h"
#include "vxwin.h"
#include "vxdbg.h"
#include "tmwincom.h"
#include "tmshare.h"
#include "tmshmem.h"
#pragma VxD_LOCKED_CODE_SEG
#pragma VxD_LOCKED_DATA_SEG
#define COLLAPSE(x) ((x)>>2)
#define EXPAND(x) ((x)<<2)
VOID shmemDebugDump ( PVOID pDevice );
STATUS shmemCreate ( DWORD Length , PVOID pContainer, PVOID *ppShmem )
{
PSHMEM_MGR_OBJECT this;
PSHMEM_BLOCK pMemory;
DWORD Status;
if ( *ppShmem == NULL )
{
if ( ( this = (PSHMEM_MGR_OBJECT)vxdMalloc (
sizeof ( SHMEM_MGR_OBJECT ) ) ) == NULL )
{
Status = TM_STATUS ( TMSHMEM_ERR_SHMEMMGRMALLOCFAIL );
goto shmemCreate_fail1;
}
}
else /* Shmem object ia already allocated we have to init it */
{
this = *ppShmem;
}
this->Size = sizeof ( SHMEM_MGR_OBJECT );
this->Length = Length;
this->pContainer = pContainer;
if ( ! ( this->pLinear =
(PVOID)winPageAllocate ( ( (this->Length >> 12) + 1 ), PG_SYS, 0,
0, 0, 0xffffffff,
&this->Physical,
PAGEZEROINIT | PAGEFIXED | PAGECONTIG | PAGEUSEALIGN,
&this->Handle ) ) )
{
Status = TM_STATUS ( TMSHMEM_ERR_PAGEALLOCFAIL );
goto shmemCreate_fail2;
}
/* page allocation failure here */
this->Free = this->Length - sizeof(SHMEM_BLOCK);
/* initialize the free memory block pointer */
pMemory = (PSHMEM_BLOCK)this->pLinear;
pMemory->pPrev = NULL;
pMemory->pNext = NULL;
pMemory->Flags.Allocated = FALSE;
pMemory->Flags.Length = COLLAPSE(this->Free);
pMemory->pData = pMemory;
((PSHMEM_BLOCK)pMemory->pData)++;
/* register the debugging callback */
dbgRegister ( shmemDebugDump, "Shared Memory Manager");
/* initialize the head ptr of the memory block */
this->pHead = pMemory;
*ppShmem = this;
return TMOK;
shmemCreate_fail2:
vxdFree ( this );
shmemCreate_fail1:
return Status;
}
STATUS shmemAllocate (PVOID pShmem, DWORD Flags, DWORD UnAlignedLength,
PVOID *pLinear, PDWORD pPhysical )
{
PSHMEM_MGR_OBJECT this = (PSHMEM_MGR_OBJECT)pShmem;
PSHMEM_BLOCK pMemory, pFreeMemory;
STATUS Status;
DWORD Length;
Length = ( UnAlignedLength + 0x4 ) & 0xfffffffc;
DP(8,"TM:shmemAllocate:ReqLen[%x]:AlignedSize[%x]:AvailLen[%x]\n",UnAlignedLength, Length, this->Free );
if ((Length + sizeof( SHMEM_BLOCK)) > this->Free)
{
DP(0,"TM:shmemAllocate:NO MORE SHARED MEMORY:FAIL\n" );
Status = TM_STATUS( TMSHMEM_ERR_OUTOFMEMORY );
return Status;
}
for (pMemory = this->pHead; pMemory ; pMemory = pMemory->pNext)
{
/*
if the current control blcok is allocated or
it is too small to satisfy this request, then
go tho the next block
*/
if( (pMemory->Flags.Allocated) ||
(EXPAND(pMemory->Flags.Length) < Length) )
continue;
/*
Since we are storing the data & the control block
in the same area, there is no point in
alloacting a control block for a buffer size <
sizeof ( control block ). This is what I check
below and if the above is true I allocate the
entire memory block to the application.
*/
if( EXPAND(pMemory->Flags.Length) > (Length + 2 * sizeof(SHMEM_BLOCK)) )
{
/* allocate a new SHMEM_BLOCK in the free space */
pFreeMemory =
(PSHMEM_BLOCK)(((PBYTE)pMemory->pData) + Length);
/* get the doubly link list pointers set */
pFreeMemory->pPrev = pMemory;
pFreeMemory->pNext = pMemory->pNext;
if(pMemory->pNext)
pMemory->pNext->pPrev = pFreeMemory;
pMemory->pNext = pFreeMemory;
/*
the rest of free memory minus the new block header
we are using to tag the free memory
*/
pFreeMemory->Flags.Length =
COLLAPSE( EXPAND(pMemory->Flags.Length) - ( Length + sizeof(SHMEM_BLOCK) ) );
/* the free block of memory is split into two parts */
pMemory->Flags.Length = COLLAPSE(Length);
/* pMemory points to the newly allcoated block */
pMemory->Flags.Allocated = TRUE;
/* pNew Memory points to the remaining free space */
pFreeMemory->Flags.Allocated = FALSE;
pFreeMemory->pData = (PVOID)pFreeMemory;
((PSHMEM_BLOCK)pFreeMemory->pData)++;
*pLinear = pMemory->pData;
*pPhysical =
( ((PBYTE)*pLinear) - ((PBYTE)this->pLinear) ) +
this->Physical;
this->Free -= (Length + sizeof(SHMEM_BLOCK));
}
else /* memory too small to allocate another control block */
{
/* return the entire free block */
pMemory->Flags.Allocated = TRUE;
*pLinear = pMemory->pData;
*pPhysical =
( ((PBYTE)*pLinear) - ((PBYTE)this->pLinear) ) +
this->Physical;
this->Free -= EXPAND(pMemory->Flags.Length);
}
return TMOK;
}
return Status;
}
STATUS shmemFree(PVOID pShmem, PVOID Buffer)
{
PSHMEM_MGR_OBJECT this = (PSHMEM_MGR_OBJECT)pShmem;
PSHMEM_BLOCK pMemory = (PSHMEM_BLOCK)Buffer;
pMemory--; /* memory now points to SHMEM_BLOCK */
if ( pMemory->pData != Buffer )
{
DP(0,"TM:shmemFree:Buffer[%x]:INVALID BLOCK POINTER\n", Buffer );
return TM_STATUS ( TMSHMEM_ERR_INVALIDPTR );
}
if ( ! pMemory->Flags.Allocated )
{
DP(0,"TM:shmemFree:Buffer[%x]:ALLOCATED FLAG NOT SET\n", Buffer );
return TM_STATUS ( TMSHMEM_ERR_INVALIDPTR );
}
pMemory->Flags.Allocated = FALSE;
this->Free += EXPAND(pMemory->Flags.Length);
/* check if we are dealing with the first control block */
if( pMemory->pPrev != NULL )
{
/*
if the previous block also free then we combine
the two blocks in to a single one to prevent
fragmentation.
*/
if (pMemory->pPrev->Flags.Allocated == FALSE )
{
/* remove this block from the doubly link list. */
/* adjust the next pointer of the previous block */
pMemory->pPrev->pNext = pMemory->pNext;
/* adjust the previous pointer of the next block */
pMemory->pNext->pPrev = pMemory->pPrev;
/*
add the length of the current block to the previous
block, also we are going to get rid of the current
MEMORY_OBJECT so add the size of that to the
previous block and to the memory manager free space
*/
pMemory->pPrev->Flags.Length = COLLAPSE ( EXPAND ( pMemory->pPrev->Flags.Length ) +
EXPAND( pMemory->Flags.Length) + sizeof ( SHMEM_BLOCK ) );
this->Free += sizeof ( SHMEM_BLOCK );
/* make the pMemory point to the previous node. */
pMemory = pMemory->pPrev;
}
}
/* NOTE : now pMemory points to the previous SHMEM_BLOCK */
/* check if we are dealing with the last control block */
if( pMemory->pNext != NULL)
{
/*
if the next node is free, we have to combine that
too into the previous block. we always combine
with the previous block.
*/
if( pMemory->pNext->Flags.Allocated == FALSE )
{
/* pMemory always points to the block that has to be removed */
pMemory = pMemory->pNext;
/* remove this block from the doubly link list. */
pMemory->pPrev->pNext = pMemory->pNext;
pMemory->pNext->pPrev = pMemory->pPrev;
/* adjust the length */
pMemory->pPrev->Flags.Length =
COLLAPSE ( EXPAND( pMemory->pPrev->Flags.Length ) +
EXPAND (pMemory->Flags.Length) + sizeof ( SHMEM_BLOCK ) );
this->Free += sizeof ( SHMEM_BLOCK );
}
}
DP(8,"TM:shmemFree:FreedLength[%x]:AvailLen[%x]\n",EXPAND(pMemory->Flags.Length), this->Free );
return TMOK;
}
VOID shmemDestroy ( PVOID pShmem )
{
PSHMEM_MGR_OBJECT this = (PSHMEM_MGR_OBJECT)pShmem;
winPageFree (this->Handle);
this->Size = 0;
vxdFree ( this );
}
VOID shmemDebugDump ( PVOID pDevice )
{
PSHMEM_MGR_OBJECT this = GetShMemObject ( pDevice );
PSHMEM_BLOCK pMemory;
CHAR szTemp[81];
/* dump the channel data structure */
_Sprintf ( szTemp,
"chnl:SIZE[%08x]:FLAG[%08x]:PLIN[%08x]:PPHY[%08x]:PLEN[%08x]\n",
this->Size, this->Flags, this->pLinear,
this->Physical,this->Length );
DP(0,szTemp);
_Sprintf ( szTemp,
"chnl:HEAD[%08x]:HNDL[%08x]:FREE[%08x]\n",
this->pHead, this->Handle, this->Free );
DP(0,szTemp);
for (pMemory = this->pHead; pMemory ; pMemory = pMemory->pNext)
{
_Sprintf ( szTemp,
"smem:MBLK[%08x]:PREV[%08x]:NEXT[%08x]:BLEN[%08x]:BALC[%08x]\n",
pMemory, pMemory->pPrev, pMemory->pNext,
EXPAND(pMemory->Flags.Length), (DWORD)pMemory->Flags.Allocated);
DP(0,szTemp);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -