/*
 * @DEC_COPYRIGHT@
 */
/*
 * HISTORY
 * $Log:	net_malloc.h,v $
 * Revision 4.2  91/09/19  22:45:21  devbld
 * Adding ODE Headers
 * 
 * $EndLog$
 */
/*	
 *	@(#)$RCSfile: net_malloc.h,v $ $Revision: 4.2 $ (DEC) $Date: 91/09/19 22:45:21 $
 */ 
/*
 */
/*
 * (c) Copyright 1990, OPEN SOFTWARE FOUNDATION, INC.
 * ALL RIGHTS RESERVED
 */
/*
 * OSF/1 Release 1.0
 */
/*
 * Malloc header file for OSF/1 networking.
 *
 *	NET_MALLOC(pointer, cast, size, type, flag)
 *	NET_FREE(pointer, type)
 *	(types, flags, etc defined)
 *
 * If Unix (4.4) we expect malloc.h to define the support.
 * Else if Mach, we use zones and other mechanisms.
 */

#if	!MACH

#ifndef	M_WAITOK
#include "sys/malloc.h"
#endif

#define	NET_MALLOC(p,c,s,t,f)	MALLOC(p,c,s,t,f)
#define NET_FREE(p,t)		FREE(p,t)

#else	/* MACH */

/*
 * Types of memory to be allocated (not all are used by net)
 */
#define	M_FREE		0	/* should be on free list */
#define M_MBUF		1	/* mbuf */
#define M_DEVBUF	2	/* device driver memory */
#define	M_SOCKET	3	/* socket structure */
#define	M_PCB		4	/* protocol control block */
#define	M_RTABLE	5	/* routing tables */
#define	M_HTABLE	6	/* IMP host tables */
#define	M_FTABLE	7	/* fragment reassembly header */
#define	M_IFADDR	9	/* interface address */
#define	M_SOOPTS	10	/* socket options */
#define	M_SONAME	11	/* socket name */
#define M_MOUNT		20	/* vfs mount struct */
#define M_FHANDLE	21	/* network file handle */
#define	M_NFSREQ	22	/* NFS request header */
#define	M_NFSMNT	23	/* NFS mount structure */
#define M_TEMP		31	/* misc temporary data buffers (was 49) */
#define M_LAST		32

struct netmallocstats {
	long	ns_inuse;	/* # of packets of this type currently in use */
	long	ns_calls;	/* total packets of this type ever allocated */
	long	ns_fail;	/* total times failed to get if M_NOWAIT */
	long	ns_maxsize;	/* biggest size allocated */
};

#include "kern/kalloc.h"

/*
 * "flags" to NET_MALLOC actually are routines to get memory. Note when
 * running in a thread context, we may block for the pmap routines to
 * fetch more memory. When in a software interrupt context, this is
 * not the case. The objects fetched by NET_MALLOC are of variable
 * length, but are largely < 256 bytes. Native zones may replace the
 * kalloc facility. Mbufs always come from native blocks (clusters).
 *
 * When using "kget" there is a danger of failing at many points. A zone
 * cannot be expanded until it is full, and then only when the caller
 * is willing to block. This causes problems all over the code. An
 * entry point to expand a zone would be a prerequisite to fixing this.
 */
#define M_WAITOK	kalloc
#if	NETISR_THREAD
#define M_NOWAIT	M_WAITOK
#else
#define M_NOWAIT	kget
#endif

/* Define a "kchunk" to save the length while preserving alignment */
typedef struct { int len; /* data follows */ } kchunk;

#define NET_MALLOC(addr, cast, size, type, flags) {		\
	netmallocstats[type].ns_calls++;			\
	if ((size) > netmallocstats[type].ns_maxsize)		\
		netmallocstats[type].ns_maxsize = (size);	\
	if ((addr) = (cast)flags((size)+sizeof(kchunk))) {	\
		((kchunk *)(addr))->len = ((size)+sizeof(kchunk));\
		(addr) = (cast)(((kchunk *)(addr))+1);		\
		netmallocstats[type].ns_inuse++;		\
	} else							\
		netmallocstats[type].ns_fail++;			\
}

#define NET_FREE(addr, type) {					\
	kfree((caddr_t)(((kchunk *)(addr))-1), (((kchunk *)(addr))-1)->len);\
	--netmallocstats[type].ns_inuse;			\
}

#ifdef	_KERNEL
extern struct	netmallocstats netmallocstats[M_LAST];
#endif
#endif	/* MACH */
