📄 pgpmempool.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpMemPool.c,v 1.12 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/
/*
* Pooled memory allocation, similar to GNU obstacks.
*/
#include "pgpConfig.h"
#include <stdio.h>
#include <string.h>
#include "pgpDebug.h"
#include "pgpMemPool.h"
#include "pgpMem.h"
#include "pgpMemoryMgr.h"
#include "pgpContext.h"
#include "pgpKeyPriv.h"
#ifndef NULL
#define NULL 0
#endif
/* Define this symbol to cause secure wiping */
#ifndef SECURE
#define SECURE 1
#endif
/*
* The memory pool allocation functions
*
* These are based on a linked list of memory blocks, usually of uniform
* size. New memory is allocated from the tail of the current block,
* until that is inadequate, then a new block is allocated.
* The entire pool can be freed at once by calling memPoolFree().
*/
typedef struct PoolBuf {
struct PoolBuf *next;
unsigned size;
/* Data follows */
} PoolBuf;
/* Page size to use */
#ifdef MSDOS
#define ALLOC_UNIT 1024
#else
#define ALLOC_UNIT (256*1024) // was 4096
#endif
static MemPool const EmptyPool =
{ NULL, NULL, NULL, 0, ALLOC_UNIT, 0, (int (*)(void *))NULL, NULL};
/*
* Initialize the pool for first use
*/
void
memPoolInit(
PGPContextRef context,
MemPool * pool)
{
*pool = EmptyPool;
pool->context = context;
}
/* Set the pool's purge function */
void
memPoolSetPurge(MemPool *pool, int (*purge)(void *), void *arg)
{
pool->purge = purge;
pool->purgearg = arg;
}
/*
* Free all the memory in the pool
*/
void
memPoolEmpty(MemPool *pool)
{
PoolBuf *buf;
while ((buf = pool->head) != NULL) {
pool->head = buf->next;
#if SECURE
pgpClearMemory( buf, buf->size);
#endif
pgpContextMemFree( pool->context, buf);
}
pool->freespace = 0;
pool->totalsize = 0;
}
/*
* Restore a pool to a marked position, freeing subsequently allocated
* memory.
*/
void
memPoolCutBack(MemPool *pool, MemPool const *cutback)
{
PoolBuf *buf;
pgpAssert(pool);
pgpAssert(cutback);
pgpAssert(pool->totalsize >= cutback->totalsize);
while((buf = pool->head) != cutback->head) {
pool->head = buf->next;
#if SECURE
pgpClearMemory( buf, buf->size);
#endif
pgpContextMemFree( pool->context, buf );
}
*pool = *cutback;
}
/*
* Structure and string allocations.
* To make alingment work, strings and other objects
* are allocated from different pools.
*/
/*
* Allocate a chunk of memory for a structure, with the given alignment.
* This is more space-efficient than malloc() for small objects
* with loose alignment restrictions - like short strings.
* Note that alignment is relative to the beginning of a chunk returned from
* malloc(), which is guaranteed by ANSI to be as aligned as can possibly
* matter.
*/
void *
memPoolAlloc(MemPool *pool, unsigned len, unsigned alignment)
{
char *p;
unsigned t;
/* Where to allocate next object */
p = pool->freeptr;
/* How far it is from the beginning of the chunk. */
t = p - (char *)pool->head;
/*
* How much padding to add to freeptr to make alignment. The first
* case (not a power of 2) will never happen, but we do it right
* for bragging rights in the ANSI C compliance department.
*/
if (alignment & (alignment-1))
t = alignment-1 - (t-1)%alignment; /* Never called */
else
t = -(int)t & (alignment-1); /* This one always */
/* Okay, does it fit? */
if (pool->freespace >= len+t) {
pool->freespace -= len+t;
p += t;
pool->freeptr = p + len;
return p;
}
/* It does not fit in the current chunk. Allocate a new chunk. */
/* First, figure out how padding is needed after the header. */
if (alignment & (alignment-1))
alignment -= 1 + (sizeof(PoolBuf)-1) % alignment;
else
alignment = (alignment-1) & -(int)sizeof(PoolBuf);
alignment += sizeof(PoolBuf);
/* Then, figure out a chunk size that will fit */
t = pool->chunksize;
pgpAssert(t);
while (len + alignment > t)
t *= 2;
while ((p = (char *)
pgpContextMemAlloc( pool->context, t, 0)) == NULL)
{
/* If that didn't work, try purging or smaller allocations */
if (!pool->purge || !pool->purge(pool->purgearg)) {
if (len + alignment == t)
return NULL;
t /= 2;
if (t < len+alignment)
t = len+alignment;
}
}
/* Update the various pointers. */
pool->totalsize += t;
((PoolBuf *)p)->next = pool->head;
((PoolBuf *)p)->size = t;
pool->head = (PoolBuf *)p;
pool->freespace = t - len - alignment;
p += alignment;
pool->freeptr = p + len;
return p;
}
/*
* Define a lightweight memory manager based on the mempool.
* It can allocate things quickly but doesn't do anything for delete.
* Then the caller should use the cutback function when the memory mgr
* is finished.
*/
static void *
sMemPoolAlloc( PGPMemoryMgrRef mgr, PGPUserValue val, PGPSize size,
PGPMemoryMgrFlags flags );
static PGPError
sMemPoolRealloc( PGPMemoryMgrRef mgr, PGPUserValue val, void **oldbuf,
PGPSize newsize, PGPMemoryMgrFlags flags, PGPSize oldsize );
static PGPError
sMemPoolDealloc( PGPMemoryMgrRef mgr, PGPUserValue val, void *buf,
PGPSize size );
static void *
sMemPoolSecureAlloc( PGPMemoryMgrRef mgr, PGPUserValue val, PGPSize size,
PGPMemoryMgrFlags flags, PGPBoolean *nonpage );
static PGPError
sMemPoolSecureDealloc( PGPMemoryMgrRef mgr, PGPUserValue val, void *buf,
PGPSize size, PGPBoolean waslocked );
PGPMemoryMgrRef
pgpMemPoolMemoryMgr( MemPool *pool )
{
PGPNewMemoryMgrStruct custom;
PGPMemoryMgrRef mgr;
pgpClearMemory( &custom, sizeof(custom) );
custom.sizeofStruct = sizeof(custom);
custom.allocProc = sMemPoolAlloc;
custom.reallocProc = sMemPoolRealloc;
custom.deallocProc = sMemPoolDealloc;
custom.secureAllocProc = sMemPoolSecureAlloc;
custom.secureDeallocProc = sMemPoolSecureDealloc;
custom.customValue = (PGPUserValue) pool;
PGPNewMemoryMgrCustom( &custom, &mgr );
return mgr;
}
static void *
sMemPoolAlloc( PGPMemoryMgrRef mgr, PGPUserValue val, PGPSize size,
PGPMemoryMgrFlags flags )
{
MemPool *pool = (MemPool *)val;
void *buf;
(void) mgr;
(void) flags;
buf = memPoolAlloc( pool, size, sizeof(void *) );
return buf;
}
static PGPError
sMemPoolRealloc( PGPMemoryMgrRef mgr, PGPUserValue val, void **oldbuf,
PGPSize newsize, PGPMemoryMgrFlags flags, PGPSize oldsize )
{
void *buf;
if( newsize <= oldsize )
return kPGPError_NoErr;
buf = sMemPoolAlloc( mgr, val, newsize, flags );
if( IsNull( buf ) )
return kPGPError_OutOfMemory;
pgpCopyMemory( *oldbuf, buf, oldsize );
*oldbuf = buf;
return kPGPError_NoErr;;
}
static PGPError
sMemPoolDealloc( PGPMemoryMgrRef mgr, PGPUserValue val, void *buf,
PGPSize size )
{
(void) mgr;
(void) val;
(void) buf;
(void) size;
return kPGPError_NoErr;
}
static void *
sMemPoolSecureAlloc( PGPMemoryMgrRef mgr, PGPUserValue val, PGPSize size,
PGPMemoryMgrFlags flags, PGPBoolean *nonpage )
{
*nonpage = FALSE;
return sMemPoolAlloc( mgr, val, size, flags );
}
static PGPError
sMemPoolSecureDealloc( PGPMemoryMgrRef mgr, PGPUserValue val, void *buf,
PGPSize size, PGPBoolean waslocked )
{
(void) mgr;
(void) val;
(void) buf;
(void) size;
(void) waslocked;
return kPGPError_NoErr;
}
#ifdef DEADCODE
/*
* Store a string in the table, returning a pointer to the string.
*/
char const *
memPoolStore(MemPool *pool, char const *str)
{
unsigned len = strlen(str) + 1;
char *p;
p = memPoolAlloc(pool, len, 1);
if (p)
memcpy(p, str, len);
return p;
}
#endif
/*
* Local Variables:
* tab-width: 4
* End:
* vi: ts=4 sw=4
* vim: si
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -