//////////////////////////////////////////////////
//Title    : pool.c
//Auhtor   : Liu Wei
//Desc     : List and Pool Queue struct implement  
//Created  : 2007-05-01
//Revision :
//
//Revision :
//
//////////////////////////////////////////////////

#ifndef _PUB_LIST_H_
#define _PUB_LIST_H_

//LIFO Queue

#define LIFOQ_HEAD( name , type )                                   \
        struct name                                                 \
        {                                                           \
        	struct type *pLqFirst;/*First elment*/                  \
        }

#define LIFOQ_ENTRY(type)                                           \
        struct                                                      \
        {                                                           \
        	struct type *pLqNext;                                   \
        }

#define	LIFOQ_EMPTY(head)	                                        \
        ((head)->pLqFirst == NULL)

#define	LIFOQ_FIRST(head)	                                        \
        ((head)->pLqFirst)

#define LIFOQ_FOREACH(var, head, field)			                    \
	    for((var) = (head)->pLqFirst; (var); (var) = (var)->field.pLqNext)

#define LIFOQ_INIT(head)                                            \
        {						                                    \
            (head)->pLqFirst = NULL;			                    \
        }

#define LIFOQ_INSERT_AFTER(lifoq_elm, elm, field)                   \
        do                                                          \
        {			                                                \
	        (elm)->field.pLqNext = (lifoq_elm)->field.pLqNext;		\
	        (lifoq_elm)->field.pLqNext = (elm);				        \
        } while (0)

#define LIFOQ_INSERT_HEAD(head, elm, field)                         \
        do                                                          \
        {			                                                \
	        (elm)->field.pLqNext = (head)->pLqFirst;			    \
	        (head)->pLqFirst = (elm);					            \
        } while (0)

#define LIFOQ_NEXT(elm, field)	    ((elm)->field.pLqNext)

#define LIFOQ_REMOVE_HEAD(head, field)                              \
        do                                                          \
        {				                                            \
	        (head)->pLqFirst = (head)->pLqFirst->field.pLqNext;		\
        } while (0)

#define LIFOQ_REMOVE(head, elm, type, field)                        \
        do                                                          \
        {			                                                \
	        if ((head)->pLqFirst == (elm))                          \
	        {				                                        \
		        LIFOQ_REMOVE_HEAD((head), field);			        \
	        }								                        \
	        else                                                    \
	        {								                        \
		        struct type *curelm = (head)->pLqFirst;		        \
                                                                    \
		        while( curelm->field.pLqNext != (elm) )		        \
		        {                                                   \
			         curelm = curelm->field.pLqNext;		        \
			    }                                                   \
		        curelm->field.pLqNext =                             \
		                curelm->field.pLqNext->field.pLqNext;		\
	        }								                        \
        } while (0)

//FIFO Quence

#define FIFOQ_HEAD(name, type)						                \
        struct name                                                 \
        {								                            \
	       struct type *pFqFirst;/* first element */                \
	       struct type **pFqLast;/* addr of last next element */	\
        }

#define FIFOQ_HEAD_INITIALIZER(head)					            \
	    { NULL, &(head).pFqFirst }

#define FIFOQ_ENTRY(type)						                    \
        struct                                                      \
        {								                            \
	       struct type *pFqNext;	/* next element */			    \
        }

#define FIFOQ_EMPTY(head)            ((head)->pFqFirst == NULL)

#define	FIFOQ_INIT(head)                                            \
        do                                                          \
        {	                                    					\
	        (head)->pFqFirst = NULL;					            \
	        (head)->spTQLast = &(head)->pFqFirst;			        \
        } while (0)

#define FIFOQ_FIRST(head)	((head)->pFqFirst)

#define	FIFOQ_LAST(head, type, field)					            \
	   (FIFOQ_EMPTY(head) ? NULL : ((struct type *)                 \
	   ((char *)((head)->spTQLast) - __offsetof(struct type, field))))

#define FIFOQ_FOREACH(var, head, field)				\
	    for((var) = (head)->pFqFirst; (var); (var) = (var)->field.pFqNext)

#define FIFOQ_INSERT_HEAD(head, elm, field)                         \
        do                                                          \
        {			                                                \
	        if (((elm)->field.pFqNext = (head)->pFqFirst) == NULL)	\
		       (head)->spTQLast = &(elm)->field.pFqNext;		    \
	        (head)->pFqFirst = (elm);					            \
        } while (0)

#define FIFOQ_INSERT_TAIL(head, elm, field)                         \
        do                                                          \
        {			                                                \
	       (elm)->field.pFqNext = NULL;					            \
	       *(head)->spTQLast = (elm);					            \
	       (head)->spTQLast = &(elm)->field.pFqNext;			    \
        } while (0)

#define FIFOQ_INSERT_AFTER(head, tqelm, elm, field)                 \
        do                                                          \
        {		                                                    \
	        if (((elm)->field.pFqNext = (tqelm)->field.pFqNext) == NULL)\
		        (head)->spTQLast = &(elm)->field.pFqNext;		    \
	       (tqelm)->field.pFqNext = (elm);				            \
        } while (0)

#define FIFOQ_NEXT(elm, field)	            ((elm)->field.pFqNext)

#define FIFOQ_REMOVE_HEAD(head, field)                              \
        do                                                          \
        {                                                           \
             if (((head)->pFqFirst = (head)->pFqFirst->field.pFqNext) == NULL) \
		        (head)->spTQLast = &(head)->pFqFirst;		        \
        } while (0)

#define FIFOQ_REMOVE_HEAD_UNTIL(head, elm, field)                   \
        do                                                          \
        {                                                           \
	       if (((head)->pFqFirst = (elm)->field.pFqNext) == NULL)   \
		       (head)->spTQLast = &(head)->pFqFirst;		        \
        } while (0)

#define FIFOQ_REMOVE(head, elm, type, field)                        \
        do                                                          \
        {                                                           \
	        if ((head)->pFqFirst == (elm))                          \
	        {				                                        \
		       FIFOQ_REMOVE_HEAD(head, field);			            \
	        }								                        \
	        else                                                    \
	        {								                        \
		       struct type *curelm = (head)->pFqFirst;		        \
		       while( curelm->field.pFqNext != (elm) )		        \
			          curelm = curelm->field.pFqNext;		        \
			                                                        \
		       if((curelm->field.pFqNext =				            \
		              curelm->field.pFqNext->field.pFqNext) == NULL)\
			      (head)->spTQLast = &(curelm)->field.pFqNext;     \
	       }								                        \
        } while (0)

// List 

#define LIST_HEAD(name, type)	 					                \
        struct name                                                 \
        {								                            \
	       struct type *pListFirst;	/* first element */			    \
        }

#define LIST_HEAD_INITIALIZER(head)					                \
	    { NULL }

#define LIST_ENTRY(type)						                            \
        struct                                                              \
        {								                                    \
	       struct type *pListNext;	/* next element */			            \
	       struct type **pListPrev;	/* address of previous next element */	\
        }

/*
 * List functions.
 */

#define	LIST_EMPTY(head)    ((head)->pListFirst == NULL)

#define LIST_FIRST(head)	((head)->pListFirst)

#define LIST_FOREACH(var, head, field)					                    \
	    for((var) = (head)->pListFirst; (var); (var) = (var)->field.pListNext)

#define	LIST_INIT(head)                                                     \
        do                                                                  \
        {						                                            \
	        (head)->pListFirst = NULL;					                    \
        } while (0)

#define LIST_INSERT_AFTER(listelm, elm, field)                                  \
        do                                                                      \
        {			                                                            \
	        if (((elm)->field.pListNext = (listelm)->field.pListNext) != NULL)	\
	        {                                                                   \
		        (listelm)->field.pListNext->field.pListPrev =		            \
		                                 &(elm)->field.pListNext;				\
	        }                                                                   \
	        (listelm)->field.pListNext = (elm);				                    \
	        (elm)->field.pListPrev = &(listelm)->field.pListNext;		        \
        } while (0)

#define LIST_INSERT_BEFORE(listelm, elm, field)                                 \
        do                                                                      \
        {			                                                            \
	        (elm)->field.pListPrev = (listelm)->field.pListPrev;		        \
	        (elm)->field.pListNext = (listelm);				                    \
	        *(listelm)->field.pListPrev = (elm);				                \
	        (listelm)->field.pListPrev = &(elm)->field.pListNext;		        \
        } while (0)

#define LIST_INSERT_HEAD(head, elm, field)                                      \
        do                                                                      \
        {                                                       				\
	        if (((elm)->field.pListNext = (head)->pListFirst) != NULL)		    \
		       (head)->pListFirst->field.pListPrev = &(elm)->field.pListNext;   \
	       (head)->pListFirst = (elm);					                        \
	       (elm)->field.pListPrev = &(head)->pListFirst;			            \
        } while (0)

#define LIST_NEXT(elm, field)	          ((elm)->field.pListNext)

#define LIST_REMOVE(elm, field)                                                 \
        do                                                                      \
        {					                                                    \
	        if ((elm)->field.pListNext != NULL)				                    \
		       (elm)->field.pListNext->field.pListPrev = 			            \
		                                 (elm)->field.pListPrev;				\
	        *(elm)->field.pListPrev = (elm)->field.pListNext;			        \
        } while (0)

/*
 * Tail queue definitions.
 */
#define TAILQ_HEAD(name, type)						                            \
        struct name                                                             \
        {								                                        \
	        struct type *pTQFirst;	/* first element */			                \
	        struct type **pTQLast;	/* addr of last next element */		        \
        }

#define TAILQ_HEAD_INITIALIZER(head)					                        \
	    { NULL, &(head).pTQFirst }

#define TAILQ_ENTRY(type)						                                \
        struct                                                                  \
        {							 	                                        \
	        struct type *pTQNext;	/* next element */			                \
	        struct type **pTQPrev;	/* address of previous next element */	    \
        }

/*
 * Tail queue functions.
 */
#define	TAILQ_EMPTY(head)     ((head)->pTQFirst == NULL)

#define TAILQ_FOREACH(var, head, field)					                        \
	    for (var = TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))

#define TAILQ_FOREACH_REVERSE(var, head, headname, field)		                \
	    for ((var) = TAILQ_LAST((head), headname);			                    \
	         (var);							                                    \
	         (var) = TAILQ_PREV((var), headname, field))

#define	TAILQ_FIRST(head) ((head)->pTQFirst)

#define	TAILQ_LAST(head, headname)                                              \
	    (*(((struct headname *)((head)->pTQLast))->pTQLast))

#define	TAILQ_NEXT(elm, field) ((elm)->field.pTQNext)

#define TAILQ_PREV(elm, headname, field)                                        \
	    (*(((struct headname *)((elm)->field.pTQPrev))->pTQLast))

#define	TAILQ_INIT(head)                                                        \
        do                                                                      \
        {						                                                \
	        (head)->pTQFirst = NULL;					                        \
	        (head)->pTQLast = &(head)->pTQFirst;				                \
        } while (0)

#define TAILQ_INSERT_HEAD(head, elm, field)                                     \
        do                                                                      \
        {			                                                            \
	        if (((elm)->field.pTQNext = (head)->pTQFirst) != NULL)	            \
		        (head)->pTQFirst->field.pTQPrev =			                    \
		                                    &(elm)->field.pTQNext;				\
	        else								                                \
		        (head)->pTQLast = &(elm)->field.pTQNext;		                \
	        (head)->pTQFirst = (elm);					                        \
	        (elm)->field.pTQPrev = &(head)->pTQFirst;			                \
        } while (0)

#define TAILQ_INSERT_TAIL(head, elm, field)                                     \
        do                                                                      \
        {			                                                            \
	       (elm)->field.pTQNext = NULL;					                        \
	       (elm)->field.pTQPrev = (head)->pTQLast;			                    \
	       *(head)->pTQLast = (elm);					                        \
	       (head)->pTQLast = &(elm)->field.pTQNext;			                    \
        } while (0)

#define TAILQ_INSERT_AFTER(head, listelm, elm, field)                           \
        do                                                                      \
        {		                                                                \
	        if (((elm)->field.pTQNext = (listelm)->field.pTQNext) != NULL)      \
		        (elm)->field.pTQNext->field.pTQPrev = &(elm)->field.pTQNext;    \
	        else                                 								\
		        (head)->pTQLast = &(elm)->field.pTQNext;                		\
	        (listelm)->field.pTQNext = (elm);				                    \
	        (elm)->field.pTQPrev = &(listelm)->field.pTQNext;		            \
        } while (0)

#define TAILQ_INSERT_BEFORE(listelm, elm, field)                                \
        do {			                                                        \
	        (elm)->field.pTQPrev = (listelm)->field.pTQPrev;		            \
	        (elm)->field.pTQNext = (listelm);			                     	\
	        *(listelm)->field.pTQPrev = (elm);				                    \
	        (listelm)->field.pTQPrev = &(elm)->field.pTQNext;		            \
        } while (0)

#define TAILQ_REMOVE(head, elm, field)                                          \
        do {			 	                                                    \
	        if (((elm)->field.pTQNext) != NULL)				                    \
		        (elm)->field.pTQNext->field.pTQPrev =  (elm)->field.pTQPrev;    \
	        else                                								\
		        (head)->pTQLast = (elm)->field.pTQPrev;		                    \
	        *(elm)->field.pTQPrev = (elm)->field.pTQNext;			            \
        } while (0)

/*
 * Pool -- Circular queue definitions.
 */
#define POOL_HEAD(name, type)					                                \
        struct name                                                             \
        {								                                        \
	        struct type *pPoolFirst;	/* first element */		                \
	        struct type *pPoolLast;		/* last element */		                \
        }

#define POOL_ENTRY(type)						                                \
        struct                                                                  \
        {								                                        \
	        struct type *pPoolNext;		/* next element */		                \
	        struct type *pPoolPrev;		/* previous element */		            \
        }

/*
 * Pool -- Circular queue functions.
 */

#define POOL_EMPTY(head)     ((head)->pPoolFirst == (void *)(head))

#define POOL_FIRST(head)     ((head)->pPoolFirst)

#define POOL_FOREACH(var, head, field)				                           \
	    for((var) = (head)->pPoolFirst;					                       \
	        (var) != (void *)(head);					                       \
	        (var) = (var)->field.pPoolNext)

#define POOL_FOREACH_REVERSE(var, head, field)			                       \
	    for((var) = (head)->pPoolLast;					                       \
	        (var) != (void *)(head);					                       \
	        (var) = (var)->field.pPoolPrev)

#define	POOL_INIT(head)                                                        \
        do                                                                     \
        {						                                               \
	        (head)->pPoolFirst = (void *)(head);				               \
	        (head)->pPoolLast = (void *)(head);				                   \
        } while (0)

#define POOL_INSERT_AFTER(head, listelm, elm, field)                           \
        do {		                                                           \
	        (elm)->field.pPoolNext = (listelm)->field.pPoolNext;		       \
	        (elm)->field.pPoolPrev = (listelm);				                   \
	        if ((listelm)->field.pPoolNext == (void *)(head))		           \
		       (head)->pPoolLast = (elm);				                       \
	        else								                               \
		       (listelm)->field.pPoolNext->field.pPoolPrev = (elm);	           \
	        (listelm)->field.pPoolNext = (elm);				                   \
        } while (0)

#define POOL_INSERT_BEFORE(head, listelm, elm, field)                          \
        do {		                                                           \
	        (elm)->field.pPoolNext = (listelm);				                   \
	        (elm)->field.pPoolPrev = (listelm)->field.pPoolPrev;		           \
	        if ((listelm)->field.pPoolPrev == (void *)(head))		           \
		       (head)->pPoolFirst = (elm);				                       \
	        else								                               \
		       (listelm)->field.pPoolPrev->field.pPoolNext = (elm);	           \
	        (listelm)->field.pPoolPrev = (elm);			 	                   \
        } while (0)

#define POOL_INSERT_HEAD(head, elm, field)                                     \
        do {			                                                       \
	       (elm)->field.pPoolNext = (head)->pPoolFirst;			               \
	       (elm)->field.pPoolPrev = (void *)(head);				               \
	       if ((head)->pPoolLast == (void *)(head))				               \
		      (head)->pPoolLast = (elm);				                       \
	       else								                                   \
		      (head)->pPoolFirst->field.pPoolPrev = (elm);		               \
	       (head)->pPoolFirst = (elm);					                       \
        } while (0)

#define POOL_INSERT_TAIL(head, elm, field)                                     \
        do {			                                                       \
	       (elm)->field.pPoolNext = (void *)(head);				               \
	       (elm)->field.pPoolPrev = (head)->pPoolLast;		 	               \
	       if ((head)->pPoolFirst == (void *)(head))			               \
		      (head)->pPoolFirst = (elm);				                       \
	       else								                                   \
		      (head)->pPoolLast->field.pPoolNext = (elm);		               \
	       (head)->pPoolLast = (elm);					                       \
        } while (0)

#define POOL_LAST(head)          ((head)->pPoolLast)

#define POOL_NEXT(elm,field)     ((elm)->field.pPoolNext)

#define POOL_PREV(elm,field)     ((elm)->field.pPoolPrev)

#define	POOL_REMOVE(head, elm, field)                                          \
        do {				                                                   \
	       if ((elm)->field.pPoolNext == (void *)(head))			               \
		      (head)->pPoolLast = (elm)->field.pPoolPrev;		               \
	       else								                                   \
		      (elm)->field.pPoolNext->field.pPoolPrev =	(elm)->field.pPoolPrev; \
		    				                                                   \
	       if ((elm)->field.pPoolPrev == (void *)(head))			               \
		      (head)->pPoolFirst = (elm)->field.pPoolNext;		               \
	       else								                                   \
		      (elm)->field.pPoolPrev->field.pPoolNext =(elm)->field.pPoolNext;    \
        } while (0)

#ifdef _KERNEL
/*
 * XXX insque() and remque() are an old way of handling certain queues.
 * They bogusly assumes that all queue heads look alike.
 */

struct quehead
{
    struct quehead *qh_link;
    struct quehead *qh_rlink;
};

#ifdef	__GNUC__

static __inline void insque ( void *a, void *b )
{
    struct quehead *element = a, *head = b;

    element->qh_link = head->qh_link;
    element->qh_rlink = head;
    head->qh_link = element;
    element->qh_link->qh_rlink = element;
}

static __inline void remque ( void *a )
{
    struct quehead *element = a;

    element->qh_link->qh_rlink = element->qh_rlink;
    element->qh_rlink->qh_link = element->qh_link;
    element->qh_rlink = 0;
}

#else                           /* !__GNUC__ */

void insque __P ( ( void *a, void *b ) );
void remque __P ( ( void *a ) );

#endif                          /* __GNUC__ */

#endif                          /* _KERNEL */
#endif
