Subject: syntactic sugar for mbuf queue
To: None <tech-kern@netbsd.org>
From: Iain Hibbert <plunky@rya-online.net>
List: tech-kern
Date: 02/03/2006 16:31:29
Hi,
   While working on the Bluetooth protocol I didnt really want to use
ifqueue which was embedded in the networking interface headers but I still
use mbufs and queues of mbufs..  so, I created a generic mbufq (see below)
which is basically a singly linked queue (SIMPLEQ) using the builtin
m_nextpkt instead of field.sqe_next

   I have this in netbt/btvar.h which is probably not the place for it (I
was thinking of splitting up btvar.h as its a bit of a catchall)

   Should this (or something like) be in sys/queue.h? sys/mbuf.h?

   Is there a better way?

iain

/*
 * Simple mbuf chain queueing system, this is basically a SIMPLEQ
 * adapted to mbuf use (ie using m_nextpkt instead of field.sqe_next).
 */
struct mbufq {
	struct mbuf *mq_first;
	struct mbuf **mq_last;
};

#define MBUFQ_INIT(q)		do {				\
	(q)->mq_first = NULL;					\
	(q)->mq_last = &(q)->mq_first;				\
} while (/*CONSTCOND*/0)

#define MBUFQ_ENQUEUE(q, m)	do {				\
	(m)->m_nextpkt = NULL;					\
	*(q)->mq_last = (m);					\
	(q)->mq_last = &(m)->m_nextpkt;				\
} while (/*CONSTCOND*/0)

#define MBUFQ_PREPEND(q, m)	do {				\
	if (((m)->m_nextpkt = (q)->mq_first) == NULL)		\
		(q)->mq_last = &(m)->m_nextpkt;			\
	(q)->mq_first = (m);					\
} while (/*CONSTCOND*/0)

#define MBUFQ_DEQUEUE(q, m)	do {				\
	if (((m) = (q)->mq_first) != NULL) { 			\
		if (((q)->mq_first = (m)->m_nextpkt) == NULL)	\
			(q)->mq_last = &(q)->mq_first;		\
		else						\
			(m)->m_nextpkt = NULL;			\
	}							\
} while (/*CONSTCOND*/0)

#define MBUFQ_DRAIN(q)		do {				\
	struct mbuf *__m0;					\
	while ((__m0 = (q)->mq_first) != NULL) {		\
		(q)->mq_first = __m0->m_nextpkt;		\
		m_freem(__m0);					\
	}							\
	(q)->mq_last = &(q)->mq_first;				\
} while (/*CONSTCOND*/0)

#define MBUFQ_FIRST(q)		((q)->mq_first)
#define MBUFQ_NEXT(m)		((m)->m_nextpkt)