/*
#ident	"@(#)smail/src:RELEASE-3_2_0_115:alloc.h,v 1.13 2002/10/01 21:44:45 woods Exp"
 */

/*
 *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
 *    Copyright (C) 1992  Ronald S. Karr
 * 
 * See the file COPYING, distributed with smail, for restriction
 * and warranty information.
 */

/*
 * alloc.h:
 *	block storage allocation
 * 	    This allows a given storage allocation to be associated 
 *	    with a group of other storage allocations.  It is
 *	    possible to free or test for existence of the class.
 *
 *	    A block a pointer to a chain of segments.  Each segment
 *	    refers to one storage allocation.  A block also contains
 *	    the total number of segments allocated.  If this number is
 *	    zero, then no storage is associated with the block.
 */

/*
 * block allocation data structure
 */
struct block {
    struct bseg *next;	/* if cnt > 0 then next holds segment chain */
    int cnt;		/* number of segments in the block */
};
struct bseg {
    struct bseg *next;	/* if != NULL, then next alloc in block */
    char *data;		/* the storage allocated */
};

/*
 * handy macros to determine if a block is active
 */
#define is_memory(block_ptr) ((struct block *)(block_ptr)->cnt)
#define is_free(block_ptr) (!(struct block *)(block_ptr)->cnt)

/*
 * backward compat macros for pmalloc() - XXX
 */
#define pmalloc(size) (bmalloc((size),perm))
#define prealloc(data,size) (brealloc((data),(size),perm))
#define pfree(data) (bfree((data),perm))

/*
 * X_CHECK - check for the xmalloc magic number
 *
 * As a debugging aid, the integer X_MAGIC is stored at the beginning
 * of each block allocated with xmalloc().  This integer is then
 * cleared after a call to xfree().  This macro checks for the magic
 * characters and calls panic if they do not exist.
 */
#define X_MAGIC	  ((ALIGNED_TYPE)0xe8f987b1)
#define X_CHECK(p)							\
	(((ALIGNED_TYPE *)(p))[-1] != X_MAGIC ?				\
		(write_log(WRITE_LOG_PANIC,				\
			"X_CHECK failed!  ptr=0x%lx, line=%d, file=%s", \
			(long)(p), __LINE__, __FILE__),			\
		 x_dont_panic ?						\
		    FAIL :						\
		    (abort(), 0))					\
	    : SUCCEED)
 
/* use these macros to panic code which should not generate a panic */
#define X_NO_PANIC() (x_dont_panic = TRUE)
#define X_PANIC_OKAY() (x_dont_panic = FALSE)

/* external variables defined in alloc.c */
extern struct block *perm;		/* permanent allocation block */
extern int x_dont_panic;		/* dont panic in X_CHECK() */

/* external functions defined in alloc.c */
extern char *xmalloc __P((size_t));
extern char *xrealloc __P((char *, size_t));
extern void xfree __P((char *));
extern char *bmalloc __P((size_t, struct block *));
extern char *brealloc __P((char *, size_t, struct block *));
extern void bfree __P((char *, struct block *));
extern struct block *malloc_block __P((void));
extern void realloc_block __P((char *, struct block *, struct block *));
extern void free_block __P((struct block *));
