xref: /illumos-gate/usr/src/uts/common/io/mega_sas/list.h (revision 6ec0e308)
1 /*
2  * list.h: header for mega_sas
3  *
4  * Solaris MegaRAID driver for SAS controllers
5  * Copyright (c) 2004-2008, LSI Logic Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  *    this list of conditions and the following disclaimer in the documentation
16  *    and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the author nor the names of its contributors may be
19  *    used to endorse or promote products derived from this software without
20  *    specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
33  * DAMAGE.
34  */
35 
36 /*
37  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
38  * Use is subject to license terms.
39  */
40 
41 #ifndef	_LIST_H_
42 #define	_LIST_H_
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /*
49  * Simple doubly linked list implementation.
50  *
51  * Some of the internal functions ("__xxx") are useful when
52  * manipulating whole lists rather than single entries, as
53  * sometimes we already know the next/prev entries and we can
54  * generate better code by using them directly rather than
55  * using the generic single-entry routines.
56  */
57 
58 struct mlist_head {
59 	struct mlist_head *next, *prev;
60 };
61 
62 typedef struct mlist_head mlist_t;
63 
64 #define	LIST_HEAD_INIT(name) { &(name), &(name) }
65 
66 #define	LIST_HEAD(name) \
67 	struct mlist_head name = LIST_HEAD_INIT(name)
68 
69 #define	INIT_LIST_HEAD(ptr) { \
70 	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
71 }
72 
73 
74 /*
75  * Insert a new entry between two known consecutive entries.
76  *
77  * This is only for internal list manipulation where we know
78  * the prev/next entries already!
79  */
__list_add(struct mlist_head * new,struct mlist_head * prev,struct mlist_head * next)80 static void __list_add(struct mlist_head *new,
81 	struct mlist_head *prev,
82 	struct mlist_head *next)
83 {
84 	next->prev = new;
85 	new->next = next;
86 	new->prev = prev;
87 	prev->next = new;
88 }
89 
90 
91 /*
92  * mlist_add - add a new entry
93  * @new: new entry to be added
94  * @head: list head to add it after
95  *
96  * Insert a new entry after the specified head.
97  * This is good for implementing stacks.
98  */
mlist_add(struct mlist_head * new,struct mlist_head * head)99 static void mlist_add(struct mlist_head *new, struct mlist_head *head)
100 {
101 	__list_add(new, head, head->next);
102 }
103 
104 
105 /*
106  * mlist_add_tail - add a new entry
107  * @new: new entry to be added
108  * @head: list head to add it before
109  *
110  * Insert a new entry before the specified head.
111  * This is useful for implementing queues.
112  */
mlist_add_tail(struct mlist_head * new,struct mlist_head * head)113 static void mlist_add_tail(struct mlist_head *new, struct mlist_head *head)
114 {
115 	__list_add(new, head->prev, head);
116 }
117 
118 
119 
120 /*
121  * Delete a list entry by making the prev/next entries
122  * point to each other.
123  *
124  * This is only for internal list manipulation where we know
125  * the prev/next entries already!
126  */
__list_del(struct mlist_head * prev,struct mlist_head * next)127 static void __list_del(struct mlist_head *prev,
128 			struct mlist_head *next)
129 {
130 	next->prev = prev;
131 	prev->next = next;
132 }
133 
134 
135 #if 0
136 /*
137  * mlist_del - deletes entry from list.
138  * @entry:	the element to delete from the list.
139  * Note:	list_empty on entry does not return true after this, the entry
140  * is in an undefined state.
141  */
142 
143 static void mlist_del(struct mlist_head *entry)
144 {
145 	__list_del(entry->prev, entry->next);
146 	entry->next = entry->prev = 0;
147 }
148 #endif
149 
150 /*
151  * mlist_del_init - deletes entry from list and reinitialize it.
152  * @entry: the element to delete from the list.
153  */
mlist_del_init(struct mlist_head * entry)154 static void mlist_del_init(struct mlist_head *entry)
155 {
156 	__list_del(entry->prev, entry->next);
157 	INIT_LIST_HEAD(entry);
158 }
159 
160 
161 /*
162  * mlist_empty - tests whether a list is empty
163  * @head: the list to test.
164  */
mlist_empty(struct mlist_head * head)165 static int mlist_empty(struct mlist_head *head)
166 {
167 	return (head->next == head);
168 }
169 
170 
171 /*
172  * mlist_splice - join two lists
173  * @list: the new list to add.
174  * @head: the place to add it in the first list.
175  */
mlist_splice(struct mlist_head * list,struct mlist_head * head)176 static void mlist_splice(struct mlist_head *list, struct mlist_head *head)
177 {
178 	struct mlist_head *first = list->next;
179 
180 	if (first != list) {
181 		struct mlist_head *last = list->prev;
182 		struct mlist_head *at = head->next;
183 
184 		first->prev = head;
185 		head->next = first;
186 
187 		last->next = at;
188 		at->prev = last;
189 	}
190 }
191 
192 
193 
194 /* TODO: set this */
195 #if 0
196 #pragma	inline(list_add, list_add_tail, __list_del, list_del,
197 		list_del_init, list_empty, list_splice)
198 #endif
199 
200 
201 /*
202  * mlist_entry - get the struct for this entry
203  * @ptr:	the &struct mlist_head pointer.
204  * @type:	the type of the struct this is embedded in.
205  * @member:	the name of the list_struct within the struct.
206  */
207 #define	mlist_entry(ptr, type, member) \
208 	((type *)((size_t)(ptr) - offsetof(type, member)))
209 
210 
211 /*
212  * mlist_for_each	-	iterate over a list
213  * @pos:	the &struct mlist_head to use as a loop counter.
214  * @head:	the head for your list.
215  */
216 #define	mlist_for_each(pos, head) \
217 	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
218 		pos = pos->next, prefetch(pos->next))
219 
220 
221 /*
222  * mlist_for_each_safe - iterate over a list safe against removal of list entry
223  * @pos:	the &struct mlist_head to use as a loop counter.
224  * @n:		another &struct mlist_head to use as temporary storage
225  * @head:	the head for your list.
226  */
227 #define	mlist_for_each_safe(pos, n, head) \
228 	for (pos = (head)->next, n = pos->next; pos != (head); \
229 		pos = n, n = pos->next)
230 
231 #ifdef __cplusplus
232 }
233 #endif
234 
235 #endif /* _LIST_H_ */
236