xref: /freebsd-src/sys/contrib/openzfs/lib/libspl/list.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy  * CDDL HEADER START
3*eda14cbcSMatt Macy  *
4*eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5*eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6*eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7*eda14cbcSMatt Macy  *
8*eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*eda14cbcSMatt Macy  * or http://www.opensolaris.org/os/licensing.
10*eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11*eda14cbcSMatt Macy  * and limitations under the License.
12*eda14cbcSMatt Macy  *
13*eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14*eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16*eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17*eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*eda14cbcSMatt Macy  *
19*eda14cbcSMatt Macy  * CDDL HEADER END
20*eda14cbcSMatt Macy  */
21*eda14cbcSMatt Macy /*
22*eda14cbcSMatt Macy  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*eda14cbcSMatt Macy  * Use is subject to license terms.
24*eda14cbcSMatt Macy  */
25*eda14cbcSMatt Macy 
26*eda14cbcSMatt Macy /*
27*eda14cbcSMatt Macy  * Generic doubly-linked list implementation
28*eda14cbcSMatt Macy  */
29*eda14cbcSMatt Macy 
30*eda14cbcSMatt Macy #include <sys/list.h>
31*eda14cbcSMatt Macy #include <sys/list_impl.h>
32*eda14cbcSMatt Macy #include <sys/types.h>
33*eda14cbcSMatt Macy #include <sys/sysmacros.h>
34*eda14cbcSMatt Macy #include <sys/debug.h>
35*eda14cbcSMatt Macy 
36*eda14cbcSMatt Macy #define	list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset))
37*eda14cbcSMatt Macy #define	list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
38*eda14cbcSMatt Macy #define	list_empty(a) ((a)->list_head.next == &(a)->list_head)
39*eda14cbcSMatt Macy 
40*eda14cbcSMatt Macy #define	list_insert_after_node(list, node, object) {	\
41*eda14cbcSMatt Macy 	list_node_t *lnew = list_d2l(list, object);	\
42*eda14cbcSMatt Macy 	lnew->prev = (node);			\
43*eda14cbcSMatt Macy 	lnew->next = (node)->next;		\
44*eda14cbcSMatt Macy 	(node)->next->prev = lnew;		\
45*eda14cbcSMatt Macy 	(node)->next = lnew;			\
46*eda14cbcSMatt Macy }
47*eda14cbcSMatt Macy 
48*eda14cbcSMatt Macy #define	list_insert_before_node(list, node, object) {	\
49*eda14cbcSMatt Macy 	list_node_t *lnew = list_d2l(list, object);	\
50*eda14cbcSMatt Macy 	lnew->next = (node);			\
51*eda14cbcSMatt Macy 	lnew->prev = (node)->prev;		\
52*eda14cbcSMatt Macy 	(node)->prev->next = lnew;		\
53*eda14cbcSMatt Macy 	(node)->prev = lnew;			\
54*eda14cbcSMatt Macy }
55*eda14cbcSMatt Macy 
56*eda14cbcSMatt Macy #define	list_remove_node(node)					\
57*eda14cbcSMatt Macy 	(node)->prev->next = (node)->next;	\
58*eda14cbcSMatt Macy 	(node)->next->prev = (node)->prev;	\
59*eda14cbcSMatt Macy 	(node)->next = (node)->prev = NULL
60*eda14cbcSMatt Macy 
61*eda14cbcSMatt Macy void
62*eda14cbcSMatt Macy list_create(list_t *list, size_t size, size_t offset)
63*eda14cbcSMatt Macy {
64*eda14cbcSMatt Macy 	ASSERT(list);
65*eda14cbcSMatt Macy 	ASSERT(size > 0);
66*eda14cbcSMatt Macy 	ASSERT(size >= offset + sizeof (list_node_t));
67*eda14cbcSMatt Macy 
68*eda14cbcSMatt Macy 	list->list_size = size;
69*eda14cbcSMatt Macy 	list->list_offset = offset;
70*eda14cbcSMatt Macy 	list->list_head.next = list->list_head.prev = &list->list_head;
71*eda14cbcSMatt Macy }
72*eda14cbcSMatt Macy 
73*eda14cbcSMatt Macy void
74*eda14cbcSMatt Macy list_destroy(list_t *list)
75*eda14cbcSMatt Macy {
76*eda14cbcSMatt Macy 	list_node_t *node = &list->list_head;
77*eda14cbcSMatt Macy 
78*eda14cbcSMatt Macy 	ASSERT(list);
79*eda14cbcSMatt Macy 	ASSERT(list->list_head.next == node);
80*eda14cbcSMatt Macy 	ASSERT(list->list_head.prev == node);
81*eda14cbcSMatt Macy 
82*eda14cbcSMatt Macy 	node->next = node->prev = NULL;
83*eda14cbcSMatt Macy }
84*eda14cbcSMatt Macy 
85*eda14cbcSMatt Macy void
86*eda14cbcSMatt Macy list_insert_after(list_t *list, void *object, void *nobject)
87*eda14cbcSMatt Macy {
88*eda14cbcSMatt Macy 	if (object == NULL) {
89*eda14cbcSMatt Macy 		list_insert_head(list, nobject);
90*eda14cbcSMatt Macy 	} else {
91*eda14cbcSMatt Macy 		list_node_t *lold = list_d2l(list, object);
92*eda14cbcSMatt Macy 		list_insert_after_node(list, lold, nobject);
93*eda14cbcSMatt Macy 	}
94*eda14cbcSMatt Macy }
95*eda14cbcSMatt Macy 
96*eda14cbcSMatt Macy void
97*eda14cbcSMatt Macy list_insert_before(list_t *list, void *object, void *nobject)
98*eda14cbcSMatt Macy {
99*eda14cbcSMatt Macy 	if (object == NULL) {
100*eda14cbcSMatt Macy 		list_insert_tail(list, nobject);
101*eda14cbcSMatt Macy 	} else {
102*eda14cbcSMatt Macy 		list_node_t *lold = list_d2l(list, object);
103*eda14cbcSMatt Macy 		list_insert_before_node(list, lold, nobject);
104*eda14cbcSMatt Macy 	}
105*eda14cbcSMatt Macy }
106*eda14cbcSMatt Macy 
107*eda14cbcSMatt Macy void
108*eda14cbcSMatt Macy list_insert_head(list_t *list, void *object)
109*eda14cbcSMatt Macy {
110*eda14cbcSMatt Macy 	list_node_t *lold = &list->list_head;
111*eda14cbcSMatt Macy 	list_insert_after_node(list, lold, object);
112*eda14cbcSMatt Macy }
113*eda14cbcSMatt Macy 
114*eda14cbcSMatt Macy void
115*eda14cbcSMatt Macy list_insert_tail(list_t *list, void *object)
116*eda14cbcSMatt Macy {
117*eda14cbcSMatt Macy 	list_node_t *lold = &list->list_head;
118*eda14cbcSMatt Macy 	list_insert_before_node(list, lold, object);
119*eda14cbcSMatt Macy }
120*eda14cbcSMatt Macy 
121*eda14cbcSMatt Macy void
122*eda14cbcSMatt Macy list_remove(list_t *list, void *object)
123*eda14cbcSMatt Macy {
124*eda14cbcSMatt Macy 	list_node_t *lold = list_d2l(list, object);
125*eda14cbcSMatt Macy 	ASSERT(!list_empty(list));
126*eda14cbcSMatt Macy 	ASSERT(lold->next != NULL);
127*eda14cbcSMatt Macy 	list_remove_node(lold);
128*eda14cbcSMatt Macy }
129*eda14cbcSMatt Macy 
130*eda14cbcSMatt Macy void *
131*eda14cbcSMatt Macy list_remove_head(list_t *list)
132*eda14cbcSMatt Macy {
133*eda14cbcSMatt Macy 	list_node_t *head = list->list_head.next;
134*eda14cbcSMatt Macy 	if (head == &list->list_head)
135*eda14cbcSMatt Macy 		return (NULL);
136*eda14cbcSMatt Macy 	list_remove_node(head);
137*eda14cbcSMatt Macy 	return (list_object(list, head));
138*eda14cbcSMatt Macy }
139*eda14cbcSMatt Macy 
140*eda14cbcSMatt Macy void *
141*eda14cbcSMatt Macy list_remove_tail(list_t *list)
142*eda14cbcSMatt Macy {
143*eda14cbcSMatt Macy 	list_node_t *tail = list->list_head.prev;
144*eda14cbcSMatt Macy 	if (tail == &list->list_head)
145*eda14cbcSMatt Macy 		return (NULL);
146*eda14cbcSMatt Macy 	list_remove_node(tail);
147*eda14cbcSMatt Macy 	return (list_object(list, tail));
148*eda14cbcSMatt Macy }
149*eda14cbcSMatt Macy 
150*eda14cbcSMatt Macy void *
151*eda14cbcSMatt Macy list_head(list_t *list)
152*eda14cbcSMatt Macy {
153*eda14cbcSMatt Macy 	if (list_empty(list))
154*eda14cbcSMatt Macy 		return (NULL);
155*eda14cbcSMatt Macy 	return (list_object(list, list->list_head.next));
156*eda14cbcSMatt Macy }
157*eda14cbcSMatt Macy 
158*eda14cbcSMatt Macy void *
159*eda14cbcSMatt Macy list_tail(list_t *list)
160*eda14cbcSMatt Macy {
161*eda14cbcSMatt Macy 	if (list_empty(list))
162*eda14cbcSMatt Macy 		return (NULL);
163*eda14cbcSMatt Macy 	return (list_object(list, list->list_head.prev));
164*eda14cbcSMatt Macy }
165*eda14cbcSMatt Macy 
166*eda14cbcSMatt Macy void *
167*eda14cbcSMatt Macy list_next(list_t *list, void *object)
168*eda14cbcSMatt Macy {
169*eda14cbcSMatt Macy 	list_node_t *node = list_d2l(list, object);
170*eda14cbcSMatt Macy 
171*eda14cbcSMatt Macy 	if (node->next != &list->list_head)
172*eda14cbcSMatt Macy 		return (list_object(list, node->next));
173*eda14cbcSMatt Macy 
174*eda14cbcSMatt Macy 	return (NULL);
175*eda14cbcSMatt Macy }
176*eda14cbcSMatt Macy 
177*eda14cbcSMatt Macy void *
178*eda14cbcSMatt Macy list_prev(list_t *list, void *object)
179*eda14cbcSMatt Macy {
180*eda14cbcSMatt Macy 	list_node_t *node = list_d2l(list, object);
181*eda14cbcSMatt Macy 
182*eda14cbcSMatt Macy 	if (node->prev != &list->list_head)
183*eda14cbcSMatt Macy 		return (list_object(list, node->prev));
184*eda14cbcSMatt Macy 
185*eda14cbcSMatt Macy 	return (NULL);
186*eda14cbcSMatt Macy }
187*eda14cbcSMatt Macy 
188*eda14cbcSMatt Macy /*
189*eda14cbcSMatt Macy  *  Insert src list after dst list. Empty src list thereafter.
190*eda14cbcSMatt Macy  */
191*eda14cbcSMatt Macy void
192*eda14cbcSMatt Macy list_move_tail(list_t *dst, list_t *src)
193*eda14cbcSMatt Macy {
194*eda14cbcSMatt Macy 	list_node_t *dstnode = &dst->list_head;
195*eda14cbcSMatt Macy 	list_node_t *srcnode = &src->list_head;
196*eda14cbcSMatt Macy 
197*eda14cbcSMatt Macy 	ASSERT(dst->list_size == src->list_size);
198*eda14cbcSMatt Macy 	ASSERT(dst->list_offset == src->list_offset);
199*eda14cbcSMatt Macy 
200*eda14cbcSMatt Macy 	if (list_empty(src))
201*eda14cbcSMatt Macy 		return;
202*eda14cbcSMatt Macy 
203*eda14cbcSMatt Macy 	dstnode->prev->next = srcnode->next;
204*eda14cbcSMatt Macy 	srcnode->next->prev = dstnode->prev;
205*eda14cbcSMatt Macy 	dstnode->prev = srcnode->prev;
206*eda14cbcSMatt Macy 	srcnode->prev->next = dstnode;
207*eda14cbcSMatt Macy 
208*eda14cbcSMatt Macy 	/* empty src list */
209*eda14cbcSMatt Macy 	srcnode->next = srcnode->prev = srcnode;
210*eda14cbcSMatt Macy }
211*eda14cbcSMatt Macy 
212*eda14cbcSMatt Macy void
213*eda14cbcSMatt Macy list_link_replace(list_node_t *lold, list_node_t *lnew)
214*eda14cbcSMatt Macy {
215*eda14cbcSMatt Macy 	ASSERT(list_link_active(lold));
216*eda14cbcSMatt Macy 	ASSERT(!list_link_active(lnew));
217*eda14cbcSMatt Macy 
218*eda14cbcSMatt Macy 	lnew->next = lold->next;
219*eda14cbcSMatt Macy 	lnew->prev = lold->prev;
220*eda14cbcSMatt Macy 	lold->prev->next = lnew;
221*eda14cbcSMatt Macy 	lold->next->prev = lnew;
222*eda14cbcSMatt Macy 	lold->next = lold->prev = NULL;
223*eda14cbcSMatt Macy }
224*eda14cbcSMatt Macy 
225*eda14cbcSMatt Macy void
226*eda14cbcSMatt Macy list_link_init(list_node_t *ln)
227*eda14cbcSMatt Macy {
228*eda14cbcSMatt Macy 	ln->next = NULL;
229*eda14cbcSMatt Macy 	ln->prev = NULL;
230*eda14cbcSMatt Macy }
231*eda14cbcSMatt Macy 
232*eda14cbcSMatt Macy int
233*eda14cbcSMatt Macy list_link_active(list_node_t *ln)
234*eda14cbcSMatt Macy {
235*eda14cbcSMatt Macy 	EQUIV(ln->next == NULL, ln->prev == NULL);
236*eda14cbcSMatt Macy 	return (ln->next != NULL);
237*eda14cbcSMatt Macy }
238*eda14cbcSMatt Macy 
239*eda14cbcSMatt Macy int
240*eda14cbcSMatt Macy list_is_empty(list_t *list)
241*eda14cbcSMatt Macy {
242*eda14cbcSMatt Macy 	return (list_empty(list));
243*eda14cbcSMatt Macy }
244