1 /*
2  * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35 
36 /*
37  * Abstract:
38  *	Declaration of list.
39  */
40 
41 #ifndef _CL_LIST_H_
42 #define _CL_LIST_H_
43 
44 #include <complib/cl_qlist.h>
45 #include <complib/cl_qpool.h>
46 
47 #ifdef __cplusplus
48 #  define BEGIN_C_DECLS extern "C" {
49 #  define END_C_DECLS   }
50 #else				/* !__cplusplus */
51 #  define BEGIN_C_DECLS
52 #  define END_C_DECLS
53 #endif				/* __cplusplus */
54 
55 BEGIN_C_DECLS
56 /****h* Component Library/List
57 * NAME
58 *	List
59 *
60 * DESCRIPTION
61 *	List stores objects in a doubly linked list.
62 *
63 *	Unlike quick list, users pass pointers to the object being stored, rather
64 *	than to a cl_list_item_t structure.  Insertion operations on a list can
65 *	fail, and callers should trap for such failures.
66 *
67 *	Use quick list in situations where insertion failures cannot be tolerated.
68 *
69 *	List is not thread safe, and users must provide serialization.
70 *
71 *	The list functions operates on a cl_list_t structure which should be
72 *	treated as opaque and should be manipulated only through the provided
73 *	functions.
74 *
75 * SEE ALSO
76 *	Types:
77 *		cl_list_iterator_t
78 *
79 *	Structures:
80 *		cl_list_t
81 *
82 *	Callbacks:
83 *		cl_pfn_list_apply_t, cl_pfn_list_find_t
84 *
85 *	Initialization/Destruction:
86 *		cl_list_construct, cl_list_init, cl_list_destroy
87 *
88 *	Iteration:
89 *		cl_list_next, cl_list_prev, cl_list_head, cl_list_tail,
90 *		cl_list_end
91 *
92 *	Manipulation:
93 *		cl_list_insert_head, cl_list_insert_tail,
94 *		cl_list_insert_array_head, cl_list_insert_array_tail,
95 *		cl_list_insert_prev, cl_list_insert_next,
96 *		cl_list_remove_head, cl_list_remove_tail,
97 *		cl_list_remove_object, cl_list_remove_item, cl_list_remove_all
98 *
99 *	Search:
100 *		cl_is_object_in_list, cl_list_find_from_head, cl_list_find_from_tail,
101 *		cl_list_apply_func
102 *
103 *	Attributes:
104 *		cl_list_count, cl_is_list_empty, cl_is_list_inited
105 *********/
106 /****s* Component Library: List/cl_list_t
107 * NAME
108 *	cl_list_t
109 *
110 * DESCRIPTION
111 *	List structure.
112 *
113 *	The cl_list_t structure should be treated as opaque and should be
114 *	manipulated only through the provided functions.
115 *
116 * SYNOPSIS
117 */
118 typedef struct _cl_list {
119 	cl_qlist_t list;
120 	cl_qpool_t list_item_pool;
121 } cl_list_t;
122 /*
123 * FIELDS
124 *	list
125 *		Quick list of items stored in the list.
126 *
127 *	list_item_pool
128 *		Quick pool of list objects for storing objects in the quick list.
129 *
130 * SEE ALSO
131 *	List
132 *********/
133 
134 /****d* Component Library: List/cl_list_iterator_t
135 * NAME
136 *	cl_list_iterator_t
137 *
138 * DESCRIPTION
139 *	Iterator type used to walk a list.
140 *
141 * SYNOPSIS
142 */
143 typedef const cl_list_item_t *cl_list_iterator_t;
144 /*
145 * NOTES
146 *	The iterator should be treated as opaque to prevent corrupting the list.
147 *
148 * SEE ALSO
149 *	List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev,
150 *	cl_list_obj
151 *********/
152 
153 /****d* Component Library: List/cl_pfn_list_apply_t
154 * NAME
155 *	cl_pfn_list_apply_t
156 *
157 * DESCRIPTION
158 *	The cl_pfn_list_apply_t function type defines the prototype for functions
159 *	used to iterate objects in a list.
160 *
161 * SYNOPSIS
162 */
163 typedef void
164  (*cl_pfn_list_apply_t) (IN void *const p_object, IN void *context);
165 /*
166 * PARAMETERS
167 *	p_object
168 *		[in] Pointer to an object stored in a list.
169 *
170 *	context
171 *		[in] Context provided in a call to cl_list_apply_func.
172 *
173 * RETURN VALUE
174 *	This function does not return a value.
175 *
176 * NOTES
177 *	This function type is provided as function prototype reference for the
178 *	function provided by users as a parameter to the cl_list_apply_func
179 *	function.
180 *
181 * SEE ALSO
182 *	List, cl_list_apply_func
183 *********/
184 
185 /****d* Component Library: List/cl_pfn_list_find_t
186 * NAME
187 *	cl_pfn_list_find_t
188 *
189 * DESCRIPTION
190 *	The cl_pfn_list_find_t function type defines the prototype for functions
191 *	used to find objects in a list.
192 *
193 * SYNOPSIS
194 */
195 typedef cl_status_t
196     (*cl_pfn_list_find_t) (IN const void *const p_object, IN void *context);
197 /*
198 * PARAMETERS
199 *	p_object
200 *		[in] Pointer to an object stored in a list.
201 *
202 *	context
203 *		[in] Context provided in a call to ListFindFromHead or ListFindFromTail.
204 *
205 * RETURN VALUES
206 *	Return CL_SUCCESS if the desired item was found.  This stops list iteration.
207 *
208 *	Return CL_NOT_FOUND to continue the list iteration.
209 *
210 * NOTES
211 *	This function type is provided as function prototype reference for the
212 *	function provided by users as a parameter to the cl_list_find_from_head
213 *	and cl_list_find_from_tail functions.
214 *
215 * SEE ALSO
216 *	List, cl_list_find_from_head, cl_list_find_from_tail
217 *********/
218 
219 /****f* Component Library: List/cl_list_construct
220 * NAME
221 *	cl_list_construct
222 *
223 * DESCRIPTION
224 *	The cl_list_construct function constructs a list.
225 *
226 * SYNOPSIS
227 */
228 void cl_list_construct(IN cl_list_t * const p_list);
229 /*
230 * PARAMETERS
231 *	p_list
232 *		[in] Pointer to cl_list_t object whose state to initialize.
233 *
234 * RETURN VALUE
235 *	This function does not return a value.
236 *
237 * NOTES
238 *	Allows calling cl_list_init, cl_list_destroy and cl_is_list_inited.
239 *
240 *	Calling cl_list_construct is a prerequisite to calling any other
241 *	list function except cl_list_init.
242 *
243 * SEE ALSO
244 *	List, cl_list_init, cl_list_destroy, cl_is_list_inited
245 *********/
246 
247 /****f* Component Library: List/cl_is_list_inited
248 * NAME
249 *	cl_is_list_inited
250 *
251 * DESCRIPTION
252 *	The cl_is_list_inited function returns whether a list was
253 *	initialized successfully.
254 *
255 * SYNOPSIS
256 */
257 static inline boolean_t cl_is_list_inited(IN const cl_list_t * const p_list)
258 {
259 	/* CL_ASSERT that a non-null pointer is provided. */
260 	CL_ASSERT(p_list);
261 	/*
262 	 * The pool is the last thing initialized.  If it is initialized, the
263 	 * list is initialized too.
264 	 */
265 	return (cl_is_qpool_inited(&p_list->list_item_pool));
266 }
267 
268 /*
269 * PARAMETERS
270 *	p_list
271 *		[in] Pointer to a cl_list_t structure whose initilization state
272 *		to check.
273 *
274 * RETURN VALUES
275 *	TRUE if the list was initialized successfully.
276 *
277 *	FALSE otherwise.
278 *
279 * NOTES
280 *	Allows checking the state of a list to determine if invoking
281 *	member functions is appropriate.
282 *
283 * SEE ALSO
284 *	List
285 *********/
286 
287 /****f* Component Library: List/cl_list_init
288 * NAME
289 *	cl_list_init
290 *
291 * DESCRIPTION
292 *	The cl_list_init function initializes a list for use.
293 *
294 * SYNOPSIS
295 */
296 cl_status_t
297 cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items);
298 /*
299 * PARAMETERS
300 *	p_list
301 *		[in] Pointer to cl_list_t structure to initialize.
302 *
303 *	min_items
304 *		[in] Minimum number of items that can be stored.  All necessary
305 *		allocations to allow storing the minimum number of items is performed
306 *		at initialization time.
307 *
308 * RETURN VALUES
309 *	CL_SUCCESS if the list was initialized successfully.
310 *
311 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for initialization.
312 *
313 * NOTES
314 *	The list will always be able to store at least as many items as specified
315 *	by the min_items parameter.
316 *
317 * SEE ALSO
318 *	List, cl_list_construct, cl_list_destroy, cl_list_insert_head,
319 *	cl_list_insert_tail, cl_list_remove_head, cl_list_remove_tail
320 *********/
321 
322 /****f* Component Library: List/cl_list_destroy
323 * NAME
324 *	cl_list_destroy
325 *
326 * DESCRIPTION
327 *	The cl_list_destroy function destroys a list.
328 *
329 * SYNOPSIS
330 */
331 void cl_list_destroy(IN cl_list_t * const p_list);
332 /*
333 * PARAMETERS
334 *	p_list
335 *		[in] Pointer to cl_list_t structure to destroy.
336 *
337 * RETURN VALUE
338 *	This function does not return a value.
339 *
340 * NOTES
341 *	cl_list_destroy does not affect any of the objects stored in the list,
342 *	but does release all memory allocated internally.  Further operations
343 *	should not be attempted on the list after cl_list_destroy is invoked.
344 *
345 *	This function should only be called after a call to cl_list_construct
346 *	or cl_list_init.
347 *
348 *	In debug builds, cl_list_destroy asserts if the list is not empty.
349 *
350 * SEE ALSO
351 *	List, cl_list_construct, cl_list_init
352 *********/
353 
354 /****f* Component Library: List/cl_is_list_empty
355 * NAME
356 *	cl_is_list_empty
357 *
358 * DESCRIPTION
359 *	The cl_is_list_empty function returns whether a list is empty.
360 *
361 * SYNOPSIS
362 */
363 static inline boolean_t cl_is_list_empty(IN const cl_list_t * const p_list)
364 {
365 	CL_ASSERT(p_list);
366 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
367 	return (cl_is_qlist_empty(&p_list->list));
368 }
369 
370 /*
371 * PARAMETERS
372 *	p_list
373 *		[in] Pointer to a cl_list_t structure.
374 *
375 * RETURN VALUES
376 *	TRUE if the specified list is empty.
377 *
378 *	FALSE otherwise.
379 *
380 * SEE ALSO
381 *	List, cl_list_count, cl_list_remove_all
382 *********/
383 
384 /****f* Component Library: List/cl_list_insert_head
385 * NAME
386 *	cl_list_insert_head
387 *
388 * DESCRIPTION
389 *	The cl_list_insert_head function inserts an object at the head of a list.
390 *
391 * SYNOPSIS
392 */
393 static inline cl_status_t
394 cl_list_insert_head(IN cl_list_t * const p_list, IN const void *const p_object)
395 {
396 	cl_pool_obj_t *p_pool_obj;
397 
398 	CL_ASSERT(p_list);
399 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
400 
401 	/* Get a list item to add to the list. */
402 	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
403 	if (!p_pool_obj)
404 		return (CL_INSUFFICIENT_MEMORY);
405 
406 	p_pool_obj->p_object = p_object;
407 	cl_qlist_insert_head(&p_list->list, &p_pool_obj->pool_item.list_item);
408 	return (CL_SUCCESS);
409 }
410 
411 /*
412 * PARAMETERS
413 *	p_list
414 *		[in] Pointer to a cl_list_t structure into which to insert the object.
415 *
416 *	p_object
417 *		[in] Pointer to an object to insert into the list.
418 *
419 * RETURN VALUES
420 *	CL_SUCCESS if the insertion was successful.
421 *
422 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
423 *
424 * NOTES
425 *	Inserts the specified object at the head of the list.  List insertion
426 *	operations are guaranteed to work for the minimum number of items as
427 *	specified in cl_list_init by the min_items parameter.
428 *
429 * SEE ALSO
430 *	List, cl_list_insert_tail, cl_list_insert_array_head,
431 *	cl_list_insert_array_tail, cl_list_insert_prev, cl_list_insert_next,
432 *	cl_list_remove_head
433 *********/
434 
435 /****f* Component Library: List/cl_list_insert_tail
436 * NAME
437 *	cl_list_insert_tail
438 *
439 * DESCRIPTION
440 *	The cl_list_insert_tail function inserts an object at the tail of a list.
441 *
442 * SYNOPSIS
443 */
444 static inline cl_status_t
445 cl_list_insert_tail(IN cl_list_t * const p_list, IN const void *const p_object)
446 {
447 	cl_pool_obj_t *p_pool_obj;
448 
449 	CL_ASSERT(p_list);
450 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
451 
452 	/* Get a list item to add to the list. */
453 	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
454 	if (!p_pool_obj)
455 		return (CL_INSUFFICIENT_MEMORY);
456 
457 	p_pool_obj->p_object = p_object;
458 	cl_qlist_insert_tail(&p_list->list, &p_pool_obj->pool_item.list_item);
459 	return (CL_SUCCESS);
460 }
461 
462 /*
463 * PARAMETERS
464 *	p_list
465 *		[in] Pointer to a cl_list_t structure into which to insert the object.
466 *
467 *	p_object
468 *		[in] Pointer to an object to insert into the list.
469 *
470 * RETURN VALUES
471 *	CL_SUCCESS if the insertion was successful.
472 *
473 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
474 *
475 * NOTES
476 *	Inserts the specified object at the tail of the list.  List insertion
477 *	operations are guaranteed to work for the minimum number of items as
478 *	specified in cl_list_init by the min_items parameter.
479 *
480 * SEE ALSO
481 *	List, cl_list_insert_head, cl_list_insert_array_head,
482 *	cl_list_insert_array_tail, cl_list_insert_prev, cl_list_insert_next,
483 *	cl_list_remove_tail
484 *********/
485 
486 /****f* Component Library: List/cl_list_insert_array_head
487 * NAME
488 *	cl_list_insert_array_head
489 *
490 * DESCRIPTION:
491 *	The cl_list_insert_array_head function inserts an array of objects
492 *	at the head of a list.
493 *
494 * SYNOPSIS
495 */
496 cl_status_t
497 cl_list_insert_array_head(IN cl_list_t * const p_list,
498 			  IN const void *const p_array,
499 			  IN uint32_t item_count, IN const uint32_t item_size);
500 /*
501 * PARAMETERS
502 *	p_list
503 *		[in] Pointer to a cl_list_t structure into which to insert the objects.
504 *
505 *	p_array
506 *		[in] Pointer to the first object in an array.
507 *
508 *	item_count
509 *		[in] Number of objects in the array.
510 *
511 *	item_size
512 *		[in] Size of the objects added to the list.  This is the stride in the
513 *		array from one object to the next.
514 *
515 * RETURN VALUES
516 *	CL_SUCCESS if the insertion was successful.
517 *
518 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
519 *
520 * NOTES
521 *	Inserts all objects in the array to the head of the list, preserving the
522 *	ordering of the objects.  If not successful, no items are added.
523 *	List insertion operations are guaranteed to work for the minimum number
524 *	of items as specified in cl_list_init by the min_items parameter.
525 *
526 * SEE ALSO
527 *	List, cl_list_insert_array_tail, cl_list_insert_head, cl_list_insert_tail,
528 *	cl_list_insert_prev, cl_list_insert_next
529 *********/
530 
531 /****f* Component Library: List/cl_list_insert_array_tail
532 * NAME
533 *	cl_list_insert_array_tail
534 *
535 * DESCRIPTION
536 *	The cl_list_insert_array_tail function inserts an array of objects
537 *	at the tail of a list.
538 *
539 * SYNOPSIS
540 */
541 cl_status_t
542 cl_list_insert_array_tail(IN cl_list_t * const p_list,
543 			  IN const void *const p_array,
544 			  IN uint32_t item_count, IN const uint32_t item_size);
545 /*
546 * PARAMETERS
547 *	p_list
548 *		[in] Pointer to a cl_list_t structure into which to insert the objects.
549 *
550 *	p_array
551 *		[in] Pointer to the first object in an array.
552 *
553 *	item_count
554 *		[in] Number of objects in the array.
555 *
556 *	item_size
557 *		[in] Size of the objects added to the list.  This is the stride in the
558 *		array from one object to the next.
559 *
560 * RETURN VALUES
561 *	CL_SUCCESS if the insertion was successful.
562 *
563 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
564 *
565 * NOTES
566 *	Inserts all objects in the array to the tail of the list, preserving the
567 *	ordering of the objects.  If not successful, no items are added.
568 *	List insertion operations are guaranteed to work for the minimum number
569 *	of items as specified in cl_list_init by the min_items parameter.
570 *
571 * SEE ALSO
572 *	List, cl_list_insert_array_head, cl_list_insert_head, cl_list_insert_tail,
573 *	cl_list_insert_prev, cl_list_insert_next
574 *********/
575 
576 /****f* Component Library: List/cl_list_insert_next
577 * NAME
578 *	cl_list_insert_next
579 *
580 * DESCRIPTION
581 *	The cl_list_insert_next function inserts an object in a list after
582 *	the object associated with a given iterator.
583 *
584 * SYNOPSIS
585 */
586 static inline cl_status_t
587 cl_list_insert_next(IN cl_list_t * const p_list,
588 		    IN cl_list_iterator_t iterator,
589 		    IN const void *const p_object)
590 {
591 	cl_pool_obj_t *p_pool_obj;
592 
593 	CL_ASSERT(p_list);
594 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
595 
596 	/* Get a list item to add to the list. */
597 	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
598 	if (!p_pool_obj)
599 		return (CL_INSUFFICIENT_MEMORY);
600 
601 	p_pool_obj->p_object = p_object;
602 	cl_qlist_insert_next(&p_list->list, (cl_list_item_t *) iterator,
603 			     &p_pool_obj->pool_item.list_item);
604 	return (CL_SUCCESS);
605 }
606 
607 /*
608 * PARAMETERS
609 *	p_list
610 *		[in] Pointer to a cl_list_t structure into which to insert the object.
611 *
612 *	iterator
613 *		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
614 *		cl_list_tail, cl_list_next, or cl_list_prev.
615 *
616 *	p_object
617 *		[in] Pointer to an object to insert into the list.
618 *
619 * RETURN VALUES
620 *	CL_SUCCESS if the insertion was successful.
621 *
622 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
623 *
624 * SEE ALSO
625 *	List, cl_list_insert_prev, cl_list_insert_head, cl_list_insert_tail,
626 *	cl_list_insert_array_head, cl_list_insert_array_tail
627 *********/
628 
629 /****f* Component Library: List/cl_list_insert_prev
630 * NAME
631 *	cl_list_insert_prev
632 *
633 * DESCRIPTION
634 *	The cl_list_insert_prev function inserts an object in a list before
635 *	the object associated with a given iterator.
636 *
637 * SYNOPSIS
638 */
639 static inline cl_status_t
640 cl_list_insert_prev(IN cl_list_t * const p_list,
641 		    IN cl_list_iterator_t iterator,
642 		    IN const void *const p_object)
643 {
644 	cl_pool_obj_t *p_pool_obj;
645 
646 	CL_ASSERT(p_list);
647 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
648 
649 	/* Get a list item to add to the list. */
650 	p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool);
651 	if (!p_pool_obj)
652 		return (CL_INSUFFICIENT_MEMORY);
653 
654 	p_pool_obj->p_object = p_object;
655 	cl_qlist_insert_prev(&p_list->list, (cl_list_item_t *) iterator,
656 			     &p_pool_obj->pool_item.list_item);
657 	return (CL_SUCCESS);
658 }
659 
660 /*
661 * PARAMETERS
662 *	p_list
663 *		[in] Pointer to a cl_list_t structure into which to insert the object.
664 *
665 *	iterator
666 *		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
667 *		cl_list_tail, cl_list_next, or cl_list_prev.
668 *
669 *	p_object
670 *		[in] Pointer to an object to insert into the list.
671 *
672 * RETURN VALUES
673 *	CL_SUCCESS if the insertion was successful.
674 *
675 *	CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion.
676 *
677 * SEE ALSO
678 *	List, cl_list_insert_next, cl_list_insert_head, cl_list_insert_tail,
679 *	cl_list_insert_array_head, cl_list_insert_array_tail
680 *********/
681 
682 /****f* Component Library: List/cl_list_remove_head
683 * NAME
684 *	cl_list_remove_head
685 *
686 * DESCRIPTION
687 *	The cl_list_remove_head function removes an object from the head of a list.
688 *
689 * SYNOPSIS
690 */
691 static inline void *cl_list_remove_head(IN cl_list_t * const p_list)
692 {
693 	cl_pool_obj_t *p_pool_obj;
694 	void *p_obj;
695 
696 	CL_ASSERT(p_list);
697 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
698 
699 	/* See if the list is empty. */
700 	if (cl_is_qlist_empty(&p_list->list))
701 		return (NULL);
702 
703 	/* Get the item at the head of the list. */
704 	p_pool_obj = (cl_pool_obj_t *) cl_qlist_remove_head(&p_list->list);
705 
706 	p_obj = (void *)p_pool_obj->p_object;
707 	/* Place the pool item back into the pool. */
708 	cl_qpool_put(&p_list->list_item_pool, &p_pool_obj->pool_item);
709 
710 	return (p_obj);
711 }
712 
713 /*
714 * PARAMETERS
715 *	p_list
716 *		[in] Pointer to a cl_list_t structure from which to remove an object.
717 *
718 * RETURN VALUES
719 *	Returns the pointer to the object formerly at the head of the list.
720 *
721 *	NULL if the list was empty.
722 *
723 * SEE ALSO
724 *	List, cl_list_remove_tail, cl_list_remove_all, cl_list_remove_object,
725 *	cl_list_remove_item, cl_list_insert_head
726 *********/
727 
728 /****f* Component Library: List/cl_list_remove_tail
729 * NAME
730 *	cl_list_remove_tail
731 *
732 * DESCRIPTION
733 *	The cl_list_remove_tail function removes an object from the tail of a list.
734 *
735 * SYNOPSIS
736 */
737 static inline void *cl_list_remove_tail(IN cl_list_t * const p_list)
738 {
739 	cl_pool_obj_t *p_pool_obj;
740 
741 	CL_ASSERT(p_list);
742 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
743 
744 	/* See if the list is empty. */
745 	if (cl_is_qlist_empty(&p_list->list))
746 		return (NULL);
747 
748 	/* Get the item at the head of the list. */
749 	p_pool_obj = (cl_pool_obj_t *) cl_qlist_remove_tail(&p_list->list);
750 
751 	/* Place the list item back into the pool. */
752 	cl_qpool_put(&p_list->list_item_pool, &p_pool_obj->pool_item);
753 
754 	return ((void *)p_pool_obj->p_object);
755 }
756 
757 /*
758 * PARAMETERS
759 *	p_list
760 *		[in] Pointer to a cl_list_t structure from which to remove an object.
761 *
762 * RETURN VALUES
763 *	Returns the pointer to the object formerly at the tail of the list.
764 *
765 *	NULL if the list was empty.
766 *
767 * SEE ALSO
768 *	List, cl_list_remove_head, cl_list_remove_all, cl_list_remove_object,
769 *	cl_list_remove_item, cl_list_insert_head
770 *********/
771 
772 /****f* Component Library: List/cl_list_remove_all
773 * NAME
774 *	cl_list_remove_all
775 *
776 * DESCRIPTION
777 *	The cl_list_remove_all function removes all objects from a list,
778 *	leaving it empty.
779 *
780 * SYNOPSIS
781 */
782 static inline void cl_list_remove_all(IN cl_list_t * const p_list)
783 {
784 	CL_ASSERT(p_list);
785 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
786 
787 	/* Return all the list items to the pool. */
788 	cl_qpool_put_list(&p_list->list_item_pool, &p_list->list);
789 }
790 
791 /*
792 * PARAMETERS
793 *	p_list
794 *		[in] Pointer to a cl_list_t structure from which to remove all objects.
795 *
796 * RETURN VALUE
797 *	This function does not return a value.
798 *
799 * SEE ALSO
800 *	List, cl_list_remove_head, cl_list_remove_tail, cl_list_remove_object,
801 *	cl_list_remove_item
802 *********/
803 
804 /****f* Component Library: List/cl_list_remove_object
805 * NAME
806 *	cl_list_remove_object
807 *
808 * DESCRIPTION
809 *	The cl_list_remove_object function removes a specific object from a list.
810 *
811 * SYNOPSIS
812 */
813 cl_status_t
814 cl_list_remove_object(IN cl_list_t * const p_list,
815 		      IN const void *const p_object);
816 /*
817 * PARAMETERS
818 *	p_list
819 *		[in] Pointer to a cl_list_t structure from which to remove the object.
820 *
821 *	p_object
822 *		[in] Pointer to an object to remove from the list.
823 *
824 * RETURN VALUES
825 *	CL_SUCCESS if the object was removed.
826 *
827 *	CL_NOT_FOUND if the object was not found in the list.
828 *
829 * NOTES
830 *	Removes the first occurrence of an object from a list.
831 *
832 * SEE ALSO
833 *	List, cl_list_remove_item, cl_list_remove_head, cl_list_remove_tail,
834 *	cl_list_remove_all
835 *********/
836 
837 /****f* Component Library: List/cl_list_remove_item
838 * NAME
839 *	cl_list_remove_item
840 *
841 * DESCRIPTION
842 *	The cl_list_remove_item function removes an object from the head of a list.
843 *
844 * SYNOPSIS
845 */
846 static inline void
847 cl_list_remove_item(IN cl_list_t * const p_list, IN cl_list_iterator_t iterator)
848 {
849 	CL_ASSERT(p_list);
850 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
851 
852 	cl_qlist_remove_item(&p_list->list, (cl_list_item_t *) iterator);
853 
854 	/* Place the list item back into the pool. */
855 	cl_qpool_put(&p_list->list_item_pool, (cl_pool_item_t *) iterator);
856 }
857 
858 /*
859 * PARAMETERS
860 *	p_list
861 *		[in] Pointer to a cl_list_t structure from which to remove the item.
862 *
863 *	iterator
864 *		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
865 *		cl_list_tail, cl_list_next, or cl_list_prev.
866 *
867 * RETURN VALUE
868 *	This function does not return a value.
869 *
870 * SEE ALSO
871 *	List, cl_list_remove_object, cl_list_remove_head, cl_list_remove_tail,
872 *	cl_list_remove_all
873 *********/
874 
875 /****f* Component Library: List/cl_is_object_in_list
876 * NAME
877 *	cl_is_object_in_list
878 *
879 * DESCRIPTION
880 *	The cl_is_object_in_list function returns whether an object
881 *	is stored in a list.
882 *
883 * SYNOPSIS
884 */
885 boolean_t
886 cl_is_object_in_list(IN const cl_list_t * const p_list,
887 		     IN const void *const p_object);
888 /*
889 * PARAMETERS
890 *	p_list
891 *		[in] Pointer to a cl_list_t structure in which to look for the object.
892 *
893 *	p_object
894 *		[in] Pointer to an object stored in a list.
895 *
896 * RETURN VALUES
897 *	TRUE if p_object was found in the list.
898 *
899 *	FALSE otherwise.
900 *
901 * SEE ALSO
902 *	List
903 *********/
904 
905 /****f* Component Library: List/cl_list_end
906 * NAME
907 *	cl_list_end
908 *
909 * DESCRIPTION
910 *	The cl_list_end function returns returns the list iterator for
911 *	the end of a list.
912 *
913 * SYNOPSIS
914 */
915 static inline cl_list_iterator_t cl_list_end(IN const cl_list_t * const p_list)
916 {
917 	CL_ASSERT(p_list);
918 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
919 
920 	return (cl_qlist_end(&p_list->list));
921 }
922 
923 /*
924 * PARAMETERS
925 *	p_list
926 *		[in] Pointer to a cl_list_t structure for which the iterator for the
927 *		object at the head is to be returned.
928 *
929 * RETURN VALUE
930 *	cl_list_iterator_t for the end of the list.
931 *
932 * NOTES
933 *	Use cl_list_obj to retrieve the object associated with the
934 *	returned cl_list_iterator_t.
935 *
936 * SEE ALSO
937 *	List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev,
938 *	cl_list_obj
939 *********/
940 
941 /****f* Component Library: List/cl_list_head
942 * NAME
943 *	cl_list_head
944 *
945 * DESCRIPTION
946 *	The cl_list_head function returns returns a list iterator for
947 *	the head of a list.
948 *
949 * SYNOPSIS
950 */
951 static inline cl_list_iterator_t cl_list_head(IN const cl_list_t * const p_list)
952 {
953 	CL_ASSERT(p_list);
954 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
955 
956 	return (cl_qlist_head(&p_list->list));
957 }
958 
959 /*
960 * PARAMETERS
961 *	p_list
962 *		[in] Pointer to a cl_list_t structure for which the iterator for the
963 *		object at the head is to be returned.
964 *
965 * RETURN VALUES
966 *	cl_list_iterator_t for the head of the list.
967 *
968 *	cl_list_iterator_t for the end of the list if the list is empty.
969 *
970 * NOTES
971 *	Use cl_list_obj to retrieve the object associated with the
972 *	returned cl_list_iterator_t.
973 *
974 * SEE ALSO
975 *	List, cl_list_tail, cl_list_next, cl_list_prev, cl_list_end,
976 *	cl_list_obj
977 *********/
978 
979 /****f* Component Library: List/cl_list_tail
980 * NAME
981 *	cl_list_tail
982 *
983 * DESCRIPTION
984 *	The cl_list_tail function returns returns a list iterator for
985 *	the tail of a list.
986 *
987 * SYNOPSIS
988 */
989 static inline cl_list_iterator_t cl_list_tail(IN const cl_list_t * const p_list)
990 {
991 	CL_ASSERT(p_list);
992 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
993 
994 	return (cl_qlist_tail(&p_list->list));
995 }
996 
997 /*
998 * PARAMETERS
999 *	p_list
1000 *		[in] Pointer to a cl_list_t structure for which the iterator for the
1001 *		object at the tail is to be returned.
1002 *
1003 * RETURN VALUES
1004 *	cl_list_iterator_t for the tail of the list.
1005 *
1006 *	cl_list_iterator_t for the end of the list if the list is empty.
1007 *
1008 * NOTES
1009 *	Use cl_list_obj to retrieve the object associated with the
1010 *
1011 *	returned cl_list_iterator_t.
1012 *
1013 * SEE ALSO
1014 *	List, cl_list_head, cl_list_next, cl_list_prev, cl_list_end,
1015 *	cl_list_obj
1016 *********/
1017 
1018 /****f* Component Library: List/cl_list_next
1019 * NAME
1020 *	cl_list_next
1021 *
1022 * DESCRIPTION
1023 *	The cl_list_next function returns a list iterator for the object stored
1024 *	in a list after the object associated with a given list iterator.
1025 *
1026 * SYNOPSIS
1027 */
1028 static inline cl_list_iterator_t cl_list_next(IN cl_list_iterator_t iterator)
1029 {
1030 	CL_ASSERT(iterator);
1031 
1032 	return (cl_qlist_next(iterator));
1033 }
1034 
1035 /*
1036 * PARAMETERS
1037 *	p_list
1038 *		[in] Pointer to a cl_list_t structure for which the iterator for the
1039 *		next object is to be returned.
1040 *
1041 *	iterator
1042 *		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
1043 *		cl_list_tail, cl_list_next, or cl_list_prev.
1044 *
1045 * RETURN VALUES
1046 *	cl_list_iterator_t for the object following the object associated with
1047 *	the list iterator specified by the iterator parameter.
1048 *
1049 *	cl_list_iterator_t for the end of the list if the list is empty.
1050 *
1051 * NOTES
1052 *	Use cl_list_obj to retrieve the object associated with the
1053 *	returned cl_list_iterator_t.
1054 *
1055 * SEE ALSO
1056 *	List, cl_list_prev, cl_list_head, cl_list_tail, cl_list_end,
1057 *	cl_list_obj
1058 *********/
1059 
1060 /****f* Component Library: List/cl_list_prev
1061 * NAME
1062 *	cl_list_prev
1063 *
1064 * DESCRIPTION
1065 *	The cl_list_prev function returns a list iterator for the object stored
1066 *	in a list before the object associated with a given list iterator.
1067 *
1068 * SYNOPSIS
1069 */
1070 static inline cl_list_iterator_t cl_list_prev(IN cl_list_iterator_t iterator)
1071 {
1072 	CL_ASSERT(iterator);
1073 
1074 	return (cl_qlist_prev(iterator));
1075 }
1076 
1077 /*
1078 * PARAMETERS
1079 *	p_list
1080 *		[in] Pointer to a cl_list_t structure for which the iterator for the
1081 *		next object is to be returned.
1082 *
1083 *	iterator
1084 *		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
1085 *		cl_list_tail, cl_list_next, or cl_list_prev.
1086 *
1087 * RETURN VALUES
1088 *	cl_list_iterator_t for the object preceding the object associated with
1089 *	the list iterator specified by the iterator parameter.
1090 *
1091 *	cl_list_iterator_t for the end of the list if the list is empty.
1092 *
1093 * NOTES
1094 *	Use cl_list_obj to retrieve the object associated with the
1095 *	returned cl_list_iterator_t.
1096 *
1097 * SEE ALSO
1098 *	List, cl_list_next, cl_list_head, cl_list_tail, cl_list_end,
1099 *	cl_list_obj
1100 *********/
1101 
1102 /****f* Component Library: List/cl_list_obj
1103 * NAME
1104 *	cl_list_obj
1105 *
1106 * DESCRIPTION
1107 *	The cl_list_obj function returns the object associated
1108 *	with a list iterator.
1109 *
1110 * SYNOPSIS
1111 */
1112 static inline void *cl_list_obj(IN cl_list_iterator_t iterator)
1113 {
1114 	CL_ASSERT(iterator);
1115 
1116 	return ((void *)((cl_pool_obj_t *) iterator)->p_object);
1117 }
1118 
1119 /*
1120 * PARAMETERS
1121 *	iterator
1122 *		[in] cl_list_iterator_t returned by a previous call to cl_list_head,
1123 *		cl_list_tail, cl_list_next, or cl_list_prev whose object is requested.
1124 *
1125 * RETURN VALUE
1126 *	Pointer to the object associated with the list iterator specified
1127 *	by the iterator parameter.
1128 *
1129 * SEE ALSO
1130 *	List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev
1131 *********/
1132 
1133 /****f* Component Library: List/cl_list_find_from_head
1134 * NAME
1135 *	cl_list_find_from_head
1136 *
1137 * DESCRIPTION
1138 *	The cl_list_find_from_head function uses a specified function
1139 *	to search for an object starting from the head of a list.
1140 *
1141 * SYNOPSIS
1142 */
1143 cl_list_iterator_t
1144 cl_list_find_from_head(IN const cl_list_t * const p_list,
1145 		       IN cl_pfn_list_find_t pfn_func,
1146 		       IN const void *const context);
1147 /*
1148 * PARAMETERS
1149 *	p_list
1150 *		[in] Pointer to a cl_list_t structure to search.
1151 *
1152 *	pfn_func
1153 *		[in] Function invoked to determine if a match was found.
1154 *		See the cl_pfn_list_find_t function type declaration for details
1155 *		about the callback function.
1156 *
1157 *	context
1158 *		[in] Value to pass to the callback functions to provide context.
1159 *
1160 * RETURN VALUES
1161 *	Returns the iterator for the object if found.
1162 *
1163 *	Returns the iterator for the list end otherwise.
1164 *
1165 * NOTES
1166 *	cl_list_find_from_head does not remove the found object from
1167 *	the list.  The iterator for the object is returned when the function
1168 *	provided by the pfn_func parameter returns CL_SUCCESS.  The function
1169 *	specified by the pfn_func parameter must not perform any list
1170 *	operations as these would corrupt the list.
1171 *
1172 * SEE ALSO
1173 *	List, cl_list_find_from_tail, cl_list_apply_func_t,
1174 *	cl_pfn_list_find_t
1175 *********/
1176 
1177 /****f* Component Library: List/cl_list_find_from_tail
1178 * NAME
1179 *	cl_list_find_from_tail
1180 *
1181 * DESCRIPTION
1182 *	The cl_list_find_from_tail function uses a specified function
1183 *	to search for an object starting from the tail of a list.
1184 *
1185 * SYNOPSIS
1186 */
1187 cl_list_iterator_t
1188 cl_list_find_from_tail(IN const cl_list_t * const p_list,
1189 		       IN cl_pfn_list_find_t pfn_func,
1190 		       IN const void *const context);
1191 /*
1192 * PARAMETERS
1193 *	p_list
1194 *		[in] Pointer to a cl_list_t structure to search.
1195 *
1196 *	pfn_func
1197 *		[in] Function invoked to determine if a match was found.
1198 *		See the cl_pfn_list_find_t function type declaration for details
1199 *		about the callback function.
1200 *
1201 *	context
1202 *		[in] Value to pass to the callback functions to provide context.
1203 *
1204 * RETURN VALUES
1205 *	Returns the iterator for the object if found.
1206 *
1207 *	Returns the iterator for the list end otherwise.
1208 *
1209 * NOTES
1210 *	cl_list_find_from_tail does not remove the found object from
1211 *	the list.  The iterator for the object is returned when the function
1212 *	provided by the pfn_func parameter returns CL_SUCCESS.  The function
1213 *	specified by the pfn_func parameter must not perform any list
1214 *	operations as these would corrupt the list.
1215 *
1216 * SEE ALSO
1217 *	List, cl_list_find_from_head, cl_list_apply_func_t,
1218 *	cl_pfn_list_find_t
1219 *********/
1220 
1221 /****f* Component Library: List/cl_list_apply_func
1222 * NAME
1223 *	cl_list_apply_func
1224 *
1225 * DESCRIPTION
1226 *	The cl_list_apply_func function executes a specified function for every
1227 *	object stored in a list.
1228 *
1229 * SYNOPSIS
1230 */
1231 void
1232 cl_list_apply_func(IN const cl_list_t * const p_list,
1233 		   IN cl_pfn_list_apply_t pfn_func,
1234 		   IN const void *const context);
1235 /*
1236 * PARAMETERS
1237 *	p_list
1238 *		[in] Pointer to a cl_list_t structure to iterate.
1239 *
1240 *	pfn_func
1241 *		[in] Function invoked for every item in a list.
1242 *		See the cl_pfn_list_apply_t function type declaration for details
1243 *		about the callback function.
1244 *
1245 *	context
1246 *		[in] Value to pass to the callback functions to provide context.
1247 *
1248 * RETURN VALUE
1249 *	This function does not return a value.
1250 *
1251 * NOTES
1252 *	cl_list_apply_func invokes the specified callback function for every
1253 *	object stored in the list, starting from the head.  The function specified
1254 *	by the pfn_func parameter must not perform any list operations as these
1255 *	would corrupt the list.
1256 *
1257 * SEE ALSO
1258 *	List, cl_list_find_from_head, cl_list_find_from_tail,
1259 *	cl_pfn_list_apply_t
1260 *********/
1261 
1262 /****f* Component Library: List/cl_list_count
1263 * NAME
1264 *	cl_list_count
1265 *
1266 * DESCRIPTION
1267 *	The cl_list_count function returns the number of objects stored in a list.
1268 *
1269 * SYNOPSIS
1270 */
1271 static inline size_t cl_list_count(IN const cl_list_t * const p_list)
1272 {
1273 	CL_ASSERT(p_list);
1274 	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
1275 
1276 	return (cl_qlist_count(&p_list->list));
1277 }
1278 
1279 /*
1280 * PARAMETERS
1281 *	p_list
1282 *		[in] Pointer to a cl_list_t structure whose object to count.
1283 *
1284 * RETURN VALUES
1285 *	Number of objects stored in the specified list.
1286 *
1287 * SEE ALSO
1288 *	List
1289 *********/
1290 
1291 END_C_DECLS
1292 #endif				/* _CL_LIST_H_ */
1293