1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  * Copyright (c) 2002-2006 Neterion, Inc.
22  */
23 
24 #ifndef XGE_LIST_H
25 #define XGE_LIST_H
26 
27 #include "xge-debug.h"
28 
29 __EXTERN_BEGIN_DECLS
30 
31 /**
32  * struct xge_list_t - List item.
33  * @prev: Previous list item.
34  * @next: Next list item.
35  *
36  * Item of a bi-directional linked list.
37  */
38 typedef struct xge_list_t {
39 	struct xge_list_t* prev;
40 	struct xge_list_t* next;
41 } xge_list_t;
42 
43 /**
44  * xge_list_init - Initialize linked list.
45  * header: first element of the list (head)
46  *
47  * Initialize linked list.
48  * See also: xge_list_t{}.
49  */
xge_list_init(xge_list_t * header)50 static inline void xge_list_init (xge_list_t *header)
51 {
52 	header->next = header;
53 	header->prev = header;
54 }
55 
56 /**
57  * xge_list_is_empty - Is the list empty?
58  * header: first element of the list (head)
59  *
60  * Determine whether the bi-directional list is empty. Return '1' in
61  * case of 'empty'.
62  * See also: xge_list_t{}.
63  */
xge_list_is_empty(xge_list_t * header)64 static inline int xge_list_is_empty(xge_list_t *header)
65 {
66     xge_assert(header != NULL);
67 
68     return header->next == header;
69 }
70 
71 /**
72  * xge_list_first_get - Return the first item from the linked list.
73  * header: first element of the list (head)
74  *
75  * Returns the next item from the header.
76  * Returns NULL if the next item is header itself
77  * See also: xge_list_remove(), xge_list_insert(), xge_list_t{}.
78  */
xge_list_first_get(xge_list_t * header)79 static inline xge_list_t *xge_list_first_get(xge_list_t *header)
80 {
81 	xge_assert(header != NULL);
82 	xge_assert(header->next != NULL);
83 	xge_assert(header->prev != NULL);
84 
85 	if(header->next == header)
86 		return NULL;
87 	else
88 		return header->next;
89 }
90 
91 /**
92  * xge_list_remove - Remove the specified item from the linked list.
93  * item: element of the list
94  *
95  * Remove item from a list.
96  * See also: xge_list_insert(), xge_list_t{}.
97  */
xge_list_remove(xge_list_t * item)98 static inline void xge_list_remove(xge_list_t *item)
99 {
100 	xge_assert(item != NULL);
101 	xge_assert(item->next != NULL);
102 	xge_assert(item->prev != NULL);
103 
104 	item->next->prev = item->prev;
105 	item->prev->next = item->next;
106 #ifdef XGE_DEBUG_ASSERT
107 	item->next = item->prev = NULL;
108 #endif
109 }
110 
111 /**
112  * xge_list_insert - Insert a new item after the specified item.
113  * new_item: new element of the list
114  * prev_item: element of the list after which the new element is
115  *             inserted
116  *
117  * Insert new item (new_item) after given item (prev_item).
118  * See also: xge_list_remove(), xge_list_insert_before(), xge_list_t{}.
119  */
xge_list_insert(xge_list_t * new_item,xge_list_t * prev_item)120 static inline void xge_list_insert (xge_list_t *new_item,
121 				    xge_list_t *prev_item)
122 {
123 	xge_assert(new_item  != NULL);
124 	xge_assert(prev_item != NULL);
125 	xge_assert(prev_item->next != NULL);
126 
127 	new_item->next = prev_item->next;
128 	new_item->prev = prev_item;
129 	prev_item->next->prev = new_item;
130 	prev_item->next = new_item;
131 }
132 
133 /**
134  * xge_list_insert_before - Insert a new item before the specified item.
135  * new_item: new element of the list
136  * next_item: element of the list after which the new element is inserted
137  *
138  * Insert new item (new_item) before given item (next_item).
139  */
xge_list_insert_before(xge_list_t * new_item,xge_list_t * next_item)140 static inline void xge_list_insert_before (xge_list_t *new_item,
141 				    	   xge_list_t *next_item)
142 {
143 	xge_assert(new_item  != NULL);
144 	xge_assert(next_item != NULL);
145 	xge_assert(next_item->next != NULL);
146 
147 	new_item->next = next_item;
148 	new_item->prev = next_item->prev;
149 	next_item->prev->next = new_item;
150 	next_item->prev = new_item;
151 }
152 
153 #define xge_list_for_each(_p, _h) \
154 	for (_p = (_h)->next, xge_os_prefetch(_p->next); _p != (_h); \
155 		_p = _p->next, xge_os_prefetch(_p->next))
156 
157 #define xge_list_for_each_safe(_p, _n, _h) \
158         for (_p = (_h)->next, _n = _p->next; _p != (_h); \
159                 _p = _n, _n = _p->next)
160 
161 #ifdef __GNUC__
162 /**
163  * xge_container_of - Given a member, return the containing structure.
164  * @ptr:	the pointer to the member.
165  * @type:	the type of the container struct this is embedded in.
166  * @member:	the name of the member within the struct.
167  *
168  * Cast a member of a structure out to the containing structure.
169  */
170 #define xge_container_of(ptr, type, member) ({			\
171          __typeof( ((type *)0)->member ) *__mptr = (ptr);	\
172         (type *)(void *)( (char *)__mptr - ((size_t) &((type *)0)->member) );})
173 #else
174 /* type unsafe version */
175 #define xge_container_of(ptr, type, member) \
176                 ((type*)(void*)((char*)(ptr) - ((size_t) &((type *)0)->member)))
177 #endif
178 
179 /**
180  * xge_offsetof - Offset of the member in the containing structure.
181  * @t:	struct name.
182  * @m:	the name of the member within the struct.
183  *
184  * Return the offset of the member @m in the structure @t.
185  */
186 #define xge_offsetof(t, m) ((size_t) (&((t *)0)->m))
187 
188 __EXTERN_END_DECLS
189 
190 #endif /* XGE_LIST_H */
191