xref: /freebsd/contrib/ofed/opensm/complib/cl_list.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2005,2009 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5*d6b92ffaSHans Petter Selasky  *
6*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11*d6b92ffaSHans Petter Selasky  *
12*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14*d6b92ffaSHans Petter Selasky  *     conditions are met:
15*d6b92ffaSHans Petter Selasky  *
16*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18*d6b92ffaSHans Petter Selasky  *        disclaimer.
19*d6b92ffaSHans Petter Selasky  *
20*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24*d6b92ffaSHans Petter Selasky  *
25*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*d6b92ffaSHans Petter Selasky  * SOFTWARE.
33*d6b92ffaSHans Petter Selasky  *
34*d6b92ffaSHans Petter Selasky  */
35*d6b92ffaSHans Petter Selasky 
36*d6b92ffaSHans Petter Selasky /*
37*d6b92ffaSHans Petter Selasky  * Abstract:
38*d6b92ffaSHans Petter Selasky  *	Implementation of quick list, and list.
39*d6b92ffaSHans Petter Selasky  *
40*d6b92ffaSHans Petter Selasky  */
41*d6b92ffaSHans Petter Selasky 
42*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
43*d6b92ffaSHans Petter Selasky #  include <config.h>
44*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
45*d6b92ffaSHans Petter Selasky 
46*d6b92ffaSHans Petter Selasky #include <complib/cl_qlist.h>
47*d6b92ffaSHans Petter Selasky #include <complib/cl_list.h>
48*d6b92ffaSHans Petter Selasky 
49*d6b92ffaSHans Petter Selasky #define FREE_ITEM_GROW_SIZE		10
50*d6b92ffaSHans Petter Selasky 
51*d6b92ffaSHans Petter Selasky /******************************************************************************
52*d6b92ffaSHans Petter Selasky  IMPLEMENTATION OF QUICK LIST
53*d6b92ffaSHans Petter Selasky ******************************************************************************/
cl_qlist_insert_array_head(IN cl_qlist_t * const p_list,IN cl_list_item_t * const p_array,IN uint32_t item_count,IN const uint32_t item_size)54*d6b92ffaSHans Petter Selasky void cl_qlist_insert_array_head(IN cl_qlist_t * const p_list,
55*d6b92ffaSHans Petter Selasky 				IN cl_list_item_t * const p_array,
56*d6b92ffaSHans Petter Selasky 				IN uint32_t item_count,
57*d6b92ffaSHans Petter Selasky 				IN const uint32_t item_size)
58*d6b92ffaSHans Petter Selasky {
59*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_item;
60*d6b92ffaSHans Petter Selasky 
61*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
62*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list->state == CL_INITIALIZED);
63*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_array);
64*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_size >= sizeof(cl_list_item_t));
65*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_count);
66*d6b92ffaSHans Petter Selasky 
67*d6b92ffaSHans Petter Selasky 	/*
68*d6b92ffaSHans Petter Selasky 	 * To add items from the array to the list in the same order as
69*d6b92ffaSHans Petter Selasky 	 * the elements appear in the array, we add them starting with
70*d6b92ffaSHans Petter Selasky 	 * the last one first.  Locate the last item.
71*d6b92ffaSHans Petter Selasky 	 */
72*d6b92ffaSHans Petter Selasky 	p_item = (cl_list_item_t *) ((uint8_t *) p_array +
73*d6b92ffaSHans Petter Selasky 				     (item_size * (item_count - 1)));
74*d6b92ffaSHans Petter Selasky 
75*d6b92ffaSHans Petter Selasky 	/* Continue to add all items to the list. */
76*d6b92ffaSHans Petter Selasky 	while (item_count--) {
77*d6b92ffaSHans Petter Selasky 		cl_qlist_insert_head(p_list, p_item);
78*d6b92ffaSHans Petter Selasky 
79*d6b92ffaSHans Petter Selasky 		/* Get the next object to add to the list. */
80*d6b92ffaSHans Petter Selasky 		p_item = (cl_list_item_t *) ((uint8_t *) p_item - item_size);
81*d6b92ffaSHans Petter Selasky 	}
82*d6b92ffaSHans Petter Selasky }
83*d6b92ffaSHans Petter Selasky 
cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list,IN cl_list_item_t * const p_array,IN uint32_t item_count,IN const uint32_t item_size)84*d6b92ffaSHans Petter Selasky void cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list,
85*d6b92ffaSHans Petter Selasky 				IN cl_list_item_t * const p_array,
86*d6b92ffaSHans Petter Selasky 				IN uint32_t item_count,
87*d6b92ffaSHans Petter Selasky 				IN const uint32_t item_size)
88*d6b92ffaSHans Petter Selasky {
89*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_item;
90*d6b92ffaSHans Petter Selasky 
91*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
92*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list->state == CL_INITIALIZED);
93*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_array);
94*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_size >= sizeof(cl_list_item_t));
95*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_count);
96*d6b92ffaSHans Petter Selasky 
97*d6b92ffaSHans Petter Selasky 	/* Set the first item to add to the list. */
98*d6b92ffaSHans Petter Selasky 	p_item = p_array;
99*d6b92ffaSHans Petter Selasky 
100*d6b92ffaSHans Petter Selasky 	/* Continue to add all items to the list. */
101*d6b92ffaSHans Petter Selasky 	while (item_count--) {
102*d6b92ffaSHans Petter Selasky 		cl_qlist_insert_tail(p_list, p_item);
103*d6b92ffaSHans Petter Selasky 
104*d6b92ffaSHans Petter Selasky 		/* Get the next object to add to the list. */
105*d6b92ffaSHans Petter Selasky 		p_item = (cl_list_item_t *) ((uint8_t *) p_item + item_size);
106*d6b92ffaSHans Petter Selasky 	}
107*d6b92ffaSHans Petter Selasky }
108*d6b92ffaSHans Petter Selasky 
cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list,IN cl_qlist_t * const p_src_list)109*d6b92ffaSHans Petter Selasky void cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list,
110*d6b92ffaSHans Petter Selasky 			       IN cl_qlist_t * const p_src_list)
111*d6b92ffaSHans Petter Selasky {
112*d6b92ffaSHans Petter Selasky #if defined( _DEBUG_ )
113*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_item;
114*d6b92ffaSHans Petter Selasky #endif
115*d6b92ffaSHans Petter Selasky 
116*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest_list);
117*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_src_list);
118*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
119*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
120*d6b92ffaSHans Petter Selasky 
121*d6b92ffaSHans Petter Selasky 	/*
122*d6b92ffaSHans Petter Selasky 	 * Is the src list empty?
123*d6b92ffaSHans Petter Selasky 	 * We must have this check here for code below to work.
124*d6b92ffaSHans Petter Selasky 	 */
125*d6b92ffaSHans Petter Selasky 	if (cl_is_qlist_empty(p_src_list))
126*d6b92ffaSHans Petter Selasky 		return;
127*d6b92ffaSHans Petter Selasky 
128*d6b92ffaSHans Petter Selasky #if defined( _DEBUG_ )
129*d6b92ffaSHans Petter Selasky 	/* Check that all items in the source list belong there. */
130*d6b92ffaSHans Petter Selasky 	p_item = cl_qlist_head(p_src_list);
131*d6b92ffaSHans Petter Selasky 	while (p_item != cl_qlist_end(p_src_list)) {
132*d6b92ffaSHans Petter Selasky 		/* All list items in the source list must point to it. */
133*d6b92ffaSHans Petter Selasky 		CL_ASSERT(p_item->p_list == p_src_list);
134*d6b92ffaSHans Petter Selasky 		/* Point them all to the destination list. */
135*d6b92ffaSHans Petter Selasky 		p_item->p_list = p_dest_list;
136*d6b92ffaSHans Petter Selasky 		p_item = cl_qlist_next(p_item);
137*d6b92ffaSHans Petter Selasky 	}
138*d6b92ffaSHans Petter Selasky #endif
139*d6b92ffaSHans Petter Selasky 
140*d6b92ffaSHans Petter Selasky 	/* Chain the destination list to the tail of the source list. */
141*d6b92ffaSHans Petter Selasky 	cl_qlist_tail(p_src_list)->p_next = cl_qlist_head(p_dest_list);
142*d6b92ffaSHans Petter Selasky 	cl_qlist_head(p_dest_list)->p_prev = cl_qlist_tail(p_src_list);
143*d6b92ffaSHans Petter Selasky 
144*d6b92ffaSHans Petter Selasky 	/*
145*d6b92ffaSHans Petter Selasky 	 * Update the head of the destination list to the head of
146*d6b92ffaSHans Petter Selasky 	 * the source list.
147*d6b92ffaSHans Petter Selasky 	 */
148*d6b92ffaSHans Petter Selasky 	p_dest_list->end.p_next = cl_qlist_head(p_src_list);
149*d6b92ffaSHans Petter Selasky 	cl_qlist_head(p_src_list)->p_prev = &p_dest_list->end;
150*d6b92ffaSHans Petter Selasky 
151*d6b92ffaSHans Petter Selasky 	/*
152*d6b92ffaSHans Petter Selasky 	 * Update the count of the destination to reflect the source items having
153*d6b92ffaSHans Petter Selasky 	 * been added.
154*d6b92ffaSHans Petter Selasky 	 */
155*d6b92ffaSHans Petter Selasky 	p_dest_list->count += p_src_list->count;
156*d6b92ffaSHans Petter Selasky 
157*d6b92ffaSHans Petter Selasky 	/* Update source list to reflect being empty. */
158*d6b92ffaSHans Petter Selasky 	__cl_qlist_reset(p_src_list);
159*d6b92ffaSHans Petter Selasky }
160*d6b92ffaSHans Petter Selasky 
cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list,IN cl_qlist_t * const p_src_list)161*d6b92ffaSHans Petter Selasky void cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list,
162*d6b92ffaSHans Petter Selasky 			       IN cl_qlist_t * const p_src_list)
163*d6b92ffaSHans Petter Selasky {
164*d6b92ffaSHans Petter Selasky #if defined( _DEBUG_ )
165*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_item;
166*d6b92ffaSHans Petter Selasky #endif
167*d6b92ffaSHans Petter Selasky 
168*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest_list);
169*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_src_list);
170*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
171*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
172*d6b92ffaSHans Petter Selasky 
173*d6b92ffaSHans Petter Selasky 	/*
174*d6b92ffaSHans Petter Selasky 	 * Is the src list empty?
175*d6b92ffaSHans Petter Selasky 	 * We must have this check here for code below to work.
176*d6b92ffaSHans Petter Selasky 	 */
177*d6b92ffaSHans Petter Selasky 	if (cl_is_qlist_empty(p_src_list))
178*d6b92ffaSHans Petter Selasky 		return;
179*d6b92ffaSHans Petter Selasky 
180*d6b92ffaSHans Petter Selasky #if defined( _DEBUG_ )
181*d6b92ffaSHans Petter Selasky 	/* Check that all items in the source list belong there. */
182*d6b92ffaSHans Petter Selasky 	p_item = cl_qlist_head(p_src_list);
183*d6b92ffaSHans Petter Selasky 	while (p_item != cl_qlist_end(p_src_list)) {
184*d6b92ffaSHans Petter Selasky 		/* All list items in the source list must point to it. */
185*d6b92ffaSHans Petter Selasky 		CL_ASSERT(p_item->p_list == p_src_list);
186*d6b92ffaSHans Petter Selasky 		/* Point them all to the destination list. */
187*d6b92ffaSHans Petter Selasky 		p_item->p_list = p_dest_list;
188*d6b92ffaSHans Petter Selasky 		p_item = cl_qlist_next(p_item);
189*d6b92ffaSHans Petter Selasky 	}
190*d6b92ffaSHans Petter Selasky #endif
191*d6b92ffaSHans Petter Selasky 
192*d6b92ffaSHans Petter Selasky 	/* Chain the source list to the tail of the destination list. */
193*d6b92ffaSHans Petter Selasky 	cl_qlist_tail(p_dest_list)->p_next = cl_qlist_head(p_src_list);
194*d6b92ffaSHans Petter Selasky 	cl_qlist_head(p_src_list)->p_prev = cl_qlist_tail(p_dest_list);
195*d6b92ffaSHans Petter Selasky 
196*d6b92ffaSHans Petter Selasky 	/*
197*d6b92ffaSHans Petter Selasky 	 * Update the tail of the destination list to the tail of
198*d6b92ffaSHans Petter Selasky 	 * the source list.
199*d6b92ffaSHans Petter Selasky 	 */
200*d6b92ffaSHans Petter Selasky 	p_dest_list->end.p_prev = cl_qlist_tail(p_src_list);
201*d6b92ffaSHans Petter Selasky 	cl_qlist_tail(p_src_list)->p_next = &p_dest_list->end;
202*d6b92ffaSHans Petter Selasky 
203*d6b92ffaSHans Petter Selasky 	/*
204*d6b92ffaSHans Petter Selasky 	 * Update the count of the destination to reflect the source items having
205*d6b92ffaSHans Petter Selasky 	 * been added.
206*d6b92ffaSHans Petter Selasky 	 */
207*d6b92ffaSHans Petter Selasky 	p_dest_list->count += p_src_list->count;
208*d6b92ffaSHans Petter Selasky 
209*d6b92ffaSHans Petter Selasky 	/* Update source list to reflect being empty. */
210*d6b92ffaSHans Petter Selasky 	__cl_qlist_reset(p_src_list);
211*d6b92ffaSHans Petter Selasky }
212*d6b92ffaSHans Petter Selasky 
cl_is_item_in_qlist(IN const cl_qlist_t * const p_list,IN const cl_list_item_t * const p_list_item)213*d6b92ffaSHans Petter Selasky boolean_t cl_is_item_in_qlist(IN const cl_qlist_t * const p_list,
214*d6b92ffaSHans Petter Selasky 			      IN const cl_list_item_t * const p_list_item)
215*d6b92ffaSHans Petter Selasky {
216*d6b92ffaSHans Petter Selasky 	const cl_list_item_t *p_temp;
217*d6b92ffaSHans Petter Selasky 
218*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
219*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item);
220*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list->state == CL_INITIALIZED);
221*d6b92ffaSHans Petter Selasky 
222*d6b92ffaSHans Petter Selasky 	/* Traverse looking for a match */
223*d6b92ffaSHans Petter Selasky 	p_temp = cl_qlist_head(p_list);
224*d6b92ffaSHans Petter Selasky 	while (p_temp != cl_qlist_end(p_list)) {
225*d6b92ffaSHans Petter Selasky 		if (p_temp == p_list_item) {
226*d6b92ffaSHans Petter Selasky 			CL_ASSERT(p_list_item->p_list == p_list);
227*d6b92ffaSHans Petter Selasky 			return (TRUE);
228*d6b92ffaSHans Petter Selasky 		}
229*d6b92ffaSHans Petter Selasky 
230*d6b92ffaSHans Petter Selasky 		p_temp = cl_qlist_next(p_temp);
231*d6b92ffaSHans Petter Selasky 	}
232*d6b92ffaSHans Petter Selasky 
233*d6b92ffaSHans Petter Selasky 	return (FALSE);
234*d6b92ffaSHans Petter Selasky }
235*d6b92ffaSHans Petter Selasky 
cl_qlist_find_next(IN const cl_qlist_t * const p_list,IN const cl_list_item_t * const p_list_item,IN cl_pfn_qlist_find_t pfn_func,IN const void * const context)236*d6b92ffaSHans Petter Selasky cl_list_item_t *cl_qlist_find_next(IN const cl_qlist_t * const p_list,
237*d6b92ffaSHans Petter Selasky 				   IN const cl_list_item_t * const p_list_item,
238*d6b92ffaSHans Petter Selasky 				   IN cl_pfn_qlist_find_t pfn_func,
239*d6b92ffaSHans Petter Selasky 				   IN const void *const context)
240*d6b92ffaSHans Petter Selasky {
241*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_found_item;
242*d6b92ffaSHans Petter Selasky 
243*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
244*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list->state == CL_INITIALIZED);
245*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item);
246*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item->p_list == p_list);
247*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
248*d6b92ffaSHans Petter Selasky 
249*d6b92ffaSHans Petter Selasky 	p_found_item = cl_qlist_next(p_list_item);
250*d6b92ffaSHans Petter Selasky 
251*d6b92ffaSHans Petter Selasky 	/* The user provided a compare function */
252*d6b92ffaSHans Petter Selasky 	while (p_found_item != cl_qlist_end(p_list)) {
253*d6b92ffaSHans Petter Selasky 		CL_ASSERT(p_found_item->p_list == p_list);
254*d6b92ffaSHans Petter Selasky 
255*d6b92ffaSHans Petter Selasky 		if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS)
256*d6b92ffaSHans Petter Selasky 			break;
257*d6b92ffaSHans Petter Selasky 
258*d6b92ffaSHans Petter Selasky 		p_found_item = cl_qlist_next(p_found_item);
259*d6b92ffaSHans Petter Selasky 	}
260*d6b92ffaSHans Petter Selasky 
261*d6b92ffaSHans Petter Selasky 	/* No match */
262*d6b92ffaSHans Petter Selasky 	return (p_found_item);
263*d6b92ffaSHans Petter Selasky }
264*d6b92ffaSHans Petter Selasky 
cl_qlist_find_prev(IN const cl_qlist_t * const p_list,IN const cl_list_item_t * const p_list_item,IN cl_pfn_qlist_find_t pfn_func,IN const void * const context)265*d6b92ffaSHans Petter Selasky cl_list_item_t *cl_qlist_find_prev(IN const cl_qlist_t * const p_list,
266*d6b92ffaSHans Petter Selasky 				   IN const cl_list_item_t * const p_list_item,
267*d6b92ffaSHans Petter Selasky 				   IN cl_pfn_qlist_find_t pfn_func,
268*d6b92ffaSHans Petter Selasky 				   IN const void *const context)
269*d6b92ffaSHans Petter Selasky {
270*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_found_item;
271*d6b92ffaSHans Petter Selasky 
272*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
273*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list->state == CL_INITIALIZED);
274*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item);
275*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item->p_list == p_list);
276*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
277*d6b92ffaSHans Petter Selasky 
278*d6b92ffaSHans Petter Selasky 	p_found_item = cl_qlist_prev(p_list_item);
279*d6b92ffaSHans Petter Selasky 
280*d6b92ffaSHans Petter Selasky 	/* The user provided a compare function */
281*d6b92ffaSHans Petter Selasky 	while (p_found_item != cl_qlist_end(p_list)) {
282*d6b92ffaSHans Petter Selasky 		CL_ASSERT(p_found_item->p_list == p_list);
283*d6b92ffaSHans Petter Selasky 
284*d6b92ffaSHans Petter Selasky 		if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS)
285*d6b92ffaSHans Petter Selasky 			break;
286*d6b92ffaSHans Petter Selasky 
287*d6b92ffaSHans Petter Selasky 		p_found_item = cl_qlist_prev(p_found_item);
288*d6b92ffaSHans Petter Selasky 	}
289*d6b92ffaSHans Petter Selasky 
290*d6b92ffaSHans Petter Selasky 	/* No match */
291*d6b92ffaSHans Petter Selasky 	return (p_found_item);
292*d6b92ffaSHans Petter Selasky }
293*d6b92ffaSHans Petter Selasky 
cl_qlist_apply_func(IN const cl_qlist_t * const p_list,IN cl_pfn_qlist_apply_t pfn_func,IN const void * const context)294*d6b92ffaSHans Petter Selasky void cl_qlist_apply_func(IN const cl_qlist_t * const p_list,
295*d6b92ffaSHans Petter Selasky 			 IN cl_pfn_qlist_apply_t pfn_func,
296*d6b92ffaSHans Petter Selasky 			 IN const void *const context)
297*d6b92ffaSHans Petter Selasky {
298*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_list_item;
299*d6b92ffaSHans Petter Selasky 
300*d6b92ffaSHans Petter Selasky 	/* Note that context can have any arbitrary value. */
301*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
302*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list->state == CL_INITIALIZED);
303*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
304*d6b92ffaSHans Petter Selasky 
305*d6b92ffaSHans Petter Selasky 	p_list_item = cl_qlist_head(p_list);
306*d6b92ffaSHans Petter Selasky 	while (p_list_item != cl_qlist_end(p_list)) {
307*d6b92ffaSHans Petter Selasky 		pfn_func(p_list_item, (void *)context);
308*d6b92ffaSHans Petter Selasky 		p_list_item = cl_qlist_next(p_list_item);
309*d6b92ffaSHans Petter Selasky 	}
310*d6b92ffaSHans Petter Selasky }
311*d6b92ffaSHans Petter Selasky 
cl_qlist_move_items(IN cl_qlist_t * const p_src_list,IN cl_qlist_t * const p_dest_list,IN cl_pfn_qlist_find_t pfn_func,IN const void * const context)312*d6b92ffaSHans Petter Selasky void cl_qlist_move_items(IN cl_qlist_t * const p_src_list,
313*d6b92ffaSHans Petter Selasky 			 IN cl_qlist_t * const p_dest_list,
314*d6b92ffaSHans Petter Selasky 			 IN cl_pfn_qlist_find_t pfn_func,
315*d6b92ffaSHans Petter Selasky 			 IN const void *const context)
316*d6b92ffaSHans Petter Selasky {
317*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_current_item, *p_next;
318*d6b92ffaSHans Petter Selasky 
319*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_src_list);
320*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest_list);
321*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
322*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
323*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
324*d6b92ffaSHans Petter Selasky 
325*d6b92ffaSHans Petter Selasky 	p_current_item = cl_qlist_head(p_src_list);
326*d6b92ffaSHans Petter Selasky 
327*d6b92ffaSHans Petter Selasky 	while (p_current_item != cl_qlist_end(p_src_list)) {
328*d6b92ffaSHans Petter Selasky 		/* Before we do anything, get a pointer to the next item. */
329*d6b92ffaSHans Petter Selasky 		p_next = cl_qlist_next(p_current_item);
330*d6b92ffaSHans Petter Selasky 
331*d6b92ffaSHans Petter Selasky 		if (pfn_func(p_current_item, (void *)context) == CL_SUCCESS) {
332*d6b92ffaSHans Petter Selasky 			/* Move the item from one list to the other. */
333*d6b92ffaSHans Petter Selasky 			cl_qlist_remove_item(p_src_list, p_current_item);
334*d6b92ffaSHans Petter Selasky 			cl_qlist_insert_tail(p_dest_list, p_current_item);
335*d6b92ffaSHans Petter Selasky 		}
336*d6b92ffaSHans Petter Selasky 		p_current_item = p_next;
337*d6b92ffaSHans Petter Selasky 	}
338*d6b92ffaSHans Petter Selasky }
339*d6b92ffaSHans Petter Selasky 
340*d6b92ffaSHans Petter Selasky /******************************************************************************
341*d6b92ffaSHans Petter Selasky  IMPLEMENTATION OF LIST
342*d6b92ffaSHans Petter Selasky ******************************************************************************/
cl_list_construct(IN cl_list_t * const p_list)343*d6b92ffaSHans Petter Selasky void cl_list_construct(IN cl_list_t * const p_list)
344*d6b92ffaSHans Petter Selasky {
345*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
346*d6b92ffaSHans Petter Selasky 
347*d6b92ffaSHans Petter Selasky 	cl_qpool_construct(&p_list->list_item_pool);
348*d6b92ffaSHans Petter Selasky }
349*d6b92ffaSHans Petter Selasky 
cl_list_init(IN cl_list_t * const p_list,IN const size_t min_items)350*d6b92ffaSHans Petter Selasky cl_status_t cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items)
351*d6b92ffaSHans Petter Selasky {
352*d6b92ffaSHans Petter Selasky 	uint32_t grow_size;
353*d6b92ffaSHans Petter Selasky 
354*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
355*d6b92ffaSHans Petter Selasky 	cl_qlist_init(&p_list->list);
356*d6b92ffaSHans Petter Selasky 
357*d6b92ffaSHans Petter Selasky 	/*
358*d6b92ffaSHans Petter Selasky 	 * We will grow by min_items/8 items at a time, with a minimum of
359*d6b92ffaSHans Petter Selasky 	 * FREE_ITEM_GROW_SIZE.
360*d6b92ffaSHans Petter Selasky 	 */
361*d6b92ffaSHans Petter Selasky 	grow_size = (uint32_t) min_items >> 3;
362*d6b92ffaSHans Petter Selasky 	if (grow_size < FREE_ITEM_GROW_SIZE)
363*d6b92ffaSHans Petter Selasky 		grow_size = FREE_ITEM_GROW_SIZE;
364*d6b92ffaSHans Petter Selasky 
365*d6b92ffaSHans Petter Selasky 	/* Initialize the pool of list items. */
366*d6b92ffaSHans Petter Selasky 	return (cl_qpool_init(&p_list->list_item_pool, min_items, 0, grow_size,
367*d6b92ffaSHans Petter Selasky 			      sizeof(cl_pool_obj_t), NULL, NULL, NULL));
368*d6b92ffaSHans Petter Selasky }
369*d6b92ffaSHans Petter Selasky 
cl_list_destroy(IN cl_list_t * const p_list)370*d6b92ffaSHans Petter Selasky void cl_list_destroy(IN cl_list_t * const p_list)
371*d6b92ffaSHans Petter Selasky {
372*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
373*d6b92ffaSHans Petter Selasky 
374*d6b92ffaSHans Petter Selasky 	cl_qpool_destroy(&p_list->list_item_pool);
375*d6b92ffaSHans Petter Selasky }
376*d6b92ffaSHans Petter Selasky 
cl_list_find_cb(IN const cl_list_item_t * const p_list_item,IN void * const context)377*d6b92ffaSHans Petter Selasky static cl_status_t cl_list_find_cb(IN const cl_list_item_t * const p_list_item,
378*d6b92ffaSHans Petter Selasky 				   IN void *const context)
379*d6b92ffaSHans Petter Selasky {
380*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list_item);
381*d6b92ffaSHans Petter Selasky 
382*d6b92ffaSHans Petter Selasky 	if (cl_list_obj(p_list_item) == context)
383*d6b92ffaSHans Petter Selasky 		return (CL_SUCCESS);
384*d6b92ffaSHans Petter Selasky 
385*d6b92ffaSHans Petter Selasky 	return (CL_NOT_FOUND);
386*d6b92ffaSHans Petter Selasky }
387*d6b92ffaSHans Petter Selasky 
cl_list_remove_object(IN cl_list_t * const p_list,IN const void * const p_object)388*d6b92ffaSHans Petter Selasky cl_status_t cl_list_remove_object(IN cl_list_t * const p_list,
389*d6b92ffaSHans Petter Selasky 				  IN const void *const p_object)
390*d6b92ffaSHans Petter Selasky {
391*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_list_item;
392*d6b92ffaSHans Petter Selasky 
393*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
394*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
395*d6b92ffaSHans Petter Selasky 
396*d6b92ffaSHans Petter Selasky 	/* find the item in question */
397*d6b92ffaSHans Petter Selasky 	p_list_item =
398*d6b92ffaSHans Petter Selasky 	    cl_qlist_find_from_head(&p_list->list, cl_list_find_cb, p_object);
399*d6b92ffaSHans Petter Selasky 	if (p_list_item != cl_qlist_end(&p_list->list)) {
400*d6b92ffaSHans Petter Selasky 		/* remove this item */
401*d6b92ffaSHans Petter Selasky 		cl_qlist_remove_item(&p_list->list, p_list_item);
402*d6b92ffaSHans Petter Selasky 		cl_qpool_put(&p_list->list_item_pool,
403*d6b92ffaSHans Petter Selasky 			     (cl_pool_item_t *) p_list_item);
404*d6b92ffaSHans Petter Selasky 		return (CL_SUCCESS);
405*d6b92ffaSHans Petter Selasky 	}
406*d6b92ffaSHans Petter Selasky 	return (CL_NOT_FOUND);
407*d6b92ffaSHans Petter Selasky }
408*d6b92ffaSHans Petter Selasky 
cl_is_object_in_list(IN const cl_list_t * const p_list,IN const void * const p_object)409*d6b92ffaSHans Petter Selasky boolean_t cl_is_object_in_list(IN const cl_list_t * const p_list,
410*d6b92ffaSHans Petter Selasky 			       IN const void *const p_object)
411*d6b92ffaSHans Petter Selasky {
412*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
413*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
414*d6b92ffaSHans Petter Selasky 
415*d6b92ffaSHans Petter Selasky 	return (cl_qlist_find_from_head
416*d6b92ffaSHans Petter Selasky 		(&p_list->list, cl_list_find_cb, p_object)
417*d6b92ffaSHans Petter Selasky 		!= cl_qlist_end(&p_list->list));
418*d6b92ffaSHans Petter Selasky }
419*d6b92ffaSHans Petter Selasky 
cl_list_insert_array_head(IN cl_list_t * const p_list,IN const void * const p_array,IN uint32_t item_count,IN const uint32_t item_size)420*d6b92ffaSHans Petter Selasky cl_status_t cl_list_insert_array_head(IN cl_list_t * const p_list,
421*d6b92ffaSHans Petter Selasky 				      IN const void *const p_array,
422*d6b92ffaSHans Petter Selasky 				      IN uint32_t item_count,
423*d6b92ffaSHans Petter Selasky 				      IN const uint32_t item_size)
424*d6b92ffaSHans Petter Selasky {
425*d6b92ffaSHans Petter Selasky 	cl_status_t status;
426*d6b92ffaSHans Petter Selasky 	void *p_object;
427*d6b92ffaSHans Petter Selasky 	uint32_t items_remain = item_count;
428*d6b92ffaSHans Petter Selasky 
429*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
430*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
431*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_array);
432*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_size);
433*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_count);
434*d6b92ffaSHans Petter Selasky 
435*d6b92ffaSHans Petter Selasky 	/*
436*d6b92ffaSHans Petter Selasky 	 * To add items from the array to the list in the same order as
437*d6b92ffaSHans Petter Selasky 	 * the elements appear in the array, we add them starting with
438*d6b92ffaSHans Petter Selasky 	 * the last one first.  Locate the last item.
439*d6b92ffaSHans Petter Selasky 	 */
440*d6b92ffaSHans Petter Selasky 	p_object = ((uint8_t *) p_array + (item_size * (item_count - 1)));
441*d6b92ffaSHans Petter Selasky 
442*d6b92ffaSHans Petter Selasky 	/* Continue to add all items to the list. */
443*d6b92ffaSHans Petter Selasky 	while (items_remain--) {
444*d6b92ffaSHans Petter Selasky 		status = cl_list_insert_head(p_list, p_object);
445*d6b92ffaSHans Petter Selasky 		if (status != CL_SUCCESS) {
446*d6b92ffaSHans Petter Selasky 			/* Remove all items that have been inserted. */
447*d6b92ffaSHans Petter Selasky 			while (items_remain++ < (item_count - 1))
448*d6b92ffaSHans Petter Selasky 				cl_list_remove_head(p_list);
449*d6b92ffaSHans Petter Selasky 			return (status);
450*d6b92ffaSHans Petter Selasky 		}
451*d6b92ffaSHans Petter Selasky 
452*d6b92ffaSHans Petter Selasky 		/* Get the next object to add to the list. */
453*d6b92ffaSHans Petter Selasky 		p_object = ((uint8_t *) p_object - item_size);
454*d6b92ffaSHans Petter Selasky 	}
455*d6b92ffaSHans Petter Selasky 
456*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
457*d6b92ffaSHans Petter Selasky }
458*d6b92ffaSHans Petter Selasky 
cl_list_insert_array_tail(IN cl_list_t * const p_list,IN const void * const p_array,IN uint32_t item_count,IN const uint32_t item_size)459*d6b92ffaSHans Petter Selasky cl_status_t cl_list_insert_array_tail(IN cl_list_t * const p_list,
460*d6b92ffaSHans Petter Selasky 				      IN const void *const p_array,
461*d6b92ffaSHans Petter Selasky 				      IN uint32_t item_count,
462*d6b92ffaSHans Petter Selasky 				      IN const uint32_t item_size)
463*d6b92ffaSHans Petter Selasky {
464*d6b92ffaSHans Petter Selasky 	cl_status_t status;
465*d6b92ffaSHans Petter Selasky 	void *p_object;
466*d6b92ffaSHans Petter Selasky 	uint32_t items_remain = item_count;
467*d6b92ffaSHans Petter Selasky 
468*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
469*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
470*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_array);
471*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_size);
472*d6b92ffaSHans Petter Selasky 	CL_ASSERT(item_count);
473*d6b92ffaSHans Petter Selasky 
474*d6b92ffaSHans Petter Selasky 	/* Set the first item to add to the list. */
475*d6b92ffaSHans Petter Selasky 	p_object = (void *)p_array;
476*d6b92ffaSHans Petter Selasky 
477*d6b92ffaSHans Petter Selasky 	/* Continue to add all items to the list. */
478*d6b92ffaSHans Petter Selasky 	while (items_remain--) {
479*d6b92ffaSHans Petter Selasky 		status = cl_list_insert_tail(p_list, p_object);
480*d6b92ffaSHans Petter Selasky 		if (status != CL_SUCCESS) {
481*d6b92ffaSHans Petter Selasky 			/* Remove all items that have been inserted. */
482*d6b92ffaSHans Petter Selasky 			while (items_remain++ < (item_count - 1))
483*d6b92ffaSHans Petter Selasky 				cl_list_remove_tail(p_list);
484*d6b92ffaSHans Petter Selasky 			return (status);
485*d6b92ffaSHans Petter Selasky 		}
486*d6b92ffaSHans Petter Selasky 
487*d6b92ffaSHans Petter Selasky 		/* Get the next object to add to the list. */
488*d6b92ffaSHans Petter Selasky 		p_object = ((uint8_t *) p_object + item_size);
489*d6b92ffaSHans Petter Selasky 	}
490*d6b92ffaSHans Petter Selasky 
491*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
492*d6b92ffaSHans Petter Selasky }
493*d6b92ffaSHans Petter Selasky 
cl_list_find_from_head(IN const cl_list_t * const p_list,IN cl_pfn_list_find_t pfn_func,IN const void * const context)494*d6b92ffaSHans Petter Selasky cl_list_iterator_t cl_list_find_from_head(IN const cl_list_t * const p_list,
495*d6b92ffaSHans Petter Selasky 					  IN cl_pfn_list_find_t pfn_func,
496*d6b92ffaSHans Petter Selasky 					  IN const void *const context)
497*d6b92ffaSHans Petter Selasky {
498*d6b92ffaSHans Petter Selasky 	cl_status_t status;
499*d6b92ffaSHans Petter Selasky 	cl_list_iterator_t itor;
500*d6b92ffaSHans Petter Selasky 
501*d6b92ffaSHans Petter Selasky 	/* Note that context can have any arbitrary value. */
502*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
503*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
504*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
505*d6b92ffaSHans Petter Selasky 
506*d6b92ffaSHans Petter Selasky 	itor = cl_list_head(p_list);
507*d6b92ffaSHans Petter Selasky 
508*d6b92ffaSHans Petter Selasky 	while (itor != cl_list_end(p_list)) {
509*d6b92ffaSHans Petter Selasky 		status = pfn_func(cl_list_obj(itor), (void *)context);
510*d6b92ffaSHans Petter Selasky 		if (status == CL_SUCCESS)
511*d6b92ffaSHans Petter Selasky 			break;
512*d6b92ffaSHans Petter Selasky 
513*d6b92ffaSHans Petter Selasky 		itor = cl_list_next(itor);
514*d6b92ffaSHans Petter Selasky 	}
515*d6b92ffaSHans Petter Selasky 
516*d6b92ffaSHans Petter Selasky 	/* no match */
517*d6b92ffaSHans Petter Selasky 	return (itor);
518*d6b92ffaSHans Petter Selasky }
519*d6b92ffaSHans Petter Selasky 
cl_list_find_from_tail(IN const cl_list_t * const p_list,IN cl_pfn_list_find_t pfn_func,IN const void * const context)520*d6b92ffaSHans Petter Selasky cl_list_iterator_t cl_list_find_from_tail(IN const cl_list_t * const p_list,
521*d6b92ffaSHans Petter Selasky 					  IN cl_pfn_list_find_t pfn_func,
522*d6b92ffaSHans Petter Selasky 					  IN const void *const context)
523*d6b92ffaSHans Petter Selasky {
524*d6b92ffaSHans Petter Selasky 	cl_status_t status;
525*d6b92ffaSHans Petter Selasky 	cl_list_iterator_t itor;
526*d6b92ffaSHans Petter Selasky 
527*d6b92ffaSHans Petter Selasky 	/* Note that context can have any arbitrary value. */
528*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
529*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
530*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
531*d6b92ffaSHans Petter Selasky 
532*d6b92ffaSHans Petter Selasky 	itor = cl_list_tail(p_list);
533*d6b92ffaSHans Petter Selasky 
534*d6b92ffaSHans Petter Selasky 	while (itor != cl_list_end(p_list)) {
535*d6b92ffaSHans Petter Selasky 		status = pfn_func(cl_list_obj(itor), (void *)context);
536*d6b92ffaSHans Petter Selasky 		if (status == CL_SUCCESS)
537*d6b92ffaSHans Petter Selasky 			break;
538*d6b92ffaSHans Petter Selasky 
539*d6b92ffaSHans Petter Selasky 		itor = cl_list_prev(itor);
540*d6b92ffaSHans Petter Selasky 	}
541*d6b92ffaSHans Petter Selasky 
542*d6b92ffaSHans Petter Selasky 	/* no match */
543*d6b92ffaSHans Petter Selasky 	return (itor);
544*d6b92ffaSHans Petter Selasky }
545*d6b92ffaSHans Petter Selasky 
cl_list_apply_func(IN const cl_list_t * const p_list,IN cl_pfn_list_apply_t pfn_func,IN const void * const context)546*d6b92ffaSHans Petter Selasky void cl_list_apply_func(IN const cl_list_t * const p_list,
547*d6b92ffaSHans Petter Selasky 			IN cl_pfn_list_apply_t pfn_func,
548*d6b92ffaSHans Petter Selasky 			IN const void *const context)
549*d6b92ffaSHans Petter Selasky {
550*d6b92ffaSHans Petter Selasky 	cl_list_iterator_t itor;
551*d6b92ffaSHans Petter Selasky 
552*d6b92ffaSHans Petter Selasky 	/* Note that context can have any arbitrary value. */
553*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_list);
554*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
555*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_func);
556*d6b92ffaSHans Petter Selasky 
557*d6b92ffaSHans Petter Selasky 	itor = cl_list_head(p_list);
558*d6b92ffaSHans Petter Selasky 
559*d6b92ffaSHans Petter Selasky 	while (itor != cl_list_end(p_list)) {
560*d6b92ffaSHans Petter Selasky 		pfn_func(cl_list_obj(itor), (void *)context);
561*d6b92ffaSHans Petter Selasky 
562*d6b92ffaSHans Petter Selasky 		itor = cl_list_next(itor);
563*d6b92ffaSHans Petter Selasky 	}
564*d6b92ffaSHans Petter Selasky }
565