/*
 * Copyright (c) 2001-2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 *	$Id: mem.h,v 1.3 2005/06/16 00:09:34 ca Exp $
 */

#ifndef SM_HEAP_H
#define SM_HEAP_H 1

#include "sm/generic.h"
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/debug.h"

#ifndef SM_HEAP_CHECK
# define SM_HEAP_CHECK	0
#endif

#ifndef DMALLOC
# define DMALLOC	0
#endif

/* memory context, struct defined in heap.c */
typedef struct sm_mctx_S sm_mctx_T, *sm_mctx_P;

/* zero out memory? */
#define SM_FL_ZALLOC	0x0001

/* flags for memory context */
#define SM_MCTX_FL_NONE	0x0000
#define SM_MCTX_FL_CHK	0x0001

typedef sm_ret_T (sm_mctx_oom_F)(size_t _size, size_t _cur, size_t _lim, void *_cbctx);

#if SM_HEAP_CHECK
# include "sm/iostub.h"
# define sm_malloc(size) sm_ctxalloc_tagged(NULL, 0, size, __FILE__, __LINE__, SmHeapGroup)
# define sm_zalloc(size) sm_ctxalloc_tagged(NULL, SM_FL_ZALLOC, size, __FILE__, __LINE__, SmHeapGroup)
# define sm_free(ptr) sm_ctxfree_tagged(NULL, ptr, __FILE__, __LINE__)
# define sm_free_size(ptr, size) sm_ctxfree_size_tagged(NULL, ptr, size, __FILE__, __LINE__)

# define sm_malloc_tagged(size, __FILE__, __LINE__, SmHeapGroup)	\
	sm_ctxalloc_tagged(NULL, 0, size, __FILE__, __LINE__, SmHeapGroup)
# define sm_zalloc_tagged(size, __FILE__, __LINE__, SmHeapGroup)	\
	sm_ctxalloc_tagged(NULL, SM_FL_ZALLOC, size, __FILE__, __LINE__, SmHeapGroup)

# define sm_ctxmalloc(mctx, size) sm_ctxalloc_tagged(mctx, 0, size, __FILE__, __LINE__, SmHeapGroup)
# define sm_ctxfree(mctx, ptr) sm_ctxfree_tagged(mctx, ptr, __FILE__, __LINE__)
# define sm_ctxfree_size(mctx, ptr, size) sm_ctxfree_size_tagged(mctx, ptr, size, __FILE__, __LINE__)
# define sm_ctxzalloc(mctx, size) sm_ctxalloc_tagged(mctx, SM_FL_ZALLOC, size, __FILE__, __LINE__, SmHeapGroup)

void *sm_ctxalloc_tagged(sm_mctx_P _sm_mctx, uint _flags, size_t, char *, int, int);
void sm_ctxfree_tagged(sm_mctx_P _sm_mctx, void *, char *, int);
void sm_ctxfree_size_tagged(sm_mctx_P _sm_mctx, void *, size_t, char *, int);
bool sm_ctxheap_register(sm_mctx_P _sm_mctx, void *, size_t, char *, int, int);
void sm_ctxheap_checkptr_tagged(sm_mctx_P _sm_mctx, void *, char *, int);
void sm_ctxheap_report(sm_mctx_P _sm_mctx, sm_file_T *, int);

#define sm_heap_report(file, verbosity) sm_ctxheap_report(NULL, file, verbosity)

#else /* SM_HEAP_CHECK */

#define sm_malloc(size)	sm_ctxalloc(NULL, 0, size)
#define sm_zalloc(size)	sm_ctxalloc(NULL, SM_FL_ZALLOC, size)
#define sm_free(ptr)	sm_ctxfree(ptr)

# define sm_ctxmalloc_tagged(ctx, size, file, line, grp)	\
		sm_ctxalloc(ctx, 0, size)
# define sm_ctxzalloc_tagged(ctx, size, file, line, grp)	\
		sm_ctxalloc(ctx, SM_FL_ZALLOC, size)
# define sm_ctxrealloc_tagged(ctx, ptr, size, file, line, grp)	\
		sm_ctxrealloc(ctx, ptr, size)
# define sm_ctxfree_tagged(ctx, ptr, file, line)	\
		sm_ctxfree(ctx, ptr)
# define sm_ctxfree_size_tagged(ctx, ptr, size, file, line)	\
		sm_ctxfree_size(ctx, ptr, size)
# define sm_ctxheap_register(ctx, ptr, size, file, line, grp)	(true)
# define sm_ctxheap_checkptr_tagged(ctx, ptr, tag, num)		SM_NOOP
# define sm_ctxheap_report(ctx, file, verbose)			SM_NOOP
# define sm_ctxmalloc(ctx, size)	sm_ctxalloc((ctx), 0, (size))
# define sm_ctxzalloc(ctx, size)	sm_ctxalloc((ctx), SM_FL_ZALLOC, (size))

void	*sm_ctxalloc(sm_mctx_P _sm_mctx, uint _flags, size_t _size);

void	 sm_ctxfree(sm_mctx_P _sm_mctx, void *);
void	 sm_ctxfree_size(sm_mctx_P _sm_mctx, void *, size_t);
#endif /* SM_HEAP_CHECK */

void *sm_ctxrealloc(sm_mctx_P _sm_mctx, void *, size_t);
void *sm_ctxreallocsize(sm_mctx_P _sm_mctx, void *_ptr, size_t _oldsize, size_t _newsize);
#define sm_realloc(ptr, size)	sm_ctxrealloc(NULL, ptr, size)

#define sm_ctxheap_checkptr(ptr) sm_ctxheap_checkptr_tagged(NULL, ptr, __FILE__, __LINE__)

#if 0
/*
**  sm_f[mc]alloc are plug in replacements for malloc and calloc
**  which can be used in a context requiring a function pointer,
**  and which are compatible with sm_free.  Warning: sm_heap_report
**  cannot report where storage leaked by sm_f[mc]alloc was allocated.
*/

/* XXX unused right now */

void	*sm_fmalloc(size_t);
void	*sm_fcalloc(size_t, size_t);
#endif /* 0 */

/*
**  Allocate 'permanent' storage that can be freed but may still be
**  allocated when the process exits.  sm_heap_report will not complain
**  about a storage leak originating from a call to sm_pmalloc.
*/

#define sm_pmalloc(size)   sm_malloc_tagged(size, __FILE__, __LINE__, 0)

#define sm_heap_group()	SmHeapGroup
#define sm_heap_setgroup(g)	(SmHeapGroup = (g))
#define sm_heap_newgroup()	(SmHeapGroup = ++SmHeapMaxGroup)

#if SM_HEAP_CHECK
extern int SmHeapGroup;
extern int SmHeapMaxGroup;

extern SM_DEBUG_T SmHeapTrace;
extern SM_DEBUG_T SmHeapCheck;
#endif /* SM_HEAP_CHECK */

__BEGIN_DECLS
void	*sm_memdup(const void *_ptr, size_t _size);

sm_ret_T sm_mctx_new(size_t _limit, sm_mctx_oom_F _mctx_oom, void *_cbctx, sm_mctx_P *_psm_mctx);
sm_ret_T sm_mctx_destroy(sm_mctx_P _sm_mctx);
sm_ret_T sm_mctx_flags(sm_mctx_P _sm_mctx, uint _flags);
__END_DECLS

#define SM_FREE(ptr) do			\
	{				\
		if ((ptr) != NULL)	\
		{			\
			sm_free(ptr);	\
			(ptr) = NULL;	\
		}			\
	} while (0)

#define SM_FREE_SIZE(ptr, size) do	\
	{				\
		if ((ptr) != NULL)	\
		{			\
			sm_free_size((ptr), (size));	\
			(ptr) = NULL;	\
		}			\
	} while (0)

#define SM_CTXFREE(mctx, ptr) do	\
	{				\
		if ((ptr) != NULL)	\
		{			\
			sm_ctxfree((mctx), (ptr));	\
			(ptr) = NULL;	\
		}			\
	} while (0)

#define SM_CTXFREE_SIZE(mctx, ptr, size) do	\
	{				\
		if ((ptr) != NULL)	\
		{			\
			sm_free_size((mctx), (ptr), (size));	\
			(ptr) = NULL;	\
		}			\
	} while (0)

#if DMALLOC
# include "dmalloc.h"
#endif

#define SM_IS_MCTX(sm_mctx)	SM_REQUIRE_ISA(sm_mctx, SM_MCTX_MAGIC)

#endif /* ! SM_HEAP_H */


syntax highlighted by Code2HTML, v. 0.9.1