1 /*-
2  * Copyright (c) 2002-2007 Neterion, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: stable/9/sys/dev/nxge/include/xge-list.h 173139 2007-10-29 14:19:32Z rwatson $
27  */
28 
29 #ifndef XGE_LIST_H
30 #define XGE_LIST_H
31 
32 #include <dev/nxge/include/xge-debug.h>
33 
34 __EXTERN_BEGIN_DECLS
35 
36 /**
37  * struct xge_list_t - List item.
38  * @prev: Previous list item.
39  * @next: Next list item.
40  *
41  * Item of a bi-directional linked list.
42  */
43 typedef struct xge_list_t {
44 	struct xge_list_t* prev;
45 	struct xge_list_t* next;
46 } xge_list_t;
47 
48 /**
49  * xge_list_init - Initialize linked list.
50  * header: first element of the list (head)
51  *
52  * Initialize linked list.
53  * See also: xge_list_t{}.
54  */
xge_list_init(xge_list_t * header)55 static inline void xge_list_init (xge_list_t *header)
56 {
57 	header->next = header;
58 	header->prev = header;
59 }
60 
61 /**
62  * xge_list_is_empty - Is the list empty?
63  * header: first element of the list (head)
64  *
65  * Determine whether the bi-directional list is empty. Return '1' in
66  * case of 'empty'.
67  * See also: xge_list_t{}.
68  */
xge_list_is_empty(xge_list_t * header)69 static inline int xge_list_is_empty(xge_list_t *header)
70 {
71 	xge_assert(header != NULL);
72 
73 	return header->next == header;
74 }
75 
76 /**
77  * xge_list_first_get - Return the first item from the linked list.
78  * header: first element of the list (head)
79  *
80  * Returns the next item from the header.
81  * Returns NULL if the next item is header itself
82  * See also: xge_list_remove(), xge_list_insert(), xge_list_t{}.
83  */
xge_list_first_get(xge_list_t * header)84 static inline xge_list_t *xge_list_first_get(xge_list_t *header)
85 {
86 	xge_assert(header != NULL);
87 	xge_assert(header->next != NULL);
88 	xge_assert(header->prev != NULL);
89 
90 	if(header->next == header)
91 	    return NULL;
92 	else
93 	    return header->next;
94 }
95 
96 /**
97  * xge_list_remove - Remove the specified item from the linked list.
98  * item: element of the list
99  *
100  * Remove item from a list.
101  * See also: xge_list_insert(), xge_list_t{}.
102  */
xge_list_remove(xge_list_t * item)103 static inline void xge_list_remove(xge_list_t *item)
104 {
105 	xge_assert(item != NULL);
106 	xge_assert(item->next != NULL);
107 	xge_assert(item->prev != NULL);
108 
109 	item->next->prev = item->prev;
110 	item->prev->next = item->next;
111 #ifdef XGE_DEBUG_ASSERT
112 	item->next = item->prev = NULL;
113 #endif
114 }
115 
116 /**
117  * xge_list_insert - Insert a new item after the specified item.
118  * new_item: new element of the list
119  * prev_item: element of the list after which the new element is
120  *             inserted
121  *
122  * Insert new item (new_item) after given item (prev_item).
123  * See also: xge_list_remove(), xge_list_insert_before(), xge_list_t{}.
124  */
xge_list_insert(xge_list_t * new_item,xge_list_t * prev_item)125 static inline void xge_list_insert (xge_list_t *new_item,
126 	                xge_list_t *prev_item)
127 {
128 	xge_assert(new_item  != NULL);
129 	xge_assert(prev_item != NULL);
130 	xge_assert(prev_item->next != NULL);
131 
132 	new_item->next = prev_item->next;
133 	new_item->prev = prev_item;
134 	prev_item->next->prev = new_item;
135 	prev_item->next = new_item;
136 }
137 
138 /**
139  * xge_list_insert_before - Insert a new item before the specified item.
140  * new_item: new element of the list
141  * next_item: element of the list after which the new element is inserted
142  *
143  * Insert new item (new_item) before given item (next_item).
144  */
xge_list_insert_before(xge_list_t * new_item,xge_list_t * next_item)145 static inline void xge_list_insert_before (xge_list_t *new_item,
146 	                       xge_list_t *next_item)
147 {
148 	xge_assert(new_item  != NULL);
149 	xge_assert(next_item != NULL);
150 	xge_assert(next_item->next != NULL);
151 
152 	new_item->next = next_item;
153 	new_item->prev = next_item->prev;
154 	next_item->prev->next = new_item;
155 	next_item->prev = new_item;
156 }
157 
158 #define xge_list_for_each(_p, _h) \
159 	for (_p = (_h)->next, xge_os_prefetch(_p->next); _p != (_h); \
160 	    _p = _p->next, xge_os_prefetch(_p->next))
161 
162 #define xge_list_for_each_safe(_p, _n, _h) \
163 	    for (_p = (_h)->next, _n = _p->next; _p != (_h); \
164 	            _p = _n, _n = _p->next)
165 
166 #ifdef __GNUC__
167 /**
168  * xge_container_of - Given a member, return the containing structure.
169  * @ptr:    the pointer to the member.
170  * @type:   the type of the container struct this is embedded in.
171  * @member: the name of the member within the struct.
172  *
173  * Cast a member of a structure out to the containing structure.
174  */
175 #define xge_container_of(ptr, type, member) ({          \
176 	     __typeof( ((type *)0)->member ) *__mptr = (ptr);   \
177 	    (type *)(void *)( (char *)__mptr - ((size_t) &((type *)0)->member) );})
178 #else
179 /* type unsafe version */
180 #define xge_container_of(ptr, type, member) \
181 	            ((type*)(void*)((char*)(ptr) - ((size_t) &((type *)0)->member)))
182 #endif
183 
184 /**
185  * xge_offsetof - Offset of the member in the containing structure.
186  * @t:  struct name.
187  * @m:  the name of the member within the struct.
188  *
189  * Return the offset of the member @m in the structure @t.
190  */
191 #define xge_offsetof(t, m) ((size_t) (&((t *)0)->m))
192 
193 __EXTERN_END_DECLS
194 
195 #endif /* XGE_LIST_H */
196