📄 pgpmemorymgr.c
字号:
PGPMemoryMgrRef mgr,
PGPSize requestSize,
PGPMemoryMgrFlags flags)
{
void *allocation = NULL;
PGPSize allocationSize = requestSize;
allocationSize += kRealHeaderSize;
pgpAssert( PGPMemoryMgrIsValid( mgr ) );
if( PGPMemoryMgrIsValid( mgr ) )
{
allocation = (*mgr->allocProc)( mgr, mgr->customValue,
allocationSize, flags );
}
if ( IsntNull( allocation ) )
{
DataHeader * header = NULL;
if ( (flags & kPGPMemoryMgrFlags_Clear ) != 0 )
{
pgpClearMemory( allocation, allocationSize );
}
else
{
pgpDebugWhackMemory( allocation, allocationSize );
}
header = (DataHeader *)allocation;
sInitDataHeader( mgr, requestSize, header );
allocation = HeaderToUserBlock( allocation );
AssertBlockValid( allocation );
sAddToLeaksList( mgr, header );
}
return( allocation );
}
/*____________________________________________________________________________
Allocate a block of memory (secure or non-secure).
____________________________________________________________________________*/
PGPError
PGPReallocData(
PGPMemoryMgrRef mgr,
void ** userPtr,
PGPSize requestSize,
PGPMemoryMgrFlags flags)
{
PGPError err = kPGPError_NoErr;
PGPValidateParam( PGPMemoryMgrIsValid( mgr ) );
PGPValidatePtr( userPtr );
/* allow a NULL input */
if ( IsntNull( *userPtr ) )
{
DataHeader * header = UserBlockToHeader( *userPtr );
PGPSize oldRequestSize = header->requestSize;
sRemoveFromLeaksList( mgr, header );
if ( header->secureAlloc )
{
AssertBlockValid( *userPtr );
err = sSecureMemoryReallocProc( mgr,
(void **) &header,
kRealHeaderSize + requestSize,
flags,
kRealHeaderSize + header->requestSize );
}
else
{
AssertBlockValid( *userPtr );
err = (*(mgr->reallocProc))( mgr, mgr->customValue,
(void **) &header,
kRealHeaderSize + requestSize,
flags,
kRealHeaderSize + header->requestSize );
}
sAddToLeaksList( mgr, header );
if ( IsntPGPError( err ) )
{
*userPtr = HeaderToUserBlock( header );
header->requestSize = requestSize;
AssertBlockValid( *userPtr );
}
if ( IsntPGPError( err ) && requestSize > oldRequestSize )
{
if ( (flags & kPGPMemoryMgrFlags_Clear ) != 0 )
{
pgpClearMemory( ((char *)(*userPtr)) + oldRequestSize,
requestSize - oldRequestSize );
}
else
{
#if PGP_DEBUG
/* clear all newly allocated data to garbage */
pgpDebugWhackMemory( ((char *)(*userPtr)) + oldRequestSize,
requestSize - oldRequestSize );
#endif
}
}
}
else
{
/* allocate a brand-new block */
*userPtr = PGPNewData( mgr, requestSize, flags );
if ( IsNull( *userPtr ) )
{
err = kPGPError_OutOfMemory;
}
}
return( err );
}
/*____________________________________________________________________________
Free a block of memory, whether secure or not.
____________________________________________________________________________*/
PGPError
PGPFreeData( void * allocation )
{
PGPError err = kPGPError_NoErr;
PGPMemoryMgrRef mgr = NULL;
DataHeader * header;
PGPSize allocationSize;
PGPValidatePtr( allocation );
header = UserBlockToHeader( allocation );
PGPValidateParam( sDataHeaderIsValid( header ) );
mgr = header->mgr;
allocationSize = kRealHeaderSize + header->requestSize;
sRemoveFromLeaksList( mgr, header );
if ( header->secureAlloc )
{
pgpClearMemory( allocation, header->requestSize );
err = (*(mgr->secureDeallocProc))(
mgr, mgr->customValue,
header,
allocationSize,
(PGPBoolean)header->nonPageable );
}
else
{
pgpDebugWhackMemory( header, allocationSize );
err = (*(mgr->deallocProc))(
mgr, mgr->customValue,
header,
allocationSize );
}
return( err );
}
void *
PGPNewSecureData(
PGPMemoryMgrRef mgr,
PGPSize requestSize,
PGPMemoryMgrFlags flags )
{
void * allocation = NULL;
PGPSize allocationSize = requestSize;
PGPBoolean isNonPageable;
allocationSize += kRealHeaderSize;
if( PGPMemoryMgrIsValid( mgr ) )
{
allocation = (*mgr->secureAllocProc)( mgr, mgr->customValue,
allocationSize, flags, &isNonPageable );
}
if ( IsntNull( allocation ) )
{
DataHeader * header = NULL;
if ( (flags & kPGPMemoryMgrFlags_Clear ) != 0)
{
pgpClearMemory( allocation, allocationSize );
}
else
{
pgpDebugWhackMemory( allocation, allocationSize );
}
header = (DataHeader *)allocation;
sInitDataHeader( mgr, requestSize, header );
header->secureAlloc = TRUE;
header->nonPageable = isNonPageable;
allocation = HeaderToUserBlock( allocation );
AssertBlockValid( allocation );
sAddToLeaksList( mgr, header );
}
return( allocation );
}
PGPFlags
PGPGetMemoryMgrDataInfo( void *allocation )
{
PGPFlags flags = 0;
DataHeader * header;
if ( IsNull( allocation ) )
return( 0 );
header = UserBlockToHeader( allocation );
if ( sDataHeaderIsValid( header ) )
{
flags |= kPGPMemoryMgrBlockInfo_Valid;
if ( header->secureAlloc )
flags |= kPGPMemoryMgrBlockInfo_Secure;
if ( header->nonPageable )
flags |= kPGPMemoryMgrBlockInfo_NonPageable;
}
return( flags );
}
typedef struct MemoryMgrInfo
{
struct MemoryMgrInfo *next;
PGPMemoryMgrRef mgr;
} MemoryMgrInfo;
static PGPMemoryMgrRef sDefaultMemoryMgr = kInvalidPGPMemoryMgrRef;
static MemoryMgrInfo *sMemoryMgrList = NULL;
static PGPRMWOLock sMemoryMgrListLock;
PGPMemoryMgrRef
PGPGetDefaultMemoryMgr(void)
{
PGPMemoryMgrRef mgr;
if( IsntNull( sMemoryMgrList ) )
{
/*
** If the list is non-null, then we have a mgr. We need to use a RMWO
** lock because this is a global list
*/
PGPRMWOLockStartReading( &sMemoryMgrListLock );
mgr = sDefaultMemoryMgr;
PGPRMWOLockStopReading( &sMemoryMgrListLock );
}
else
{
mgr = kInvalidPGPMemoryMgrRef;
}
return( mgr );
}
PGPError
PGPSetDefaultMemoryMgr(PGPMemoryMgrRef memoryMgr)
{
PGPError err = kPGPError_NoErr;
PGPBoolean foundMemoryMgr = FALSE;
PGPValidateParam( PGPMemoryMgrRefIsValid( memoryMgr ) );
if( IsNull( sMemoryMgrList ) )
{
/*
** If there is no list, initialize the RMWO lock. This presents
** a small window where the lock could get initialized twice,
** however this is not a call likely to introduce race conditions.
*/
InitializePGPRMWOLock( &sMemoryMgrListLock );
}
PGPRMWOLockStartWriting( &sMemoryMgrListLock );
if( IsntNull( sMemoryMgrList ) )
{
MemoryMgrInfo *cur;
/*
** Check to see if this memory mgr is already in our list and use
** it if it is
*/
cur = sMemoryMgrList;
while( IsntNull( cur ) )
{
if( cur->mgr == memoryMgr )
{
foundMemoryMgr = TRUE;
break;
}
cur = cur->next;
}
}
if( ! foundMemoryMgr )
{
MemoryMgrInfo *info;
info = (MemoryMgrInfo *) PGPNewData( memoryMgr, sizeof( *info ), 0 );
if( IsntNull( info ) )
{
info->mgr = memoryMgr;
info->next = sMemoryMgrList;
sMemoryMgrList = info;
}
else
{
err = kPGPError_OutOfMemory;
}
}
if( IsntPGPError( err ) )
sDefaultMemoryMgr = memoryMgr;
PGPRMWOLockStopWriting( &sMemoryMgrListLock );
return( err );
}
void
pgpFreeDefaultMemoryMgrList(void)
{
if( IsntNull( sMemoryMgrList ) )
{
MemoryMgrInfo *cur;
PGPRMWOLockStartWriting( &sMemoryMgrListLock );
cur = sMemoryMgrList;
while( IsntNull( cur ) )
{
MemoryMgrInfo *next;
PGPMemoryMgrRef mgr;
next = cur->next;
mgr = cur->mgr;
PGPFreeData( cur );
PGPFreeMemoryMgr( mgr );
cur = next;
}
sMemoryMgrList = NULL;
PGPRMWOLockStopWriting( &sMemoryMgrListLock );
DeletePGPRMWOLock( &sMemoryMgrListLock );
}
}
#if TESTING
/* test reallocation, then dispose of the ptr */
static void
sTestUsingPtr(
PGPMemoryMgrRef mgr,
void * data )
{
PGPError err = kPGPError_NoErr;
(void)mgr;
err = PGPReallocData( mgr, &data, 20000, 0 );
pgpAssertNoErr( err );
err = PGPReallocData( mgr, &data, 500, 0 );
pgpAssertNoErr( err );
err = PGPReallocData( mgr, &data, 0, 0 );
pgpAssertNoErr( err );
err = PGPReallocData( mgr, &data, 20001, 0 );
pgpAssertNoErr( err );
PGPFreeData( data );
}
static void
sTestMultiAllocations( PGPMemoryMgrRef mgr)
{
#define kNumTestPtrs 50
void * plain[ kNumTestPtrs ];
void * secure[ kNumTestPtrs ];
PGPUInt32 idx;
void * temp;
PGPError err = kPGPError_NoErr;
for( idx = 0; idx < kNumTestPtrs; ++idx )
{
PGPSize ptrSize;
PGPFlags flags;
ptrSize = idx * 17;
plain[ idx ] = PGPNewData( mgr, ptrSize, 0);
if ( IsntNull( plain[ idx ] ) )
{
flags = PGPGetMemoryMgrDataInfo( plain[ idx ] );
pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Valid ) != 0 );
pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Secure ) == 0 );
pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_NonPageable ) == 0 );
}
secure[ idx ] = PGPNewSecureData( mgr, ptrSize, 0 );
if ( IsntNull( secure[ idx ] ) )
{
flags = PGPGetMemoryMgrDataInfo( secure[ idx ] );
pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Valid ) != 0 );
pgpAssert( ( flags & kPGPMemoryMgrBlockInfo_Secure ) != 0 );
}
}
/* free even numbered items */
for( idx = 0; idx < kNumTestPtrs; idx += 2 )
{
PGPFreeData( plain[ idx ] );
PGPFreeData( secure[ idx ] );
}
/* free odd numbered items */
for( idx = 1; idx < kNumTestPtrs; idx += 2 )
{
PGPFreeData( plain[ idx ] );
PGPFreeData( secure[ idx ] );
}
/* test realloc case with NULL ptr */
temp = NULL;
err = PGPReallocData( mgr, &temp, 1000, 0 );
pgpAssertNoErr( err );
pgpAssert( IsntNull( temp ) );
PGPFreeData( temp );
}
static void
sTestMemoryMgr( PGPMemoryMgrRef mgr )
{
void * temp = NULL;
/* test normal allocation */
temp = PGPNewData( mgr, 1000,
kPGPMemoryMgrFlags_Clear );
if ( IsntNull( temp ) )
{
sTestUsingPtr( mgr, temp );
}
sTestMultiAllocations( mgr );
/* test secure allocation */
temp = PGPNewSecureData( mgr, 1000,
kPGPMemoryMgrFlags_Clear );
if ( IsntNull( temp ) )
{
sTestUsingPtr( mgr, temp );
}
sTestMultiAllocations( mgr );
#if MEMORY_MGR_TRACK_LEAKS
pgpAssert( mgr->numAllocations == 0 );
#endif
}
#endif
/*__Editor_settings____
Local Variables:
tab-width: 4
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -