Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*++
packet.cpp
This file contains the code which implements the CPacket derived classes. A CPacket derived object describes the most basic IO operation that is performed.
--*/
#include "stdinc.h"
#ifdef CIO_DEBUG
#include <stdlib.h> // For Rand() function
#endif
#ifdef _NO_TEMPLATES_
DECLARE_ORDEREDLISTFUNC( CPacket )
#endif
//
// Module globals
//
CPool CBufferAllocator::rgPool[ MAX_BUFFER_SIZES ] ;//!!!How do you give this a signature?
DWORD CBufferAllocator::rgPoolSizes[ MAX_BUFFER_SIZES ] ; CBufferAllocator CBuffer::gAllocator ; CBufferAllocator* CSmallBufferCache::BufferAllocator = 0 ; CBufferAllocator* CMediumBufferCache::BufferAllocator = 0 ; CSmallBufferCache* CBuffer::gpDefaultSmallCache = 0 ; CMediumBufferCache* CBuffer::gpDefaultMediumCache = 0 ;
//
// Control what size buffers the server uses
//
DWORD cbLargeBufferSize = 33 * 1024 ; DWORD cbMediumBufferSize = 4 * 1024 ; DWORD cbSmallBufferSize = 512 ;
BOOL CBufferAllocator::InitClass( ) { /*++
Routine Description :
This function initializes the CBufferAllocator class which handles all memory management of CBuffer objects. We will use three different CPools to produce CBuffers of different sizes.
Arguments :
None.
Return Value :
TRUE if successfull false otherwise !
--*/
rgPoolSizes[0] = cbSmallBufferSize ; rgPoolSizes[1] = cbMediumBufferSize ; rgPoolSizes[2] = cbLargeBufferSize ;
for( int i=0; i< sizeof( rgPoolSizes ) / sizeof( rgPoolSizes[0] ); i++ ) { if( !rgPool[i].ReserveMemory( MAX_BUFFERS / ((i+1)*(i+1)), rgPoolSizes[i] ) ) break ; } if( i != sizeof( rgPoolSizes ) / sizeof( rgPoolSizes[0] ) ) { for( i--; i!=0; i-- ) { rgPool[i].ReleaseMemory() ; } return FALSE ; } return TRUE ; }
BOOL CBufferAllocator::TermClass() { /*++
Routine Description :
Clean up all the CPool objects we use to manage CBuffer memory
Arguments :
None.
Return Value ;
TRUE if successfull FALSE otherwise.
--*/
BOOL fSuccess = TRUE ; for( int i=0; i< sizeof( rgPoolSizes ) / sizeof( rgPoolSizes[0] ); i++ ) { _ASSERT( rgPool[i].GetAllocCount() == 0 ) ; fSuccess &= rgPool[i].ReleaseMemory() ; } return fSuccess ; }
LPVOID CBufferAllocator::Allocate( DWORD cb, DWORD& cbOut ) { /*++
Routine description :
Allocate the memory required for a CBuffer object from the CPool which will provide a large enough block of memory. We will use a portion of the allocated memory to hold a pointer back to the particular CPool from which this memory was allocated
Arguments :
cb - Number of bytes required cbOut - Number of bytes allocated for the CBuffer
Return Value :
Pointer to the allocated block of memory - NULL on failure
--*/
//cb += sizeof( CBuffer ) ;
cb += sizeof( CPool* ) ;
//_ASSERT( size == sizeof( CBuffer ) ) ;
cbOut = 0 ; for( int i=0; i<sizeof(rgPoolSizes)/sizeof(rgPoolSizes[0]); i++ ) { if( cb < rgPoolSizes[i] ) { cbOut = rgPoolSizes[i] - sizeof( CPool * ) ; void *pv = rgPool[i].Alloc() ; if( pv == 0 ) { return 0 ; } ((CPool **)pv)[0] = &rgPool[i] ; return (void *)&(((CPool **)pv)[1]) ; } } _ASSERT( 1==0 ) ; return 0 ; }
void CBufferAllocator::Release( void* pv ) { /*++
Routine description :
Release memory that was used for a CBuffer object back to its CPool examine the DWORD before the allocated memory to figure out which CPool to release this too.
Arguments :
pv - the memory being released
Return Value :
None.
--*/ CPool** pPool = (CPool**)pv ; pPool[-1]->Free( (void*)&(pPool[-1]) ) ; }
#ifdef DEBUG
//
// Debug functions - the following functions all do various forms of validation
// to ensure that memory is being properly manipulated
//
int CBufferAllocator::GetPoolIndex( void* lpv ) { /*++
Routine Description :
figure out which pool this block of memory was allocated out of.
Agruments :
lpv - pointer to a block of memory allocated by CBufferAllocator when it was allocated we stuck a pointer to the CPool we used ahead of the pointer
Return Value :
index of the pool used to allocate the buffer
--*/ CPool** pPool = (CPool**)lpv ; CPool* pool = pPool[-1] ;
for( int i=0; i < sizeof(rgPoolSizes)/sizeof(rgPoolSizes[0]); i++ ) { if( pool == &rgPool[i] ) { return i ; } } return -1 ; }
void CBufferAllocator::Erase( void* lpv ) { /*++
Routine Description :
Fill a block of released memory so it is easy to spot during debug.
Arguments :
lpv - released memory
Returns :
Nothing
--*/
int i = GetPoolIndex( lpv ) ; _ASSERT( i >= 0 ) ;
DWORD cb = rgPoolSizes[i] - sizeof( CPool*) ; FillMemory( (BYTE*)lpv, cb, 0xCC ) ; }
BOOL CBufferAllocator::EraseCheck( void* lpv ) { /*++
Routine Description :
Verify that a block of memory has been erased using CBufferAllocator::Erase()
Arguments :
lpv - released memory
Returns :
TRUE if correctly erased FALSE otherwise
--*/ int i = GetPoolIndex( lpv ) ; _ASSERT( i>=0 ) ; DWORD cb = rgPoolSizes[i] - sizeof( CPool* ) ; for( DWORD j=sizeof(CPool*); j < cb; j++ ) { if( ((BYTE*)lpv)[j] != 0xCC ) return FALSE ; } return TRUE ; }
BOOL CBufferAllocator::RangeCheck( void* lpv ) { /*++
Routine Description :
Check that a block of memory is actually something that we would allocate. Unfortunately, this is hard to do with the current CPool interface.
Arguments :
lpv - block of memory
Return Value :
Always TRUE
--*/ //
// Need to modify CPool so we can examine the address range into which objects fall !
//
return TRUE ; }
BOOL CBufferAllocator::SizeCheck( DWORD cb ) { /*++
Routine Description : Check that we are trying to allocate a size which is legal for this allocater.
Arguments :
cb - the requested size
Return Value :
TRUE if legit, FALSE otherwise.
--*/ return (cb + sizeof( CPool* )) < rgPoolSizes[2] ; } #endif // DEBUG
BOOL CBuffer::gTerminate = FALSE ;
BOOL CBuffer::InitClass() { /*++
Routine Description :
This class initializes the CBufferClass.
Arguemtns :
None.
Return Value :
TRUE if successfull.
--*/ gTerminate = FALSE ; if( CBufferAllocator::InitClass() ) { CSmallBufferCache::InitClass( &gAllocator ) ; CMediumBufferCache::InitClass( &gAllocator ) ;
gpDefaultSmallCache = XNEW CSmallBufferCache() ; gpDefaultMediumCache = XNEW CMediumBufferCache() ; if( gpDefaultSmallCache == 0 || gpDefaultMediumCache == 0 ) {
if( gpDefaultMediumCache != 0 ) { XDELETE gpDefaultMediumCache ; gpDefaultMediumCache = 0 ; } if( gpDefaultSmallCache != 0 ) { XDELETE gpDefaultSmallCache ; gpDefaultSmallCache = 0 ; } CBufferAllocator::TermClass() ; return gTerminate ;
} else { gTerminate = TRUE ; } } return gTerminate ; }
BOOL CBuffer::TermClass() { /*++
Routine Description :
Terminate the CBuffer class - release everything ever allocated through this class.
Arguments :
None.
Return Value : TRUE if successfull.
--*/
if( gpDefaultMediumCache != 0 ) { XDELETE gpDefaultMediumCache ; gpDefaultMediumCache = 0 ; } if( gpDefaultSmallCache != 0 ) { XDELETE gpDefaultSmallCache ; gpDefaultSmallCache = 0 ; }
if( !gTerminate ) { return TRUE ; } else { return CBufferAllocator::TermClass() ; } }
void* CBuffer::operator new( size_t size, DWORD cb, DWORD &cbOut, CSmallBufferCache* pCache, CMediumBufferCache* pMediumCache ) { /*++
Routine Description :
Allocate a buffer of a specified size, if possible from a Cache.
Arguments :
size - size being requested - this will be the size of CBuffer itself as generated by the compiler. not so usefull as we intend m_rgbBuff to be variable sized. cb - Caller provided size - this indicates how big we want the buffer to be and tells us we need to allocate a block big support a m_rgbBuff of that size cbOut - Out parameter - get the exact sizeof m_rgbBuff that can be accommodated pCache - Cache from which to allocate small buffers pMediumCache - Cache from which to allocate medium sized buffers
Return Value :
pointer to allocated block (NULL on failure).
--*/
//
// Validate args - default args for pCache and pMediumCache
// should ensure these are never NULL
//
_ASSERT( pCache != 0 ) ; _ASSERT( pMediumCache != 0 ) ;
cb += sizeof( CBuffer ) ; _ASSERT( size == sizeof( CBuffer ) ) ;
void* pv = 0 ; if( cb <= CBufferAllocator::rgPoolSizes[0] ) { pv = pCache->Alloc( cb, cbOut ) ; } else if( cb <= CBufferAllocator::rgPoolSizes[1] ) { pv = pMediumCache->Alloc( cb, cbOut ) ; } else { pv = gAllocator.Allocate( cb, cbOut ) ; } if( pv != 0 ) { cbOut -= sizeof( CBuffer ) ; } _ASSERT( cbOut >= (cb - sizeof(CBuffer)) ) ;
return pv ; }
void CBuffer::operator delete( void* pv ) { /*++
Routine Description :
Release a block of memory allocated to hold a CBuffer object to some place.
Arguments :
pv - block of memory being released.
Return Value :
none.
--*/
CPool** pPool = (CPool**)pv ;
if( pPool[-1] == &CBufferAllocator::rgPool[0] ) gpDefaultSmallCache->Free( pv ) ; else if (pPool[-1] == &CBufferAllocator::rgPool[1] ) gpDefaultMediumCache->Free( pv ) ; else gAllocator.Release( pv ) ; }
void CBuffer::Destroy( CBuffer* pbuffer, CSmallBufferCache* pCache ) { if( pCache == 0 ) { delete pbuffer ; } else { pCache->Free( (void*)pbuffer ) ; } }
|