1221167Sgnn/*-
2221167Sgnn * Copyright(c) 2002-2011 Exar Corp.
3221167Sgnn * All rights reserved.
4221167Sgnn *
5221167Sgnn * Redistribution and use in source and binary forms, with or without
6221167Sgnn * modification are permitted provided the following conditions are met:
7221167Sgnn *
8221167Sgnn *    1. Redistributions of source code must retain the above copyright notice,
9221167Sgnn *       this list of conditions and the following disclaimer.
10221167Sgnn *
11221167Sgnn *    2. Redistributions in binary form must reproduce the above copyright
12221167Sgnn *       notice, this list of conditions and the following disclaimer in the
13221167Sgnn *       documentation and/or other materials provided with the distribution.
14221167Sgnn *
15221167Sgnn *    3. Neither the name of the Exar Corporation nor the names of its
16221167Sgnn *       contributors may be used to endorse or promote products derived from
17221167Sgnn *       this software without specific prior written permission.
18221167Sgnn *
19221167Sgnn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20221167Sgnn * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21221167Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22221167Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23221167Sgnn * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24221167Sgnn * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25221167Sgnn * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26221167Sgnn * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27221167Sgnn * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28221167Sgnn * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29221167Sgnn * POSSIBILITY OF SUCH DAMAGE.
30221167Sgnn */
31221167Sgnn/*$FreeBSD$*/
32221167Sgnn
33221167Sgnn#ifndef	VXGE_LIST_H
34221167Sgnn#define	VXGE_LIST_H
35221167Sgnn
36221167Sgnn__EXTERN_BEGIN_DECLS
37221167Sgnn
38221167Sgnn/*
39221167Sgnn * struct vxge_list_t - List item.
40221167Sgnn * @prev: Previous list item.
41221167Sgnn * @next: Next list item.
42221167Sgnn *
43221167Sgnn * Item of a bi-directional linked list.
44221167Sgnn */
45221167Sgnntypedef struct vxge_list_t {
46221167Sgnn	struct vxge_list_t		 *prev;
47221167Sgnn	struct vxge_list_t		 *next;
48221167Sgnn} vxge_list_t;
49221167Sgnn
50221167Sgnn/*
51221167Sgnn * vxge_list_init - Initialize linked list.
52221167Sgnn * @header: first element of the list (head)
53221167Sgnn *
54221167Sgnn * Initialize linked list.
55221167Sgnn * See also: vxge_list_t {}.
56221167Sgnn */
57221167Sgnnstatic inline void vxge_list_init(vxge_list_t *header)
58221167Sgnn{
59221167Sgnn	vxge_assert(header != NULL);
60221167Sgnn
61221167Sgnn	header->next = header;
62221167Sgnn	header->prev = header;
63221167Sgnn}
64221167Sgnn
65221167Sgnn/*
66221167Sgnn * vxge_list_is_empty - Is the list empty?
67221167Sgnn * @header: first element of the list (head)
68221167Sgnn *
69221167Sgnn * Determine whether the bi-directional list is empty. Return '1' in
70221167Sgnn * case of 'empty'.
71221167Sgnn * See also: vxge_list_t {}.
72221167Sgnn */
73221167Sgnnstatic inline int vxge_list_is_empty(vxge_list_t *header)
74221167Sgnn{
75221167Sgnn	vxge_assert(header != NULL);
76221167Sgnn
77221167Sgnn	return (header->next == header);
78221167Sgnn}
79221167Sgnn
80221167Sgnn/*
81221167Sgnn * vxge_list_first_get - Return the first item from the linked list.
82221167Sgnn * @header: first element of the list (head)
83221167Sgnn *
84221167Sgnn * Returns the next item from the header.
85221167Sgnn * Returns NULL if the next item is header itself
86221167Sgnn * See also: vxge_list_remove(), vxge_list_insert(), vxge_list_t {}.
87221167Sgnn */
88221167Sgnnstatic inline vxge_list_t *vxge_list_first_get(vxge_list_t *header)
89221167Sgnn{
90221167Sgnn	vxge_assert(header != NULL);
91221167Sgnn	vxge_assert(header->next != NULL);
92221167Sgnn	vxge_assert(header->prev != NULL);
93221167Sgnn
94221167Sgnn	if (header->next == header)
95221167Sgnn		return (NULL);
96221167Sgnn	else
97221167Sgnn		return (header->next);
98221167Sgnn}
99221167Sgnn
100221167Sgnn/*
101221167Sgnn * vxge_list_remove - Remove the specified item from the linked list.
102221167Sgnn * @item: element of the list
103221167Sgnn *
104221167Sgnn * Remove item from a list.
105221167Sgnn * See also: vxge_list_insert(), vxge_list_t {}.
106221167Sgnn */
107221167Sgnnstatic inline void vxge_list_remove(vxge_list_t *item)
108221167Sgnn{
109221167Sgnn	vxge_assert(item != NULL);
110221167Sgnn	vxge_assert(item->next != NULL);
111221167Sgnn	vxge_assert(item->prev != NULL);
112221167Sgnn
113221167Sgnn	item->next->prev = item->prev;
114221167Sgnn	item->prev->next = item->next;
115221167Sgnn#if defined(VXGE_DEBUG_ASSERT)
116221167Sgnn	item->next = item->prev = NULL;
117221167Sgnn#endif
118221167Sgnn}
119221167Sgnn
120221167Sgnn/*
121221167Sgnn * vxge_list_insert - Insert a new item after the specified item.
122221167Sgnn * @new_item: new element of the list
123221167Sgnn * @prev_item: element of the list after which the new element is
124221167Sgnn *		inserted
125221167Sgnn *
126221167Sgnn * Insert new item (new_item) after given item (prev_item).
127221167Sgnn * See also: vxge_list_remove(), vxge_list_insert_before(), vxge_list_t {}.
128221167Sgnn */
129221167Sgnnstatic inline void vxge_list_insert(vxge_list_t *new_item,
130221167Sgnn    vxge_list_t *prev_item)
131221167Sgnn{
132221167Sgnn	vxge_assert(new_item != NULL);
133221167Sgnn	vxge_assert(prev_item != NULL);
134221167Sgnn	vxge_assert(prev_item->next != NULL);
135221167Sgnn
136221167Sgnn	new_item->next = prev_item->next;
137221167Sgnn	new_item->prev = prev_item;
138221167Sgnn	prev_item->next->prev = new_item;
139221167Sgnn	prev_item->next = new_item;
140221167Sgnn}
141221167Sgnn
142221167Sgnn/*
143221167Sgnn * vxge_list_insert_before - Insert a new item before the specified item.
144221167Sgnn * @new_item: new element of the list
145221167Sgnn * @next_item: element of the list after which the new element is inserted
146221167Sgnn *
147221167Sgnn * Insert new item (new_item) before given item (next_item).
148221167Sgnn */
149221167Sgnnstatic inline void vxge_list_insert_before(vxge_list_t *new_item,
150221167Sgnn    vxge_list_t * next_item)
151221167Sgnn{
152221167Sgnn	vxge_assert(new_item != NULL);
153221167Sgnn	vxge_assert(next_item != NULL);
154221167Sgnn	vxge_assert(next_item->next != NULL);
155221167Sgnn
156221167Sgnn	new_item->next = next_item;
157221167Sgnn	new_item->prev = next_item->prev;
158221167Sgnn	next_item->prev->next = new_item;
159221167Sgnn	next_item->prev = new_item;
160221167Sgnn}
161221167Sgnn
162221167Sgnn#define	vxge_list_for_each(_p, _h) \
163221167Sgnn	for (_p = (_h)->next, vxge_os_prefetch(_p->next); _p != (_h); \
164221167Sgnn		_p = _p->next, vxge_os_prefetch(_p->next))
165221167Sgnn
166221167Sgnn#define	vxge_list_for_each_safe(_p, _n, _h) \
167221167Sgnn	for (_p = (_h)->next, _n = _p->next; _p != (_h); \
168221167Sgnn		_p = _n, _n = _p->next)
169221167Sgnn
170221167Sgnn#define	vxge_list_for_each_prev_safe(_p, _n, _h) \
171221167Sgnn	for (_p = (_h)->prev, _n = _p->prev; _p != (_h); \
172221167Sgnn		_p = _n, _n = _p->prev)
173221167Sgnn
174221167Sgnn#if defined(__GNUC__)
175221167Sgnn/*
176221167Sgnn * vxge_container_of - Given a member, return the containing structure.
177221167Sgnn * @ptr:	the pointer to the member.
178221167Sgnn * @type:	the type of the container struct this is embedded in.
179221167Sgnn * @member:	the name of the member within the struct.
180221167Sgnn *
181221167Sgnn * Cast a member of a structure out to the containing structure.
182221167Sgnn */
183221167Sgnn#define	vxge_container_of(ptr, type, member) (\
184221167Sgnn	{ __typeof(((type *)0)->member) *__mptr = (ptr);	\
185221167Sgnn	(type *)(void *)((char *)__mptr - ((ptr_t)&((type *)0)->member)); })
186221167Sgnn#else
187221167Sgnn/* type unsafe version */
188221167Sgnn#define	vxge_container_of(ptr, type, member) \
189221167Sgnn	((type *)(void *)((char *)(ptr) - ((ptr_t)&((type *)0)->member)))
190221167Sgnn#endif
191221167Sgnn
192221167Sgnn/*
193221167Sgnn * vxge_offsetof - Offset of the member in the containing structure.
194221167Sgnn * @t:	struct name.
195221167Sgnn * @m:	the name of the member within the struct.
196221167Sgnn *
197221167Sgnn * Return the offset of the member @m in the structure @t.
198221167Sgnn */
199221167Sgnn#define	vxge_offsetof(t, m)			((ptr_t)(&((t *)0)->m))
200221167Sgnn
201221167Sgnn__EXTERN_END_DECLS
202221167Sgnn
203221167Sgnn#endif	/* VXGE_LIST_H */
204