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

📄 pgpmempool.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 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 + -