189495Snyan/*-
289495Snyan * Copyright(c) 2002-2011 Exar Corp.
389495Snyan * All rights reserved.
489495Snyan *
589495Snyan * Redistribution and use in source and binary forms, with or without
689495Snyan * modification are permitted provided the following conditions are met:
789495Snyan *
889495Snyan *    1. Redistributions of source code must retain the above copyright notice,
989495Snyan *       this list of conditions and the following disclaimer.
1089495Snyan *
1189495Snyan *    2. Redistributions in binary form must reproduce the above copyright
1289495Snyan *       notice, this list of conditions and the following disclaimer in the
1389495Snyan *       documentation and/or other materials provided with the distribution.
1489495Snyan *
1589495Snyan *    3. Neither the name of the Exar Corporation nor the names of its
1689495Snyan *       contributors may be used to endorse or promote products derived from
1789495Snyan *       this software without specific prior written permission.
1889495Snyan *
1989495Snyan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2089495Snyan * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2189495Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2289495Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2389495Snyan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2489495Snyan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2589495Snyan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2689495Snyan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2789495Snyan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2889495Snyan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2989495Snyan * POSSIBILITY OF SUCH DAMAGE.
3089495Snyan */
3189495Snyan/*$FreeBSD$*/
3289495Snyan
3389495Snyan#ifndef	VXGE_LIST_H
3489495Snyan#define	VXGE_LIST_H
3589495Snyan
3689495Snyan__EXTERN_BEGIN_DECLS
3789495Snyan
3889495Snyan/*
3989495Snyan * struct vxge_list_t - List item.
40103641Snyan * @prev: Previous list item.
4189495Snyan * @next: Next list item.
4289495Snyan *
4389495Snyan * Item of a bi-directional linked list.
44103641Snyan */
4589495Snyantypedef struct vxge_list_t {
4689495Snyan	struct vxge_list_t		 *prev;
4789495Snyan	struct vxge_list_t		 *next;
4889495Snyan} vxge_list_t;
4989495Snyan
5089495Snyan/*
5189495Snyan * vxge_list_init - Initialize linked list.
5289495Snyan * @header: first element of the list (head)
5389495Snyan *
5489495Snyan * Initialize linked list.
5589495Snyan * See also: vxge_list_t {}.
5689495Snyan */
5789495Snyanstatic inline void vxge_list_init(vxge_list_t *header)
5897065Snyan{
5997065Snyan	vxge_assert(header != NULL);
6089495Snyan
6189495Snyan	header->next = header;
6289495Snyan	header->prev = header;
6389495Snyan}
6489495Snyan
6597065Snyan/*
6689495Snyan * vxge_list_is_empty - Is the list empty?
6789495Snyan * @header: first element of the list (head)
6889495Snyan *
6989495Snyan * Determine whether the bi-directional list is empty. Return '1' in
7089495Snyan * case of 'empty'.
7189495Snyan * See also: vxge_list_t {}.
7289495Snyan */
7389495Snyanstatic inline int vxge_list_is_empty(vxge_list_t *header)
7489495Snyan{
7589495Snyan	vxge_assert(header != NULL);
7689495Snyan
7789495Snyan	return (header->next == header);
78200776Snyan}
79200776Snyan
80200776Snyan/*
81200776Snyan * vxge_list_first_get - Return the first item from the linked list.
82200776Snyan * @header: first element of the list (head)
83200776Snyan *
84200776Snyan * Returns the next item from the header.
85200776Snyan * Returns NULL if the next item is header itself
86200776Snyan * See also: vxge_list_remove(), vxge_list_insert(), vxge_list_t {}.
87200776Snyan */
8889495Snyanstatic inline vxge_list_t *vxge_list_first_get(vxge_list_t *header)
8989495Snyan{
90	vxge_assert(header != NULL);
91	vxge_assert(header->next != NULL);
92	vxge_assert(header->prev != NULL);
93
94	if (header->next == header)
95		return (NULL);
96	else
97		return (header->next);
98}
99
100/*
101 * vxge_list_remove - Remove the specified item from the linked list.
102 * @item: element of the list
103 *
104 * Remove item from a list.
105 * See also: vxge_list_insert(), vxge_list_t {}.
106 */
107static inline void vxge_list_remove(vxge_list_t *item)
108{
109	vxge_assert(item != NULL);
110	vxge_assert(item->next != NULL);
111	vxge_assert(item->prev != NULL);
112
113	item->next->prev = item->prev;
114	item->prev->next = item->next;
115#if defined(VXGE_DEBUG_ASSERT)
116	item->next = item->prev = NULL;
117#endif
118}
119
120/*
121 * vxge_list_insert - Insert a new item after the specified item.
122 * @new_item: new element of the list
123 * @prev_item: element of the list after which the new element is
124 *		inserted
125 *
126 * Insert new item (new_item) after given item (prev_item).
127 * See also: vxge_list_remove(), vxge_list_insert_before(), vxge_list_t {}.
128 */
129static inline void vxge_list_insert(vxge_list_t *new_item,
130    vxge_list_t *prev_item)
131{
132	vxge_assert(new_item != NULL);
133	vxge_assert(prev_item != NULL);
134	vxge_assert(prev_item->next != NULL);
135
136	new_item->next = prev_item->next;
137	new_item->prev = prev_item;
138	prev_item->next->prev = new_item;
139	prev_item->next = new_item;
140}
141
142/*
143 * vxge_list_insert_before - Insert a new item before the specified item.
144 * @new_item: new element of the list
145 * @next_item: element of the list after which the new element is inserted
146 *
147 * Insert new item (new_item) before given item (next_item).
148 */
149static inline void vxge_list_insert_before(vxge_list_t *new_item,
150    vxge_list_t * next_item)
151{
152	vxge_assert(new_item != NULL);
153	vxge_assert(next_item != NULL);
154	vxge_assert(next_item->next != NULL);
155
156	new_item->next = next_item;
157	new_item->prev = next_item->prev;
158	next_item->prev->next = new_item;
159	next_item->prev = new_item;
160}
161
162#define	vxge_list_for_each(_p, _h) \
163	for (_p = (_h)->next, vxge_os_prefetch(_p->next); _p != (_h); \
164		_p = _p->next, vxge_os_prefetch(_p->next))
165
166#define	vxge_list_for_each_safe(_p, _n, _h) \
167	for (_p = (_h)->next, _n = _p->next; _p != (_h); \
168		_p = _n, _n = _p->next)
169
170#define	vxge_list_for_each_prev_safe(_p, _n, _h) \
171	for (_p = (_h)->prev, _n = _p->prev; _p != (_h); \
172		_p = _n, _n = _p->prev)
173
174#if defined(__GNUC__)
175/*
176 * vxge_container_of - Given a member, return the containing structure.
177 * @ptr:	the pointer to the member.
178 * @type:	the type of the container struct this is embedded in.
179 * @member:	the name of the member within the struct.
180 *
181 * Cast a member of a structure out to the containing structure.
182 */
183#define	vxge_container_of(ptr, type, member) (\
184	{ __typeof(((type *)0)->member) *__mptr = (ptr);	\
185	(type *)(void *)((char *)__mptr - ((ptr_t)&((type *)0)->member)); })
186#else
187/* type unsafe version */
188#define	vxge_container_of(ptr, type, member) \
189	((type *)(void *)((char *)(ptr) - ((ptr_t)&((type *)0)->member)))
190#endif
191
192/*
193 * vxge_offsetof - Offset of the member in the containing structure.
194 * @t:	struct name.
195 * @m:	the name of the member within the struct.
196 *
197 * Return the offset of the member @m in the structure @t.
198 */
199#define	vxge_offsetof(t, m)			((ptr_t)(&((t *)0)->m))
200
201__EXTERN_END_DECLS
202
203#endif	/* VXGE_LIST_H */
204