Blame complib/cl_list.c

Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 2002-2005,2009 Mellanox Technologies LTD. All rights reserved.
Packit Service 54dbc3
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * This software is available to you under a choice of one of two
Packit Service 54dbc3
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit Service 54dbc3
 * General Public License (GPL) Version 2, available from the file
Packit Service 54dbc3
 * COPYING in the main directory of this source tree, or the
Packit Service 54dbc3
 * OpenIB.org BSD license below:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *     Redistribution and use in source and binary forms, with or
Packit Service 54dbc3
 *     without modification, are permitted provided that the following
Packit Service 54dbc3
 *     conditions are met:
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions of source code must retain the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 *      - Redistributions in binary form must reproduce the above
Packit Service 54dbc3
 *        copyright notice, this list of conditions and the following
Packit Service 54dbc3
 *        disclaimer in the documentation and/or other materials
Packit Service 54dbc3
 *        provided with the distribution.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit Service 54dbc3
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service 54dbc3
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit Service 54dbc3
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit Service 54dbc3
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit Service 54dbc3
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 54dbc3
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit Service 54dbc3
 * SOFTWARE.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
/*
Packit Service 54dbc3
 * Abstract:
Packit Service 54dbc3
 *	Implementation of quick list, and list.
Packit Service 54dbc3
 *
Packit Service 54dbc3
 */
Packit Service 54dbc3
Packit Service 54dbc3
#if HAVE_CONFIG_H
Packit Service 54dbc3
#  include <config.h>
Packit Service 54dbc3
#endif				/* HAVE_CONFIG_H */
Packit Service 54dbc3
Packit Service 54dbc3
#include <complib/cl_qlist.h>
Packit Service 54dbc3
#include <complib/cl_list.h>
Packit Service 54dbc3
Packit Service 54dbc3
#define FREE_ITEM_GROW_SIZE		10
Packit Service 54dbc3
Packit Service 54dbc3
/******************************************************************************
Packit Service 54dbc3
 IMPLEMENTATION OF QUICK LIST
Packit Service 54dbc3
******************************************************************************/
Packit Service 54dbc3
void cl_qlist_insert_array_head(IN cl_qlist_t * const p_list,
Packit Service 54dbc3
				IN cl_list_item_t * const p_array,
Packit Service 54dbc3
				IN uint32_t item_count,
Packit Service 54dbc3
				IN const uint32_t item_size)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(p_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_array);
Packit Service 54dbc3
	CL_ASSERT(item_size >= sizeof(cl_list_item_t));
Packit Service 54dbc3
	CL_ASSERT(item_count);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * To add items from the array to the list in the same order as
Packit Service 54dbc3
	 * the elements appear in the array, we add them starting with
Packit Service 54dbc3
	 * the last one first.  Locate the last item.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_item = (cl_list_item_t *) ((uint8_t *) p_array +
Packit Service 54dbc3
				     (item_size * (item_count - 1)));
Packit Service 54dbc3
Packit Service 54dbc3
	/* Continue to add all items to the list. */
Packit Service 54dbc3
	while (item_count--) {
Packit Service 54dbc3
		cl_qlist_insert_head(p_list, p_item);
Packit Service 54dbc3
Packit Service 54dbc3
		/* Get the next object to add to the list. */
Packit Service 54dbc3
		p_item = (cl_list_item_t *) ((uint8_t *) p_item - item_size);
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list,
Packit Service 54dbc3
				IN cl_list_item_t * const p_array,
Packit Service 54dbc3
				IN uint32_t item_count,
Packit Service 54dbc3
				IN const uint32_t item_size)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(p_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_array);
Packit Service 54dbc3
	CL_ASSERT(item_size >= sizeof(cl_list_item_t));
Packit Service 54dbc3
	CL_ASSERT(item_count);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Set the first item to add to the list. */
Packit Service 54dbc3
	p_item = p_array;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Continue to add all items to the list. */
Packit Service 54dbc3
	while (item_count--) {
Packit Service 54dbc3
		cl_qlist_insert_tail(p_list, p_item);
Packit Service 54dbc3
Packit Service 54dbc3
		/* Get the next object to add to the list. */
Packit Service 54dbc3
		p_item = (cl_list_item_t *) ((uint8_t *) p_item + item_size);
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list,
Packit Service 54dbc3
			       IN cl_qlist_t * const p_src_list)
Packit Service 54dbc3
{
Packit Service 54dbc3
#if defined( _DEBUG_ )
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
#endif
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_dest_list);
Packit Service 54dbc3
	CL_ASSERT(p_src_list);
Packit Service 54dbc3
	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Is the src list empty?
Packit Service 54dbc3
	 * We must have this check here for code below to work.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (cl_is_qlist_empty(p_src_list))
Packit Service 54dbc3
		return;
Packit Service 54dbc3
Packit Service 54dbc3
#if defined( _DEBUG_ )
Packit Service 54dbc3
	/* Check that all items in the source list belong there. */
Packit Service 54dbc3
	p_item = cl_qlist_head(p_src_list);
Packit Service 54dbc3
	while (p_item != cl_qlist_end(p_src_list)) {
Packit Service 54dbc3
		/* All list items in the source list must point to it. */
Packit Service 54dbc3
		CL_ASSERT(p_item->p_list == p_src_list);
Packit Service 54dbc3
		/* Point them all to the destination list. */
Packit Service 54dbc3
		p_item->p_list = p_dest_list;
Packit Service 54dbc3
		p_item = cl_qlist_next(p_item);
Packit Service 54dbc3
	}
Packit Service 54dbc3
#endif
Packit Service 54dbc3
Packit Service 54dbc3
	/* Chain the destination list to the tail of the source list. */
Packit Service 54dbc3
	cl_qlist_tail(p_src_list)->p_next = cl_qlist_head(p_dest_list);
Packit Service 54dbc3
	cl_qlist_head(p_dest_list)->p_prev = cl_qlist_tail(p_src_list);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Update the head of the destination list to the head of
Packit Service 54dbc3
	 * the source list.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_dest_list->end.p_next = cl_qlist_head(p_src_list);
Packit Service 54dbc3
	cl_qlist_head(p_src_list)->p_prev = &p_dest_list->end;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Update the count of the destination to reflect the source items having
Packit Service 54dbc3
	 * been added.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_dest_list->count += p_src_list->count;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Update source list to reflect being empty. */
Packit Service 54dbc3
	__cl_qlist_reset(p_src_list);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list,
Packit Service 54dbc3
			       IN cl_qlist_t * const p_src_list)
Packit Service 54dbc3
{
Packit Service 54dbc3
#if defined( _DEBUG_ )
Packit Service 54dbc3
	cl_list_item_t *p_item;
Packit Service 54dbc3
#endif
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_dest_list);
Packit Service 54dbc3
	CL_ASSERT(p_src_list);
Packit Service 54dbc3
	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Is the src list empty?
Packit Service 54dbc3
	 * We must have this check here for code below to work.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	if (cl_is_qlist_empty(p_src_list))
Packit Service 54dbc3
		return;
Packit Service 54dbc3
Packit Service 54dbc3
#if defined( _DEBUG_ )
Packit Service 54dbc3
	/* Check that all items in the source list belong there. */
Packit Service 54dbc3
	p_item = cl_qlist_head(p_src_list);
Packit Service 54dbc3
	while (p_item != cl_qlist_end(p_src_list)) {
Packit Service 54dbc3
		/* All list items in the source list must point to it. */
Packit Service 54dbc3
		CL_ASSERT(p_item->p_list == p_src_list);
Packit Service 54dbc3
		/* Point them all to the destination list. */
Packit Service 54dbc3
		p_item->p_list = p_dest_list;
Packit Service 54dbc3
		p_item = cl_qlist_next(p_item);
Packit Service 54dbc3
	}
Packit Service 54dbc3
#endif
Packit Service 54dbc3
Packit Service 54dbc3
	/* Chain the source list to the tail of the destination list. */
Packit Service 54dbc3
	cl_qlist_tail(p_dest_list)->p_next = cl_qlist_head(p_src_list);
Packit Service 54dbc3
	cl_qlist_head(p_src_list)->p_prev = cl_qlist_tail(p_dest_list);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Update the tail of the destination list to the tail of
Packit Service 54dbc3
	 * the source list.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_dest_list->end.p_prev = cl_qlist_tail(p_src_list);
Packit Service 54dbc3
	cl_qlist_tail(p_src_list)->p_next = &p_dest_list->end;
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * Update the count of the destination to reflect the source items having
Packit Service 54dbc3
	 * been added.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_dest_list->count += p_src_list->count;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Update source list to reflect being empty. */
Packit Service 54dbc3
	__cl_qlist_reset(p_src_list);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
boolean_t cl_is_item_in_qlist(IN const cl_qlist_t * const p_list,
Packit Service 54dbc3
			      IN const cl_list_item_t * const p_list_item)
Packit Service 54dbc3
{
Packit Service 54dbc3
	const cl_list_item_t *p_temp;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(p_list_item);
Packit Service 54dbc3
	CL_ASSERT(p_list->state == CL_INITIALIZED);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Traverse looking for a match */
Packit Service 54dbc3
	p_temp = cl_qlist_head(p_list);
Packit Service 54dbc3
	while (p_temp != cl_qlist_end(p_list)) {
Packit Service 54dbc3
		if (p_temp == p_list_item) {
Packit Service 54dbc3
			CL_ASSERT(p_list_item->p_list == p_list);
Packit Service 54dbc3
			return (TRUE);
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		p_temp = cl_qlist_next(p_temp);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	return (FALSE);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_list_item_t *cl_qlist_find_next(IN const cl_qlist_t * const p_list,
Packit Service 54dbc3
				   IN const cl_list_item_t * const p_list_item,
Packit Service 54dbc3
				   IN cl_pfn_qlist_find_t pfn_func,
Packit Service 54dbc3
				   IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_found_item;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(p_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_list_item);
Packit Service 54dbc3
	CL_ASSERT(p_list_item->p_list == p_list);
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	p_found_item = cl_qlist_next(p_list_item);
Packit Service 54dbc3
Packit Service 54dbc3
	/* The user provided a compare function */
Packit Service 54dbc3
	while (p_found_item != cl_qlist_end(p_list)) {
Packit Service 54dbc3
		CL_ASSERT(p_found_item->p_list == p_list);
Packit Service 54dbc3
Packit Service 54dbc3
		if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS)
Packit Service 54dbc3
			break;
Packit Service 54dbc3
Packit Service 54dbc3
		p_found_item = cl_qlist_next(p_found_item);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* No match */
Packit Service 54dbc3
	return (p_found_item);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_list_item_t *cl_qlist_find_prev(IN const cl_qlist_t * const p_list,
Packit Service 54dbc3
				   IN const cl_list_item_t * const p_list_item,
Packit Service 54dbc3
				   IN cl_pfn_qlist_find_t pfn_func,
Packit Service 54dbc3
				   IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_found_item;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(p_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_list_item);
Packit Service 54dbc3
	CL_ASSERT(p_list_item->p_list == p_list);
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	p_found_item = cl_qlist_prev(p_list_item);
Packit Service 54dbc3
Packit Service 54dbc3
	/* The user provided a compare function */
Packit Service 54dbc3
	while (p_found_item != cl_qlist_end(p_list)) {
Packit Service 54dbc3
		CL_ASSERT(p_found_item->p_list == p_list);
Packit Service 54dbc3
Packit Service 54dbc3
		if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS)
Packit Service 54dbc3
			break;
Packit Service 54dbc3
Packit Service 54dbc3
		p_found_item = cl_qlist_prev(p_found_item);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* No match */
Packit Service 54dbc3
	return (p_found_item);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_qlist_apply_func(IN const cl_qlist_t * const p_list,
Packit Service 54dbc3
			 IN cl_pfn_qlist_apply_t pfn_func,
Packit Service 54dbc3
			 IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_list_item;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Note that context can have any arbitrary value. */
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(p_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	p_list_item = cl_qlist_head(p_list);
Packit Service 54dbc3
	while (p_list_item != cl_qlist_end(p_list)) {
Packit Service 54dbc3
		pfn_func(p_list_item, (void *)context);
Packit Service 54dbc3
		p_list_item = cl_qlist_next(p_list_item);
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_qlist_move_items(IN cl_qlist_t * const p_src_list,
Packit Service 54dbc3
			 IN cl_qlist_t * const p_dest_list,
Packit Service 54dbc3
			 IN cl_pfn_qlist_find_t pfn_func,
Packit Service 54dbc3
			 IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_current_item, *p_next;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_src_list);
Packit Service 54dbc3
	CL_ASSERT(p_dest_list);
Packit Service 54dbc3
	CL_ASSERT(p_src_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(p_dest_list->state == CL_INITIALIZED);
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	p_current_item = cl_qlist_head(p_src_list);
Packit Service 54dbc3
Packit Service 54dbc3
	while (p_current_item != cl_qlist_end(p_src_list)) {
Packit Service 54dbc3
		/* Before we do anything, get a pointer to the next item. */
Packit Service 54dbc3
		p_next = cl_qlist_next(p_current_item);
Packit Service 54dbc3
Packit Service 54dbc3
		if (pfn_func(p_current_item, (void *)context) == CL_SUCCESS) {
Packit Service 54dbc3
			/* Move the item from one list to the other. */
Packit Service 54dbc3
			cl_qlist_remove_item(p_src_list, p_current_item);
Packit Service 54dbc3
			cl_qlist_insert_tail(p_dest_list, p_current_item);
Packit Service 54dbc3
		}
Packit Service 54dbc3
		p_current_item = p_next;
Packit Service 54dbc3
	}
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
/******************************************************************************
Packit Service 54dbc3
 IMPLEMENTATION OF LIST
Packit Service 54dbc3
******************************************************************************/
Packit Service 54dbc3
void cl_list_construct(IN cl_list_t * const p_list)
Packit Service 54dbc3
{
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qpool_construct(&p_list->list_item_pool);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_status_t cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items)
Packit Service 54dbc3
{
Packit Service 54dbc3
	uint32_t grow_size;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	cl_qlist_init(&p_list->list);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * We will grow by min_items/8 items at a time, with a minimum of
Packit Service 54dbc3
	 * FREE_ITEM_GROW_SIZE.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	grow_size = (uint32_t) min_items >> 3;
Packit Service 54dbc3
	if (grow_size < FREE_ITEM_GROW_SIZE)
Packit Service 54dbc3
		grow_size = FREE_ITEM_GROW_SIZE;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Initialize the pool of list items. */
Packit Service 54dbc3
	return (cl_qpool_init(&p_list->list_item_pool, min_items, 0, grow_size,
Packit Service 54dbc3
			      sizeof(cl_pool_obj_t), NULL, NULL, NULL));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_list_destroy(IN cl_list_t * const p_list)
Packit Service 54dbc3
{
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
Packit Service 54dbc3
	cl_qpool_destroy(&p_list->list_item_pool);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
static cl_status_t cl_list_find_cb(IN const cl_list_item_t * const p_list_item,
Packit Service 54dbc3
				   IN void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	CL_ASSERT(p_list_item);
Packit Service 54dbc3
Packit Service 54dbc3
	if (cl_list_obj(p_list_item) == context)
Packit Service 54dbc3
		return (CL_SUCCESS);
Packit Service 54dbc3
Packit Service 54dbc3
	return (CL_NOT_FOUND);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_status_t cl_list_remove_object(IN cl_list_t * const p_list,
Packit Service 54dbc3
				  IN const void *const p_object)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_item_t *p_list_item;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
Packit Service 54dbc3
	/* find the item in question */
Packit Service 54dbc3
	p_list_item =
Packit Service 54dbc3
	    cl_qlist_find_from_head(&p_list->list, cl_list_find_cb, p_object);
Packit Service 54dbc3
	if (p_list_item != cl_qlist_end(&p_list->list)) {
Packit Service 54dbc3
		/* remove this item */
Packit Service 54dbc3
		cl_qlist_remove_item(&p_list->list, p_list_item);
Packit Service 54dbc3
		cl_qpool_put(&p_list->list_item_pool,
Packit Service 54dbc3
			     (cl_pool_item_t *) p_list_item);
Packit Service 54dbc3
		return (CL_SUCCESS);
Packit Service 54dbc3
	}
Packit Service 54dbc3
	return (CL_NOT_FOUND);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
boolean_t cl_is_object_in_list(IN const cl_list_t * const p_list,
Packit Service 54dbc3
			       IN const void *const p_object)
Packit Service 54dbc3
{
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
Packit Service 54dbc3
	return (cl_qlist_find_from_head
Packit Service 54dbc3
		(&p_list->list, cl_list_find_cb, p_object)
Packit Service 54dbc3
		!= cl_qlist_end(&p_list->list));
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_status_t cl_list_insert_array_head(IN cl_list_t * const p_list,
Packit Service 54dbc3
				      IN const void *const p_array,
Packit Service 54dbc3
				      IN uint32_t item_count,
Packit Service 54dbc3
				      IN const uint32_t item_size)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_status_t status;
Packit Service 54dbc3
	void *p_object;
Packit Service 54dbc3
	uint32_t items_remain = item_count;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
	CL_ASSERT(p_array);
Packit Service 54dbc3
	CL_ASSERT(item_size);
Packit Service 54dbc3
	CL_ASSERT(item_count);
Packit Service 54dbc3
Packit Service 54dbc3
	/*
Packit Service 54dbc3
	 * To add items from the array to the list in the same order as
Packit Service 54dbc3
	 * the elements appear in the array, we add them starting with
Packit Service 54dbc3
	 * the last one first.  Locate the last item.
Packit Service 54dbc3
	 */
Packit Service 54dbc3
	p_object = ((uint8_t *) p_array + (item_size * (item_count - 1)));
Packit Service 54dbc3
Packit Service 54dbc3
	/* Continue to add all items to the list. */
Packit Service 54dbc3
	while (items_remain--) {
Packit Service 54dbc3
		status = cl_list_insert_head(p_list, p_object);
Packit Service 54dbc3
		if (status != CL_SUCCESS) {
Packit Service 54dbc3
			/* Remove all items that have been inserted. */
Packit Service 54dbc3
			while (items_remain++ < (item_count - 1))
Packit Service 54dbc3
				cl_list_remove_head(p_list);
Packit Service 54dbc3
			return (status);
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* Get the next object to add to the list. */
Packit Service 54dbc3
		p_object = ((uint8_t *) p_object - item_size);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	return (CL_SUCCESS);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_status_t cl_list_insert_array_tail(IN cl_list_t * const p_list,
Packit Service 54dbc3
				      IN const void *const p_array,
Packit Service 54dbc3
				      IN uint32_t item_count,
Packit Service 54dbc3
				      IN const uint32_t item_size)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_status_t status;
Packit Service 54dbc3
	void *p_object;
Packit Service 54dbc3
	uint32_t items_remain = item_count;
Packit Service 54dbc3
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
	CL_ASSERT(p_array);
Packit Service 54dbc3
	CL_ASSERT(item_size);
Packit Service 54dbc3
	CL_ASSERT(item_count);
Packit Service 54dbc3
Packit Service 54dbc3
	/* Set the first item to add to the list. */
Packit Service 54dbc3
	p_object = (void *)p_array;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Continue to add all items to the list. */
Packit Service 54dbc3
	while (items_remain--) {
Packit Service 54dbc3
		status = cl_list_insert_tail(p_list, p_object);
Packit Service 54dbc3
		if (status != CL_SUCCESS) {
Packit Service 54dbc3
			/* Remove all items that have been inserted. */
Packit Service 54dbc3
			while (items_remain++ < (item_count - 1))
Packit Service 54dbc3
				cl_list_remove_tail(p_list);
Packit Service 54dbc3
			return (status);
Packit Service 54dbc3
		}
Packit Service 54dbc3
Packit Service 54dbc3
		/* Get the next object to add to the list. */
Packit Service 54dbc3
		p_object = ((uint8_t *) p_object + item_size);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	return (CL_SUCCESS);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_list_iterator_t cl_list_find_from_head(IN const cl_list_t * const p_list,
Packit Service 54dbc3
					  IN cl_pfn_list_find_t pfn_func,
Packit Service 54dbc3
					  IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_status_t status;
Packit Service 54dbc3
	cl_list_iterator_t itor;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Note that context can have any arbitrary value. */
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	itor = cl_list_head(p_list);
Packit Service 54dbc3
Packit Service 54dbc3
	while (itor != cl_list_end(p_list)) {
Packit Service 54dbc3
		status = pfn_func(cl_list_obj(itor), (void *)context);
Packit Service 54dbc3
		if (status == CL_SUCCESS)
Packit Service 54dbc3
			break;
Packit Service 54dbc3
Packit Service 54dbc3
		itor = cl_list_next(itor);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* no match */
Packit Service 54dbc3
	return (itor);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
cl_list_iterator_t cl_list_find_from_tail(IN const cl_list_t * const p_list,
Packit Service 54dbc3
					  IN cl_pfn_list_find_t pfn_func,
Packit Service 54dbc3
					  IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_status_t status;
Packit Service 54dbc3
	cl_list_iterator_t itor;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Note that context can have any arbitrary value. */
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	itor = cl_list_tail(p_list);
Packit Service 54dbc3
Packit Service 54dbc3
	while (itor != cl_list_end(p_list)) {
Packit Service 54dbc3
		status = pfn_func(cl_list_obj(itor), (void *)context);
Packit Service 54dbc3
		if (status == CL_SUCCESS)
Packit Service 54dbc3
			break;
Packit Service 54dbc3
Packit Service 54dbc3
		itor = cl_list_prev(itor);
Packit Service 54dbc3
	}
Packit Service 54dbc3
Packit Service 54dbc3
	/* no match */
Packit Service 54dbc3
	return (itor);
Packit Service 54dbc3
}
Packit Service 54dbc3
Packit Service 54dbc3
void cl_list_apply_func(IN const cl_list_t * const p_list,
Packit Service 54dbc3
			IN cl_pfn_list_apply_t pfn_func,
Packit Service 54dbc3
			IN const void *const context)
Packit Service 54dbc3
{
Packit Service 54dbc3
	cl_list_iterator_t itor;
Packit Service 54dbc3
Packit Service 54dbc3
	/* Note that context can have any arbitrary value. */
Packit Service 54dbc3
	CL_ASSERT(p_list);
Packit Service 54dbc3
	CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool));
Packit Service 54dbc3
	CL_ASSERT(pfn_func);
Packit Service 54dbc3
Packit Service 54dbc3
	itor = cl_list_head(p_list);
Packit Service 54dbc3
Packit Service 54dbc3
	while (itor != cl_list_end(p_list)) {
Packit Service 54dbc3
		pfn_func(cl_list_obj(itor), (void *)context);
Packit Service 54dbc3
Packit Service 54dbc3
		itor = cl_list_next(itor);
Packit Service 54dbc3
	}
Packit Service 54dbc3
}