1/*-
2 * Copyright(c) 2002-2011 Exar Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification are permitted provided the following conditions are met:
7 *
8 *    1. Redistributions of source code must retain the above copyright notice,
9 *       this list of conditions and the following disclaimer.
10 *
11 *    2. Redistributions in binary form must reproduce the above copyright
12 *       notice, this list of conditions and the following disclaimer in the
13 *       documentation and/or other materials provided with the distribution.
14 *
15 *    3. Neither the name of the Exar Corporation nor the names of its
16 *       contributors may be used to endorse or promote products derived from
17 *       this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31/*$FreeBSD$*/
32
33#ifndef	VXGE_LIST_H
34#define	VXGE_LIST_H
35
36__EXTERN_BEGIN_DECLS
37
38/*
39 * struct vxge_list_t - List item.
40 * @prev: Previous list item.
41 * @next: Next list item.
42 *
43 * Item of a bi-directional linked list.
44 */
45typedef struct vxge_list_t {
46	struct vxge_list_t		 *prev;
47	struct vxge_list_t		 *next;
48} vxge_list_t;
49
50/*
51 * vxge_list_init - Initialize linked list.
52 * @header: first element of the list (head)
53 *
54 * Initialize linked list.
55 * See also: vxge_list_t {}.
56 */
57static inline void vxge_list_init(vxge_list_t *header)
58{
59	vxge_assert(header != NULL);
60
61	header->next = header;
62	header->prev = header;
63}
64
65/*
66 * vxge_list_is_empty - Is the list empty?
67 * @header: first element of the list (head)
68 *
69 * Determine whether the bi-directional list is empty. Return '1' in
70 * case of 'empty'.
71 * See also: vxge_list_t {}.
72 */
73static inline int vxge_list_is_empty(vxge_list_t *header)
74{
75	vxge_assert(header != NULL);
76
77	return (header->next == header);
78}
79
80/*
81 * vxge_list_first_get - Return the first item from the linked list.
82 * @header: first element of the list (head)
83 *
84 * Returns the next item from the header.
85 * Returns NULL if the next item is header itself
86 * See also: vxge_list_remove(), vxge_list_insert(), vxge_list_t {}.
87 */
88static inline vxge_list_t *vxge_list_first_get(vxge_list_t *header)
89{
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