[Fedora-directory-commits] ldapserver/ldap/servers/slapd mempool.c, NONE, 1.1 add.c, 1.12, 1.13 attrsyntax.c, 1.7, 1.8 ava.c, 1.7, 1.8 bind.c, 1.14, 1.15 ch_malloc.c, 1.9, 1.10 computed.c, 1.5, 1.6 connection.c, 1.19, 1.20 entry.c, 1.18, 1.19 filter.c, 1.10, 1.11 filtercmp.c, 1.6, 1.7 libglobs.c, 1.25, 1.26 main.c, 1.25, 1.26 operation.c, 1.6, 1.7 proto-slap.h, 1.36, 1.37 rwlock.c, 1.5, 1.6 slap.h, 1.35, 1.36 slapi2nspr.c, 1.5, 1.6

Noriko Hosoi nhosoi at fedoraproject.org
Wed Oct 15 06:30:08 UTC 2008


Author: nhosoi

Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv25637/ldap/servers/slapd

Modified Files:
	add.c attrsyntax.c ava.c bind.c ch_malloc.c computed.c 
	connection.c entry.c filter.c filtercmp.c libglobs.c main.c 
	operation.c proto-slap.h rwlock.c slap.h slapi2nspr.c 
Added Files:
	mempool.c 
Log Message:
Resolves: #466702
Summary: Memory usage research: checking in the experimental code
See also: http://directory.fedoraproject.org/wiki/Memory_Usage_Research



--- NEW FILE mempool.c ---
/** BEGIN COPYRIGHT BLOCK
 * This Program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; version 2 of the License.
 * 
 * This Program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA.
 * 
 * In addition, as a special exception, Red Hat, Inc. gives You the additional
 * right to link the code of this Program with code not covered under the GNU
 * General Public License ("Non-GPL Code") and to distribute linked combinations
 * including the two, subject to the limitations in this paragraph. Non-GPL Code
 * permitted under this exception must only link to the code of this Program
 * through those well defined interfaces identified in the file named EXCEPTION
 * found in the source code files (the "Approved Interfaces"). The files of
 * Non-GPL Code may instantiate templates or use macros or inline functions from
 * the Approved Interfaces without causing the resulting work to be covered by
 * the GNU General Public License. Only Red Hat, Inc. may make changes or
 * additions to the list of Approved Interfaces. You must obey the GNU General
 * Public License in all respects for all of the Program code and other code used
 * in conjunction with the Program except the Non-GPL Code covered by this
 * exception. If you modify this file, you may extend this exception to your
 * version of the file, but you are not obligated to do so. If you do not wish to
 * provide this exception without modification, you must delete this exception
 * statement from your version and license this file solely under the GPL without
 * exception. 
 * 
 * Copyright (C) 2008 Red Hat, Inc.
 * All rights reserved.
 * END COPYRIGHT BLOCK **/

#ifdef MEMPOOL_EXPERIMENTAL

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <slap.h>
#include <prcountr.h>

struct mempool_object {
	struct mempool_object *mempool_next;
};

typedef int (*mempool_cleanup_callback)(void *object);

#ifdef SHARED_MEMPOOL
/* 
 * shared mempool among threads
 * contention causes the performance degradation
 * (Warning: SHARED_MEMPOOL code is obsolete)
 */
#define MEMPOOL_END NULL
static struct mempool {
	const char *mempool_name;
	struct mempool_object *mempool_head;
	PRLock *mempool_mutex;
	mempool_cleanup_callback mempool_cleanup_fn;
	unsigned long mempool_count;
} mempool[] = {
	{"2K", NULL, NULL, NULL, 0},
	{"4K", NULL, NULL, NULL, 0},
	{"8K", NULL, NULL, NULL, 0},
	{"16K", NULL, NULL, NULL, 0},
	{"32K", NULL, NULL, NULL, 0},
	{"64K", NULL, NULL, NULL, 0},
	{"128K", NULL, NULL, NULL, 0},
	{"256K", NULL, NULL, NULL, 0},
	{"512K", NULL, NULL, NULL, 0},
	{"1M", NULL, NULL, NULL, 0},
	{"2M", NULL, NULL, NULL, 0},
	{"4M", NULL, NULL, NULL, 0},
	{"8M", NULL, NULL, NULL, 0},
	{"16M", NULL, NULL, NULL, 0},
	{"32M", NULL, NULL, NULL, 0},
	{"64M", NULL, NULL, NULL, 0},
	{MEMPOOL_END, NULL, NULL, NULL, 0}
};
#else
/* 
 * mempool per thread; no lock is needed
 */
#define MAX_MEMPOOL 16
#define MEMPOOL_END 0
struct mempool {
	const char *mempool_name;
	struct mempool_object *mempool_head;
	mempool_cleanup_callback mempool_cleanup_fn;
	unsigned long mempool_count;
};

char *mempool_names[] =
{
	"2K", "4K", "8K", "16K", 
	"32K", "64K", "128K", "256K", 
	"512K", "1M", "2M", "4M", 
	"8M", "16M", "32M", "64M"
};
#endif

static PRUintn mempool_index;	/* thread private index used to store mempool
                                   in NSPR ThreadPrivateIndex */
static void mempool_destroy();

/*
 * mempool_init creates NSPR thread private index, 
 * then allocates per-thread-private.
 * mempool is initialized at the first mempool_return
 */
static void
mempool_init(struct mempool **my_mempool)
{
	int i;
	if (NULL == my_mempool) {
		return;
	} 
#ifdef SHARED_MEMPOOL
	for (i = 0; MEMPOOL_END != mempool[i].mempool_name; i++) {
		mempool[i].mempool_mutex = PR_NewLock();
		if (NULL == mempool[i].mempool_mutex) {
			PRErrorCode ec = PR_GetError();
			slapi_log_error (SLAPI_LOG_FATAL, "mempool", "mempool_init: "
				"failed to create mutex - (%d - %s); mempool(%s) is disabled",
				ec, slapd_pr_strerror(ec), mempool[i].mempool_name);
			rc = LDAP_OPERATIONS_ERROR;
		}
	}
#else
	PR_NewThreadPrivateIndex (&mempool_index, mempool_destroy);
	*my_mempool = (struct mempool *)slapi_ch_calloc(MAX_MEMPOOL, sizeof(struct mempool));
	for (i = 0; i < MAX_MEMPOOL; i++) {
		(*my_mempool)[i].mempool_name = mempool_names[i];
	}
#endif
}

/*
 * mempool_destroy is a callback which is set to NSPR ThreadPrivateIndex
 */
static void 
mempool_destroy()
{
	int i = 0;
	struct mempool *my_mempool;
#ifdef SHARED_MEMPOOL
	for (i = 0; MEMPOOL_END != mempool[i].mempool_name; i++) {
		struct mempool_object *object = NULL;
		if (NULL == mempool[i].mempool_mutex) {
			/* mutex is NULL; this mempool is not enabled */
			continue;
		}
		object = mempool[i].mempool_head;
		mempool[i].mempool_head = NULL;
		while (NULL != object) {
			struct mempool_object *next = object->mempool_next;
			if (NULL != mempool[i].mempool_cleanup_fn) {
				(mempool[i].mempool_cleanup_fn)((void *)object);
			}
			slapi_ch_free((void **)&object);
			object = next;
		}
		PR_DestroyLock(mempool[i].mempool_mutex);
		mempool[i].mempool_mutex = NULL;
	}
#else
	my_mempool = (struct mempool *)PR_GetThreadPrivate(mempool_index);
	if (NULL == my_mempool || my_mempool[0].mempool_name != mempool_names[0]) {
		/* mempool is not initialized */
		return;
	}
	for (i = 0; i < MAX_MEMPOOL; i++) {
		struct mempool_object *object = my_mempool[i].mempool_head;
		while (NULL != object) {
			struct mempool_object *next = object->mempool_next;
			if (NULL != my_mempool[i].mempool_cleanup_fn) {
				(my_mempool[i].mempool_cleanup_fn)((void *)object);
			}
			slapi_ch_free((void **)&object);
			object = next;
		}
		my_mempool[i].mempool_head = NULL;
		my_mempool[i].mempool_count = 0;
	}
	slapi_ch_free((void **)&my_mempool);
	PR_SetThreadPrivate (mempool_index, (void *)NULL);
#endif
}

/*
 * return memory to memory pool
 * (Callback cleanup function was intented to release nested memory in the 
 *  memory area.  Initially, memory had its structure which could point
 *  other memory area.  But the current code (#else) expects no structure.
 *  Thus, the cleanup callback is not needed)
 *  The current code (#else) uses the memory pool stored in the 
 *  per-thread-private data.
 */
int
mempool_return(int type, void *object, mempool_cleanup_callback cleanup)
{
	PR_ASSERT(type >= 0 && type < MEMPOOL_END);

	if (!config_get_mempool_switch()) {
		return LDAP_SUCCESS;	/* memory pool: off */
	}
#ifdef SHARED_MEMPOOL
	if (NULL == mempool[type].mempool_mutex) {
		/* mutex is NULL; this mempool is not enabled */
		return LDAP_SUCCESS;
	}
	PR_Lock(mempool[type].mempool_mutex);
	((struct mempool_object *)object)->mempool_next = mempool[type].mempool_head;
	mempool[type].mempool_head = (struct mempool_object *)object;
	mempool[type].mempool_cleanup_fn = cleanup;
	mempool[type].mempool_count++;
	PR_Unlock(mempool[type].mempool_mutex);
	return LDAP_SUCCESS;
#else
	{
	struct mempool *my_mempool;
	int maxfreelist;
	my_mempool = (struct mempool *)PR_GetThreadPrivate(mempool_index);
	if (NULL == my_mempool || my_mempool[0].mempool_name != mempool_names[0]) {
		/* mempool is not initialized */
		mempool_init(&my_mempool);
	} 
	((struct mempool_object *)object)->mempool_next = my_mempool[type].mempool_head;
	maxfreelist = config_get_mempool_maxfreelist();
	if ((maxfreelist > 0) && (my_mempool[type].mempool_count > maxfreelist)) {
		return LDAP_UNWILLING_TO_PERFORM;
	} else {
		my_mempool[type].mempool_head = (struct mempool_object *)object;
		my_mempool[type].mempool_cleanup_fn = cleanup;
		my_mempool[type].mempool_count++;
		PR_SetThreadPrivate (mempool_index, (void *)my_mempool);
		return LDAP_SUCCESS;
	}
	}
#endif
}

/*
 * get memory from memory pool
 *  The current code (#else) uses the memory pool stored in the 
 *  per-thread-private data.
 */
void *
mempool_get(int type)
{
	struct mempool_object *object = NULL;
	struct mempool *my_mempool;
	PR_ASSERT(type >= 0 && type < MEMPOOL_END);

	if (!config_get_mempool_switch()) {
		return NULL;	/* memory pool: off */
	}
#ifdef SHARED_MEMPOOL
	if (NULL == mempool[type].mempool_mutex) {
		/* mutex is NULL; this mempool is not enabled */
		return NULL;
	}

	PR_Lock(mempool[type].mempool_mutex);
	object = mempool[type].mempool_head;
	if (NULL != object) {
		mempool[type].mempool_head = object->mempool_next;
		mempool[type].mempool_count--;
		object->mempool_next = NULL;
	}
	PR_Unlock(mempool[type].mempool_mutex);
#else
	my_mempool = (struct mempool *)PR_GetThreadPrivate(mempool_index);
	if (NULL == my_mempool || my_mempool[0].mempool_name != mempool_names[0]) {	/* mempool is not initialized */
		return NULL;
	} 

	object = my_mempool[type].mempool_head;
	if (NULL != object) {
		my_mempool[type].mempool_head = object->mempool_next;
		my_mempool[type].mempool_count--;
		object->mempool_next = NULL;
		PR_SetThreadPrivate (mempool_index, (void *)my_mempool);
	}
#endif
	return object;
}

/*****************************************************************************
 * The rest is slapi_ch_malloc and its friends, which are adjusted to mempool.
 * The challenge is mempool_return needs to know the size of the memory, but
 * free does not pass the info.  To work around it, malloc allocates the extra
 * space in front of the memory to be returned and store the size in the extra
 * space.  
 *
 * Also, to simplify the code, it allocates the smallest 2^n size which
 * could store the requested size.  We should make the granurality higher for
 * the real use.  
 *
 * Above 64MB, the functions call mmap directly.  The reason
 * why I chose mmap over mempool is in mempool, the memory stays until the
 * server is shutdown even if the memory is never be requested.  By using mmap,
 * the memory is returned to the system and it's guaranteed to shrink the 
 * process size.
 *
 * In this implementation, it changes the behavior based on the requested 
 * size (+ size space -- unsigned long)* :
 * 1B ~ 1KB: call system *alloc/free; but still it needs to store the size to
 *           support realloc.  The function needs to know if the passed address
 *           is the real address or shifted for the size.
 * 1KB + 1B ~ 64MB: use mempool
 * 64MB + 1B ~ : call mmap
 */
#include <sys/mman.h>
static int slapi_ch_munmap_no_roundup(void **start, unsigned long len);
char *slapi_ch_mmap(unsigned long len);

static int counters_created= 0;
PR_DEFINE_COUNTER(slapi_ch_counter_malloc);
PR_DEFINE_COUNTER(slapi_ch_counter_calloc);
PR_DEFINE_COUNTER(slapi_ch_counter_realloc);
PR_DEFINE_COUNTER(slapi_ch_counter_strdup);
PR_DEFINE_COUNTER(slapi_ch_counter_free);
PR_DEFINE_COUNTER(slapi_ch_counter_created);
PR_DEFINE_COUNTER(slapi_ch_counter_exist);

#define OOM_PREALLOC_SIZE  65536
static void *oom_emergency_area = NULL;
static PRLock *oom_emergency_lock = NULL;

#define SLAPD_MODULE	"memory allocator"

static const char* const oom_advice =
  "\nThe server has probably allocated all available virtual memory. To solve\n"
  "this problem, make more virtual memory available to your server, or reduce\n"
  "one or more of the following server configuration settings:\n"
  "  nsslapd-cachesize        (Database Settings - Maximum entries in cache)\n"
  "  nsslapd-cachememsize     (Database Settings - Memory available for cache)\n"
  "  nsslapd-dbcachesize      (LDBM Plug-in Settings - Maximum cache size)\n"
  "  nsslapd-import-cachesize (LDBM Plug-in Settings - Import cache size).\n"
  "Can't recover; calling exit(1).\n";

static void
create_counters()
{
	PR_CREATE_COUNTER(slapi_ch_counter_malloc,"slapi_ch","malloc","");
	PR_CREATE_COUNTER(slapi_ch_counter_calloc,"slapi_ch","calloc","");
	PR_CREATE_COUNTER(slapi_ch_counter_realloc,"slapi_ch","realloc","");
	PR_CREATE_COUNTER(slapi_ch_counter_strdup,"slapi_ch","strdup","");
	PR_CREATE_COUNTER(slapi_ch_counter_free,"slapi_ch","free","");
	PR_CREATE_COUNTER(slapi_ch_counter_created,"slapi_ch","created","");
	PR_CREATE_COUNTER(slapi_ch_counter_exist,"slapi_ch","exist","");

	/* ensure that we have space to allow for shutdown calls to malloc()
	 * from should we run out of memory.
	 */
	if (oom_emergency_area == NULL) {
	  oom_emergency_area = malloc(OOM_PREALLOC_SIZE);
	}
	oom_emergency_lock = PR_NewLock();
}

static void
log_negative_alloc_msg( const char *op, const char *units, unsigned long size )
{
	slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		"cannot %s %lu %s;\n"
		"trying to allocate 0 or a negative number of %s is not portable and\n"
		"gives different results on different platforms.\n",
		op, size, units, units );
}

static char *
slapi_ch_malloc_core( unsigned long	lsize )
{
	char	*newmem;

	if ( (newmem = (char *) malloc( lsize )) == NULL ) {
		int	oserr = errno;
	
		oom_occurred();
		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
			"malloc of %lu bytes failed; OS error %d (%s)%s\n",
			lsize, oserr, slapd_system_strerror( oserr ), oom_advice );
		exit( 1 );
	}
	*(unsigned long *)newmem = lsize;
	newmem += sizeof(unsigned long);

	return newmem;
}

char *
slapi_ch_malloc( unsigned long	size )
{
	char	*newmem;
    unsigned long	lsize;

	if (size <= 0) {
		log_negative_alloc_msg( "malloc", "bytes", size );
		return 0;
	}

	lsize = size + sizeof(unsigned long);
	if (lsize <= 1024) {
		newmem = slapi_ch_malloc_core( lsize );
	} else if (lsize <= 67108864) {
		/* return 2KB ~ 64MB memory to memory pool */
		unsigned long roundup = 1;
		int n = 0;
		while (1) {
			roundup <<= 1;
			n++;
			if (roundup >= lsize) {
				break;
			}
		}
		PR_ASSERT(n >= 11 && n <= 26);
		newmem = (char *)mempool_get(n-11);	/* 11: 2^11 = 2K */
		if (NULL == newmem) {
			newmem = slapi_ch_malloc_core( roundup );
		}
	} else {
		newmem = slapi_ch_mmap( size );
	}

	if(!counters_created)
	{
		create_counters();
		counters_created= 1;
	}
	PR_INCREMENT_COUNTER(slapi_ch_counter_malloc);
	PR_INCREMENT_COUNTER(slapi_ch_counter_created);
	PR_INCREMENT_COUNTER(slapi_ch_counter_exist);
#if defined(_WIN32) && defined(DEBUG)
	if(recording)
	{
		add_memory_record(newmem,size);
	}
#endif

	return( newmem );
}

static char *
slapi_ch_realloc_core( char *block, unsigned long lsize )
{
	char	*realblock;
	char	*newmem;

	realblock = block - sizeof(unsigned long);
	if ( (newmem = (char *) realloc( realblock, lsize )) == NULL ) {
		int	oserr = errno;
	
		oom_occurred();
		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		    "realloc of %lu bytes failed; OS error %d (%s)%s\n",
			lsize, oserr, slapd_system_strerror( oserr ), oom_advice );
		exit( 1 );
	}
	*(unsigned long *)newmem = lsize;
	newmem += sizeof(unsigned long);

	return newmem;
}

char *
slapi_ch_realloc( char *block, unsigned long size )
{
	char	*newmem;
    unsigned long lsize;
	unsigned long origsize;
	char *realblock;
	char *realnewmem;

	if ( block == NULL ) {
		return( slapi_ch_malloc( size ) );
	}

	if (size <= 0) {
		log_negative_alloc_msg( "realloc", "bytes", size );
		return block;
	}

	lsize = size + sizeof(unsigned long);
	if (lsize <= 1024) {
		newmem = slapi_ch_realloc_core( block, lsize );
	} else if (lsize <= 67108864) {
		/* return 2KB ~ 64MB memory to memory pool */
		unsigned long roundup = 1;
		int n = 0;
		while (1) {
			roundup <<= 1;
			n++;
			if (roundup >= lsize) {
				break;
			}
		}
		PR_ASSERT(n >= 11 && n <= 26);
		newmem = (char *)mempool_get(n-11);	/* 11: 2^11 = 2K */
		if (NULL == newmem) {
			newmem = slapi_ch_realloc_core( block, roundup );
		} else {
			realblock = block - sizeof(unsigned long);
			origsize = *(unsigned long *)realblock - sizeof(unsigned long);;
			memcpy(newmem, block, origsize);
			slapi_ch_free_string(&block);
		}
	} else {
		realblock = block - sizeof(unsigned long);
		origsize = *(unsigned long *)realblock - sizeof(unsigned long);;
		newmem = slapi_ch_mmap( size );
		memcpy(newmem, block, origsize);
		realnewmem = newmem - sizeof(unsigned long);
		*(unsigned long *)realnewmem = lsize;
		slapi_ch_free_string(&block);
	}
	if(!counters_created)
	{
		create_counters();
		counters_created= 1;
	}
    PR_INCREMENT_COUNTER(slapi_ch_counter_realloc);
#if defined(_WIN32) && defined(DEBUG)
	if(recording)
	{
		remove_memory_record(block);
		add_memory_record(newmem,size);
	}
#endif

	return( newmem );
}

static char *
slapi_ch_calloc_core( unsigned long	lsize )
{
	char	*newmem;

	if ( (newmem = (char *) calloc( 1, lsize )) == NULL ) {
		int	oserr = errno;
	
		oom_occurred();
		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		    "calloc of %lu bytes failed; OS error %d (%s)%s\n",
			lsize, oserr, slapd_system_strerror( oserr ), oom_advice );
		exit( 1 );
	}
	*(unsigned long *)newmem = lsize;
	newmem += sizeof(unsigned long);

	return newmem;
}

char *
slapi_ch_calloc( unsigned long nelem, unsigned long size )
{
	char	*newmem;
    unsigned long	lsize;

	if (size <= 0) {
		log_negative_alloc_msg( "calloc", "bytes", size );
		return 0;
	}

	if (nelem <= 0) {
		log_negative_alloc_msg( "calloc", "elements", nelem );
		return 0;
	}

	lsize = nelem * size + sizeof(unsigned long);
	if (lsize <= 1024) {
		newmem = slapi_ch_calloc_core( lsize );
	} else if (lsize <= 67108864) {
		/* return 2KB ~ 64MB memory to memory pool */
		unsigned long roundup = 1;
		int n = 0;
		while (1) {
			roundup <<= 1;
			n++;
			if (roundup >= lsize) {
				break;
			}
		}
		PR_ASSERT(n >= 11 && n <= 26);
		newmem = (char *)mempool_get(n-11);	/* 11: 2^11 = 2K */
		if (NULL == newmem) {
			newmem = slapi_ch_calloc_core( roundup );
		} else {
			memset (newmem, 0, size * nelem);
		}
	} else {
		unsigned long mysize = size * nelem;
		newmem = slapi_ch_mmap( mysize );
		memset(newmem, 0, mysize);
	}
	if(!counters_created)
	{
		create_counters();
		counters_created= 1;
	}
    PR_INCREMENT_COUNTER(slapi_ch_counter_calloc);
    PR_INCREMENT_COUNTER(slapi_ch_counter_created);
    PR_INCREMENT_COUNTER(slapi_ch_counter_exist);
#if defined(_WIN32) && defined(DEBUG)
	if(recording)
	{
		add_memory_record(newmem,size);
	}
#endif
	return( newmem );
}

char *
slapi_ch_strdup ( const char* s1 )
{
    char* newmem;
    unsigned long	lsize;
	
	/* strdup pukes on NULL strings...bail out now */
	if(NULL == s1)
		return NULL;

	lsize = strlen(s1) + sizeof(unsigned long) + 1;
	newmem = slapi_ch_malloc( lsize );
	sprintf(newmem, "%s", s1);	

	if(!counters_created)
	{
		create_counters();
		counters_created= 1;
	}
    PR_INCREMENT_COUNTER(slapi_ch_counter_strdup);
    PR_INCREMENT_COUNTER(slapi_ch_counter_created);
    PR_INCREMENT_COUNTER(slapi_ch_counter_exist);
#if defined(_WIN32) && defined(DEBUG)
	if(recording)
	{
		add_memory_record(newmem,strlen(s1)+1);
	}
#endif
    return newmem;
}

/*
 * Function: slapi_ch_free 
 *
 * Returns: nothing 
 *
 * Description: frees the pointer, and then sets it to NULL to 
 *              prevent free-memory writes. 
 *              Note: pass in the address of the pointer you want to free.
 *              Note: you can pass in null pointers, it's cool.
 *
 * Implementation: get the size from the size space, and determine the behavior
 *                 based upon the size:
 *      1B ~ 1KB: call system free
 *      1KB + 1B ~ 64MB: return memory to mempool
 *      64MB + 1B ~ : call munmap
 */
void 
slapi_ch_free(void **ptr)
{
	void *realptr;
	unsigned long size;

	if (ptr==NULL || *ptr == NULL){
	return;
	}

#if defined(_WIN32) && defined(DEBUG)
	if(recording)
	{
		remove_memory_record(*ptr);
	}
#endif
	realptr = (void *)((char *)*ptr - sizeof(unsigned long));
	size = *(unsigned long *)realptr;
	if (size <= 1024) {
		free (realptr);
	} else if (size <= 67108864) {
		/* return 2KB ~ 64MB memory to memory pool */
		unsigned long roundup = 1;
		int n = 0;
		int rc = LDAP_SUCCESS;
		while (1) {
			roundup <<= 1;
			n++;
			if (roundup >= size) {
				break;
			}
		}
        PR_ASSERT(n >= 11 && n <= 26);
        rc = mempool_return(n-11, *ptr, (mempool_cleanup_callback)NULL);
        if (LDAP_SUCCESS != rc) {
			free (realptr);
        }
	} else {
		slapi_ch_munmap_no_roundup( ptr, size );
	}
	*ptr = NULL;

	if(!counters_created)
	{
		create_counters();
		counters_created= 1;
	}
    PR_INCREMENT_COUNTER(slapi_ch_counter_free);
    PR_DECREMENT_COUNTER(slapi_ch_counter_exist);
	return;
}

char *
slapi_ch_mmap(unsigned long len)
{
	char   *newmem;
	long   sc_page_size = config_get_system_page_size();
	int	   sc_page_bits = config_get_system_page_bits();
	unsigned long roundup = (len&(sc_page_size-1))?(((len>>sc_page_bits)+1)<<sc_page_bits):len;
	if ( (newmem = (char *)mmap(NULL, roundup, PROT_READ | PROT_WRITE,
			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0/*ignored */)) == MAP_FAILED ) {
		int	oserr = errno;

	  	oom_occurred();
		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		    "mmap of %lu bytes failed; OS error %d (%s)%s\n",
			roundup, oserr, slapd_system_strerror( oserr ), oom_advice );
		exit( 1 );
	}
	*(unsigned long *)newmem = roundup;
	newmem += sizeof(unsigned long);
	return( newmem );
}

int
slapi_ch_munmap(void **start, unsigned long len)
{
	long   sc_page_size = config_get_system_page_size();
	int	   sc_page_bits = config_get_system_page_bits();
	unsigned long roundup = (len&(sc_page_size-1))?(((len>>sc_page_bits)+1)<<sc_page_bits):len;
	void  *realstart = *start - sizeof(unsigned long);
	int    rc = munmap(realstart, roundup);
	if (0 != rc) {
		int	oserr = errno;

		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		    "munmap of %lu bytes failed; OS error %d (%s)\n",
			roundup, oserr, slapd_system_strerror( oserr ) );
		/* Leaked. This should not happen */
	}
	*start = NULL;
	return rc;
}

static char *
slapi_ch_mmap_no_roundup( unsigned long	size)
{
	char	*newmem;
	unsigned long	mysize;

	if ( (newmem = (char *)mmap(NULL, size + sizeof(unsigned long),
					PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
					-1, 0/*ignored */)) == MAP_FAILED ) {
		int	oserr = errno;
	
		oom_occurred();
		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		    "mmap of %lu bytes failed; OS error %d (%s)%s\n",
			size + sizeof(unsigned long), oserr,
			slapd_system_strerror( oserr ), oom_advice );
		exit( 1 );
	}
	*(unsigned long *)newmem = size;
	newmem += sizeof(unsigned long);

	return newmem;
}

static int
slapi_ch_munmap_no_roundup(void **start, unsigned long len)
{
	void  *realstart = *start - sizeof(unsigned long);
	int    reallen = len + sizeof(unsigned long);
	int    rc = munmap(realstart, reallen);
	if (0 != rc) {
		int	oserr = errno;

		slapi_log_error( SLAPI_LOG_FATAL, SLAPD_MODULE,
		    "munmap of %lu bytes failed; OS error %d (%s)\n",
			len, oserr, slapd_system_strerror( oserr ) );
		/* Leaked. This should not happen */
	}
	*start = NULL;
	return rc;
}

/*
  This function is just like PR_smprintf.  It works like sprintf
  except that it allocates enough memory to hold the result
  string and returns that allocated memory to the caller.  The
  caller must use slapi_ch_free_string to free the memory.
  It should only be used in those situations that will eventually free
  the memory using slapi_ch_free_string e.g. allocating a string
  that will be freed as part of pblock cleanup, or passed in to create
  a Slapi_DN, or things of that nature.  If you have control of the
  flow such that the memory will be allocated and freed in the same
  scope, better to just use PR_smprintf and PR_smprintf_free instead
  because it is likely faster.
*/
/*
  This implementation is the same as PR_smprintf.  
  The above comment does not apply to this function for now.
  see [150809] for more details.
  WARNING - with this fix, this means we are now mixing PR_Malloc with
  slapi_ch_free.  Which is ok for now - they both use malloc/free from
  the operating system.  But if this changes in the future, this
  function will have to change as well.
*/
char *
slapi_ch_smprintf(const char *fmt, ...)
{
	char *p = NULL, *q = NULL;
	va_list ap;

	if (NULL == fmt) {
		return NULL;
	}

	va_start(ap, fmt);
	p = PR_vsmprintf(fmt, ap);
	va_end(ap);

	q = slapi_ch_strdup (p); 	/* ugly ...; hope there's any better way */
	free(p);

	return q;
}
#endif /* MEMPOOL_EXPERIMENTAL */


Index: add.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/add.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- add.c	25 Jan 2008 00:59:00 -0000	1.12
+++ add.c	15 Oct 2008 06:30:03 -0000	1.13
@@ -158,7 +158,7 @@
 			ber_bvecfree( vals );
 			goto free_and_return;
 		}
-		free( type );
+		slapi_ch_free_string(&type);
 	
        /* for now we just ignore attributes that client is not allowed
           to modify so not to break existing clients */


Index: attrsyntax.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/attrsyntax.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- attrsyntax.c	4 Jun 2008 22:22:55 -0000	1.7
+++ attrsyntax.c	15 Oct 2008 06:30:03 -0000	1.8
@@ -695,9 +695,7 @@
 	if ( NULL != *pi ) {
 		rc = 0;
 	}
-	if ( tmp != NULL ) {
-		free( tmp );
-	}
+	slapi_ch_free_string(&tmp);
 
 	return( rc );
 }


Index: ava.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/ava.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ava.c	11 Jul 2007 21:29:06 -0000	1.7
+++ ava.c	15 Oct 2008 06:30:03 -0000	1.8
@@ -62,13 +62,13 @@
 
 	if ( ber_scanf( ber, "{ao}", &type, &ava->ava_value )
 	    == LBER_ERROR ) {
-        slapi_ch_free_string(&type);
+        slapi_ch_free_string( &type );
         ava_done(ava);
 		LDAPDebug( LDAP_DEBUG_ANY, "  get_ava ber_scanf\n", 0, 0, 0 );
 		return( LDAP_PROTOCOL_ERROR );
 	}
 	ava->ava_type = slapi_attr_syntax_normalize(type);
-	free( type );
+	slapi_ch_free_string( &type );
 
 	return( 0 );
 }


Index: bind.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/bind.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- bind.c	8 Oct 2008 17:29:03 -0000	1.14
+++ bind.c	15 Oct 2008 06:30:03 -0000	1.15
@@ -652,12 +652,8 @@
     if (be)
         slapi_be_Unlock(be);
     slapi_sdn_done(&sdn);
-    if ( saslmech != NULL ) {
-        free( saslmech );
-    }
-    if ( cred.bv_val != NULL ) {
-        free( cred.bv_val );
-    }
+    slapi_ch_free_string( &saslmech );
+    slapi_ch_free( (void **)&cred.bv_val );
 	if ( bind_target_entry != NULL )
 		slapi_entry_free(bind_target_entry);
 }


Index: ch_malloc.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/ch_malloc.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ch_malloc.c	10 Nov 2006 23:45:40 -0000	1.9
+++ ch_malloc.c	15 Oct 2008 06:30:03 -0000	1.10
@@ -139,6 +139,7 @@
 		op, size, units, units );
 }
 
+#if !defined(MEMPOOL_EXPERIMENTAL)
 char *
 slapi_ch_malloc(
     unsigned long	size
@@ -300,6 +301,7 @@
 #endif
     return newmem;
 }
+#endif /* !MEMPOOL_EXPERIMENTAL */
 
 struct berval*
 slapi_ch_bvdup (const struct berval* v)
@@ -334,6 +336,7 @@
     return newberval;
 }
 
+#if !defined(MEMPOOL_EXPERIMENTAL)
 /*
  *  Function: slapi_ch_free 
  *
@@ -368,6 +371,7 @@
     PR_DECREMENT_COUNTER(slapi_ch_counter_exist);
 	return;
 }
+#endif /* !MEMPOOL_EXPERIMENTAL */
 
 
 /* just like slapi_ch_free, takes the address of the struct berval pointer */
@@ -414,6 +418,7 @@
   the operating system.  But if this changes in the future, this
   function will have to change as well.
 */
+#if !defined(MEMPOOL_EXPERIMENTAL)
 char *
 slapi_ch_smprintf(const char *fmt, ...)
 {
@@ -430,6 +435,7 @@
 
 	return p;
 }
+#endif
 
 /* ========================= NT Specific Leak Checking Code ================================== */
 


Index: computed.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/computed.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- computed.c	10 Nov 2006 23:45:40 -0000	1.5
+++ computed.c	15 Oct 2008 06:30:03 -0000	1.6
@@ -139,7 +139,7 @@
 	PR_ASSERT(NULL != function);
 	PR_ASSERT(NULL != compute_evaluators_lock);
 	PR_RWLock_Wlock(compute_evaluators_lock);
-	new_eval = calloc(1,sizeof (compute_evaluator));
+	new_eval = (compute_evaluator *)slapi_ch_calloc(1,sizeof (compute_evaluator));
 	if (NULL == new_eval) {
 		rc = ENOMEM;
 	} else {
@@ -180,7 +180,7 @@
 		while (current != NULL) {
 			compute_evaluator *asabird = current;
 			current = current->next;
-			free(asabird);
+			slapi_ch_free((void **)&asabird);
 		}
 		PR_RWLock_Unlock(compute_evaluators_lock);
 		/* Free the lock */
@@ -192,7 +192,7 @@
 		while (current != NULL) {
 			compute_rewriter *asabird = current;
 			current = current->next;
-			free(asabird);
+			slapi_ch_free((void **)&asabird);
 		}
 		PR_RWLock_Unlock(compute_rewriters_lock);
 		PR_DestroyRWLock(compute_rewriters_lock);
@@ -208,7 +208,7 @@
 	compute_rewriter *new_rewriter = NULL;
 	PR_ASSERT(NULL != function);
 	PR_ASSERT(NULL != compute_rewriters_lock);
-	new_rewriter = calloc(1,sizeof (compute_rewriter));
+	new_rewriter = (compute_rewriter *)slapi_ch_calloc(1,sizeof (compute_rewriter));
 	if (NULL == new_rewriter) {
 		rc = ENOMEM;
 	} else {


Index: connection.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/connection.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- connection.c	19 Oct 2007 18:48:27 -0000	1.19
+++ connection.c	15 Oct 2008 06:30:03 -0000	1.20
@@ -191,12 +191,12 @@
 	conn->c_prfd= NULL;
 	/* c_ci stays as it is */
 	conn->c_fdi= SLAPD_INVALID_SOCKET_INDEX;
-    conn->c_next= NULL;
-    conn->c_prev= NULL;
+	conn->c_next= NULL;
+	conn->c_prev= NULL;
 	conn->c_extension= NULL;
 	/* remove any SASL I/O from the connection */
 	sasl_io_cleanup(conn);
-        sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
+	sasl_dispose((sasl_conn_t**)&conn->c_sasl_conn);
 
 	/* free the connection socket buffer */
 	connection_free_private_buffer(conn);
@@ -2310,7 +2310,7 @@
 
 	pb = tmp->pb;
 	/* Free the memory used by the pb found. */
-	free ((char *) tmp);
+	slapi_ch_free ((void **)&tmp);
 
 	return (pb);
 }
@@ -2448,7 +2448,7 @@
 	typelen= conn->c_authtype ? strlen (conn->c_authtype) : 0;
 
 	slapi_sdn_done(&op->o_sdn);
-	slapi_ch_free((void **) &(op->o_authtype));
+	slapi_ch_free_string(&(op->o_authtype));
     if (dnlen <= 0 && typelen <= 0) {
         op->o_authtype = NULL;
     } else {


Index: entry.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/entry.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- entry.c	3 Oct 2008 04:28:22 -0000	1.18
+++ entry.c	15 Oct 2008 06:30:03 -0000	1.19
@@ -1918,7 +1918,7 @@
 				*actual_type_name =
 							(char**)slapi_ch_malloc(sizeof(*actual_type_name));
 				slapi_attr_get_type( tmp_attr, &vattr_type );
-				**actual_type_name = strdup(vattr_type);
+				**actual_type_name = slapi_ch_strdup(vattr_type);
 							
 			}
 		}
@@ -1974,7 +1974,7 @@
 				*results = valueset_dup(&(tmp_attr->a_present_values));
 
 				slapi_attr_get_type( tmp_attr, &vattr_type );
-				*actual_type_name = strdup(vattr_type);
+				*actual_type_name = slapi_ch_strdup(vattr_type);
 							
 			}
 		}


Index: filter.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/filter.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- filter.c	8 Oct 2008 17:29:03 -0000	1.10
+++ filter.c	15 Oct 2008 06:30:04 -0000	1.11
@@ -303,7 +303,7 @@
 		} else {
 			err = LDAP_SUCCESS;
 			f->f_type = slapi_attr_syntax_normalize( type );
-			free( type );
+			slapi_ch_free_string( &type );
 			filter_compute_hash(f);
 			*fstr = slapi_ch_smprintf( "(%s=*)", f->f_type );
 		}
@@ -458,7 +458,7 @@
 		return( LDAP_PROTOCOL_ERROR );
 	}
 	f->f_sub_type = slapi_attr_syntax_normalize( type );
-	free( type );
+	slapi_ch_free_string( &type );
 	f->f_sub_initial = NULL;
 	f->f_sub_any = NULL;
 	f->f_sub_final = NULL;
@@ -477,7 +477,7 @@
 		}
 		if ( val == NULL || *val == '\0' ) {
 			if ( val != NULL ) {
-				free( val );
+				slapi_ch_free_string( &val );
 			}
 			return( LDAP_INVALID_SYNTAX );
 		}
@@ -593,7 +593,7 @@
 				rc = LDAP_PROTOCOL_ERROR;
 			    } else {
 				mrf->mrf_type = slapi_attr_syntax_normalize(type);
-				free (type);
+				slapi_ch_free_string (&type);
 			    }
 			}
 			gotelem++;
@@ -642,7 +642,7 @@
 Slapi_Filter *
 slapi_filter_dup(Slapi_Filter *f)
 {
-	Slapi_Filter *out = 0;
+	Slapi_Filter         *out = 0;
 	struct slapi_filter *fl = 0;
 	struct slapi_filter **outl = 0;
 	struct slapi_filter *lastout = 0;
@@ -651,7 +651,7 @@
 		return NULL;
 	}
 
-	out = (struct slapi_filter*)calloc(1, sizeof(struct slapi_filter));
+	out = (struct slapi_filter*)slapi_ch_calloc(1, sizeof(struct slapi_filter));
 	if ( out == NULL ) {
 		LDAPDebug(LDAP_DEBUG_ANY, "slapi_filter_dup: memory allocation error\n",
 		    0, 0, 0 );


Index: filtercmp.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/filtercmp.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- filtercmp.c	10 Nov 2006 23:45:40 -0000	1.6
+++ filtercmp.c	15 Oct 2008 06:30:05 -0000	1.7
@@ -264,7 +264,7 @@
 	return 1;
     ret = 1;	/* assume failure until done comparing */
     if (count1 > 20)
-	tally = (int *)malloc(count1);
+	tally = (int *)slapi_ch_malloc(count1);
     else
 	tally = buf;
     if (!tally)
@@ -292,7 +292,7 @@
 
 done:
     if ((count1 > 20) && tally)
-	free(tally);
+	slapi_ch_free((void **)&tally);
     return ret;
 }
 
@@ -310,7 +310,7 @@
 	return 1;
     ret = 1;
     if (count1 > 20)
-	tally = (int *)malloc(count1);
+	tally = (int *)slapi_ch_malloc(count1);
     else
 	tally = buf;
     if (!tally)
@@ -336,7 +336,7 @@
 
 done:
     if ((count1 > 20) && tally)
-	free(tally);
+	slapi_ch_free((void **)&tally);
     return ret;
 }
 


Index: libglobs.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/libglobs.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- libglobs.c	8 Oct 2008 17:29:03 -0000	1.25
+++ libglobs.c	15 Oct 2008 06:30:05 -0000	1.26
@@ -585,6 +585,14 @@
 		NULL, 0,
 		(void **)&global_slapdFrontendConfig.outbound_ldap_io_timeout,
 		CONFIG_INT, NULL}
+#ifdef MEMPOOL_EXPERIMENTAL
+	,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
+		NULL, 0,
+		(void**)&global_slapdFrontendConfig.mempool_switch, CONFIG_ON_OFF, (ConfigGetFunc)config_get_mempool_switch},
+	{CONFIG_MEMPOOL_MAXFREELIST_ATTRIBUTE, config_set_mempool_maxfreelist,
+		NULL, 0,
+		(void**)&global_slapdFrontendConfig.mempool_maxfreelist, CONFIG_INT, (ConfigGetFunc)config_get_mempool_maxfreelist}
+#endif /* MEMPOOL_EXPERIMENTAL */
 };
 
 /*
@@ -940,6 +948,19 @@
   cfg->auditlog_exptime = 1;
   cfg->auditlog_exptimeunit = slapi_ch_strdup("month");
 
+#ifdef MEMPOOL_EXPERIMENTAL
+  cfg->mempool_switch = LDAP_ON;
+  cfg->mempool_maxfreelist = 1024;
+  cfg->system_page_size = sysconf(_SC_PAGE_SIZE);	/* not to get every time; no set, get only */
+  {
+    long sc_size = cfg->system_page_size;
+    cfg->system_page_bits = 0;
+    while ((sc_size >>= 1) > 0) {
+      cfg->system_page_bits++;	/* to calculate once; no set, get only */
+    }
+  }
+#endif /* MEMPOOL_EXPERIMENTAL */
+
   init_config_get_and_set();
 }
 
@@ -4840,6 +4861,79 @@
 	return retVal;
 }
 
+#ifdef MEMPOOL_EXPERIMENTAL
+int
+config_set_mempool_switch( const char *attrname, char *value, char *errorbuf, int apply ) {
+	int retVal = LDAP_SUCCESS;
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+	retVal = config_set_onoff(attrname,
+		value,
+		&(slapdFrontendConfig->mempool_switch),
+		errorbuf,
+		apply);
+
+	return retVal;
+}
+
+int
+config_get_mempool_switch()
+{
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+	return slapdFrontendConfig->mempool_switch;
+}
+
+int
+config_set_mempool_maxfreelist( const char *attrname, char *value, char *errorbuf, int apply )
+{
+	int retVal = LDAP_SUCCESS;
+	char *endp = NULL;
+	int maxfreelist;
+
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+	
+	if ( config_value_is_null( attrname, value, errorbuf, 0 )) {
+		return LDAP_OPERATIONS_ERROR;
+	}
+	errno = 0;
+	maxfreelist = strtol(value, &endp, 10);
+	if (0 != errno ) {
+		return LDAP_OPERATIONS_ERROR;
+	}
+
+	if ( apply ) {
+		CFG_LOCK_WRITE(slapdFrontendConfig);
+
+		slapdFrontendConfig->mempool_maxfreelist = maxfreelist;
+	
+		CFG_UNLOCK_WRITE(slapdFrontendConfig);
+	}
+	
+	return retVal;
+}
+
+int
+config_get_mempool_maxfreelist()
+{
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+	return slapdFrontendConfig->mempool_maxfreelist;
+}
+
+long
+config_get_system_page_size()
+{
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+	return slapdFrontendConfig->system_page_size;
+}
+
+int
+config_get_system_page_bits()
+{
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+	return slapdFrontendConfig->system_page_bits;
+}
+#endif /* MEMPOOL_EXPERIMENTAL */
+
 int
 config_set_csnlogging(const char *attrname, char *value, char *errorbuf, int apply)
 {


Index: main.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/main.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- main.c	8 Oct 2008 17:29:03 -0000	1.25
+++ main.c	15 Oct 2008 06:30:05 -0000	1.26
@@ -225,7 +225,7 @@
   char *log=NULL, *ptr=NULL;
   int rc=0;
 
-  log=strdup(name);
+  log=slapi_ch_strdup(name);
   if(strip_fn) 
   {
     if((ptr=strrchr(log,'/'))==NULL)
@@ -250,7 +250,7 @@
     }
     PR_CloseDir( dir );
   }
-  free(log);
+  slapi_ch_free_string(&log);
 }
 
 /* Changes the owner of the files in the logs and
@@ -621,6 +621,12 @@
 }
 #endif /* WIN32 */
 
+#ifdef MEMPOOL_EXPERIMENTAL
+void _free_wrapper(void *ptr)
+{
+	slapi_ch_free(&ptr);
+}
+#endif
 
 int
 main( int argc, char **argv)
@@ -635,6 +641,19 @@
 	_main();
 #endif
 #endif
+#ifdef MEMPOOL_EXPERIMENTAL
+	/* to use LDAP C SDK lber functions seemlessly with slapi_ch_malloc funcs,
+	 * setting the slapi_ch_malloc funcs to lber option here. */
+	{
+		struct ldap_memalloc_fns memalloc_fns;
+
+		memalloc_fns.ldapmem_malloc = (LDAP_MALLOC_CALLBACK *)slapi_ch_malloc;
+		memalloc_fns.ldapmem_calloc = (LDAP_CALLOC_CALLBACK *)slapi_ch_calloc;
+		memalloc_fns.ldapmem_realloc = (LDAP_REALLOC_CALLBACK *)slapi_ch_realloc;
+		memalloc_fns.ldapmem_free = (LDAP_FREE_CALLBACK *)_free_wrapper;
+		ldap_set_option( 0x1, LDAP_OPT_MEMALLOC_FN_PTRS, &memalloc_fns );
+	}
+#endif
 	/*
 	 * Initialize NSPR very early. NSPR supports implicit initialization,
 	 * but it is not bulletproof -- so it is better to be explicit.


Index: operation.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/operation.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- operation.c	10 Nov 2006 23:45:40 -0000	1.6
+++ operation.c	15 Oct 2008 06:30:05 -0000	1.7
@@ -170,7 +170,7 @@
 	    factory_destroy_extension(get_operation_object_type(),*op,conn,&((*op)->o_extension));
 		slapi_sdn_done(&(*op)->o_sdn);
 		slapi_sdn_free(&(*op)->o_target_spec);
-		free( (*op)->o_authtype );
+		slapi_ch_free_string( &(*op)->o_authtype );
 		if ( (*op)->o_searchattrs != NULL ) {
 			cool_charray_free( (*op)->o_searchattrs );
 		}


Index: proto-slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/proto-slap.h,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- proto-slap.h	27 Aug 2008 21:56:07 -0000	1.36
+++ proto-slap.h	15 Oct 2008 06:30:05 -0000	1.37
@@ -346,6 +346,11 @@
 int config_set_localuser( const char *attrname, char *value, char *errorbuf, int apply );
 #endif /* !_WIN32 */
 
+#ifdef MEMPOOL_EXPERIMENTAL
+int config_set_mempool_switch( const char *attrname, char *value, char *errorbuf, int apply );
+int config_set_mempool_maxfreelist( const char *attrname, char *value, char *errorbuf, int apply );
+#endif /* MEMPOOL_EXPERIMENTAL */
+
 int config_get_SSLclientAuth();
 int config_get_ssl_check_hostname();
 char *config_get_SSL3ciphers();
@@ -451,6 +456,13 @@
 int config_get_rewrite_rfc1274();
 int config_get_outbound_ldap_io_timeout(void);
 int config_get_csnlogging();
+#ifdef MEMPOOL_EXPERIMENTAL
+int config_get_mempool_switch();
+int config_get_mempool_maxfreelist();
+long config_get_system_page_size();
+int config_get_system_page_bits();
+#endif
+
 int is_abspath(const char *);
 char* rel2abspath( char * );
 char* rel2abspath_ext( char *, char * );


Index: rwlock.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/rwlock.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- rwlock.c	10 Nov 2006 23:45:40 -0000	1.5
+++ rwlock.c	15 Oct 2008 06:30:05 -0000	1.6
@@ -193,23 +193,21 @@
 {
     rwl	*rp;
 
-    if (( rp = (rwl *)malloc( sizeof( rwl ))) == NULL ) {
-	return NULL;
-    }
+    rp = (rwl *)slapi_ch_malloc( sizeof( rwl ));
     
     if (( rp->rwl_readers_mutex = PR_NewLock()) == NULL ) {
-	free( rp );
+	slapi_ch_free( (void **)&rp );
 	return NULL;
     }
     if (( rp->rwl_writers_mutex = PR_NewLock()) == NULL ) {
 	PR_DestroyLock( rp->rwl_readers_mutex );
-	free( rp );
+	slapi_ch_free( (void **)&rp );
 	return NULL;
     }
     if (( rp->rwl_writer_waiting_cv = PR_NewCondVar( rp->rwl_readers_mutex )) == NULL ) {
 	PR_DestroyLock( rp->rwl_readers_mutex );
 	PR_DestroyLock( rp->rwl_writers_mutex );
-	free( rp );
+	slapi_ch_free( (void **)&rp );
     }
     rp->rwl_num_readers = rp->rwl_writer_waiting = 0;
     
@@ -254,6 +252,6 @@
 	PR_DestroyCondVar( rp->rwl_writer_waiting_cv );
     }
     memset( rp, '\0', sizeof( rwl ));
-    free( rp );
+    slapi_ch_free( (void **)&rp );
     *rh = NULL;
 }


Index: slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slap.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- slap.h	15 Jul 2008 16:49:42 -0000	1.35
+++ slap.h	15 Oct 2008 06:30:05 -0000	1.36
@@ -1769,6 +1769,11 @@
 #define CONFIG_HASH_FILTERS_ATTRIBUTE "nsslapd-hash-filters"
 #define CONFIG_OUTBOUND_LDAP_IO_TIMEOUT_ATTRIBUTE "nsslapd-outbound-ldap-io-timeout"
 
+#ifdef MEMPOOL_EXPERIMENTAL
+#define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool"
+#define CONFIG_MEMPOOL_MAXFREELIST_ATTRIBUTE "nsslapd-mempool-maxfreelist"
+#endif /* MEMPOOL_EXPERIMENTAL */
+
 /* flag used to indicate that the change to the config parameter should be saved */
 #define CONFIG_APPLY 1
 
@@ -1960,6 +1965,12 @@
 #ifndef _WIN32
   struct passwd *localuserinfo; /* userinfo of localuser */
 #endif /* _WIN32 */
+#ifdef MEMPOOL_EXPERIMENTAL
+  int mempool_switch;           /* switch to turn memory pool on/off */
+  int mempool_maxfreelist;      /* max free list length per memory pool item */
+  long system_page_size;		/* system page size */
+  int system_page_bits;			/* bit count to shift the system page size */
+#endif /* MEMPOOL_EXPERIMENTAL */
 } slapdFrontendConfig_t;
 
 #define SLAPD_FULL	0


Index: slapi2nspr.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi2nspr.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- slapi2nspr.c	10 Nov 2006 23:45:40 -0000	1.5
+++ slapi2nspr.c	15 Oct 2008 06:30:05 -0000	1.6
@@ -214,6 +214,12 @@
     return( prrc == PR_SUCCESS ? 1 : 0 );
 }
 
+#ifdef MEMPOOL_EXPERIMENTAL
+void _free_wrapper(void *ptr)
+{
+    slapi_ch_free(&ptr);
+}
+#endif
 
 /*
  * Function: slapi_ldap_init()
@@ -239,18 +245,40 @@
      * Note that ldapssl_init() uses libprldap implicitly.
      */
 
+#ifdef MEMPOOL_EXPERIMENTAL
+    {
+    /* 
+     * slapi_ch_malloc functions need to be set to LDAP C SDK
+     */
+    struct ldap_memalloc_fns memalloc_fns;
+    memalloc_fns.ldapmem_malloc = (LDAP_MALLOC_CALLBACK *)slapi_ch_malloc;
+    memalloc_fns.ldapmem_calloc = (LDAP_CALLOC_CALLBACK *)slapi_ch_calloc;
+    memalloc_fns.ldapmem_realloc = (LDAP_REALLOC_CALLBACK *)slapi_ch_realloc;
+    memalloc_fns.ldapmem_free = (LDAP_FREE_CALLBACK *)_free_wrapper;
+    }
+    /* 
+     * MEMPOOL_EXPERIMENTAL: 
+     * These LDAP C SDK init function needs to be revisited.
+     * In ldap_init called via ldapssl_init and prldap_init initializes
+     * options and set default values including memalloc_fns, then it
+     * initializes as sasl client by calling sasl_client_init.  In
+     * sasl_client_init, it creates mechlist using the malloc function
+     * available at the moment which could mismatch the malloc/free functions
+     * set later.
+     */
+#endif
     if ( secure ) {
 	ld = ldapssl_init( ldaphost, ldapport, secure );
     } else {
 	ld = prldap_init( ldaphost, ldapport, shared );
     }
 
-	/* Update snmp interaction table */
-	if ( ld == NULL) {
-		set_snmp_interaction_row( ldaphost, ldapport, -1);
-	} else {
-		set_snmp_interaction_row( ldaphost, ldapport, 0);
-	}
+    /* Update snmp interaction table */
+    if ( ld == NULL) {
+	set_snmp_interaction_row( ldaphost, ldapport, -1);
+    } else {
+	set_snmp_interaction_row( ldaphost, ldapport, 0);
+    }
 
     if ( ld != NULL ) {
 	/*




More information about the Fedora-directory-commits mailing list