⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tmshmem.c

📁 wince host 和 target PCI驱动程序
💻 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 + -