blob: 2ce881343bedc939719207e19f011eb33f0b235f [file] [log] [blame]
/*
* Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/**=============================================================================
vos_list.c
\brief
Description...
==============================================================================**/
/* $HEADER$ */
/**-----------------------------------------------------------------------------
Include files
----------------------------------------------------------------------------*/
#include <vos_list.h>
#include <vos_trace.h>
/**-----------------------------------------------------------------------------
Preprocessor definitions and constants
----------------------------------------------------------------------------*/
#define VOS_LIST_COOKIE 0xabadfeed
/**-----------------------------------------------------------------------------
Type declarations
----------------------------------------------------------------------------*/
/**-----------------------------------------------------------------------------
Function declarations and documenation
----------------------------------------------------------------------------*/
VOS_STATUS vos_list_init( vos_list_t *pList )
{
if ( pList == NULL)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie == VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: already initialized list", __func__);
return VOS_STATUS_E_BUSY;
}
mutex_init(&pList->lock);
INIT_LIST_HEAD( &pList->anchor );
pList->count = 0;
pList->cookie = VOS_LIST_COOKIE;
return( VOS_STATUS_SUCCESS );
}
VOS_STATUS vos_list_destroy( vos_list_t *pList )
{
int rc;
if (pList == NULL)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->count !=0 )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list length not equal to zero", __func__);
return VOS_STATUS_E_BUSY;
}
// clear the cookie. This indicates the list is destroyed.
pList->cookie = 0;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS vos_list_insert_front( vos_list_t *pList, vos_list_node_t *pNode )
{
int rc;
if ( ( pList == NULL) || ( pNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
list_add( pNode, &pList->anchor );
pList->count++;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS vos_list_insert_back( vos_list_t *pList, vos_list_node_t *pNode )
{
int rc;
if ( ( pList == NULL) || ( pNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
list_add_tail( pNode, &pList->anchor );
pList->count++;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS vos_list_insert_back_size( vos_list_t *pList, vos_list_node_t *pNode, v_SIZE_t *pSize )
{
int rc;
if ( ( pList == NULL) || ( pNode == NULL) || (pSize == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
list_add_tail( pNode, &pList->anchor );
pList->count++;
*pSize = pList->count;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS vos_list_remove_front( vos_list_t *pList, vos_list_node_t **ppNode )
{
struct list_head * listptr;
int rc;
// the assumption here is that pList is the head of the list (dummy
// node) and points to first and last element in circular linked list
if ( ( pList == NULL ) || ( ppNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty( &pList->anchor ) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO_HIGH,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
listptr = pList->anchor.next;
*ppNode = listptr;
list_del(pList->anchor.next);
pList->count--;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS vos_list_remove_back( vos_list_t *pList, vos_list_node_t **ppNode )
{
struct list_head * listptr;
int rc;
// the assumption here is that pList is the head of the list (dummy node) and points to first and
// last element in circular linked list
if ( ( pList == NULL ) || ( ppNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty( &pList->anchor ) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
listptr = pList->anchor.prev;
*ppNode = listptr;
list_del(pList->anchor.prev);
pList->count--;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
VOS_STATUS vos_list_size( vos_list_t *pList, v_SIZE_t *pSize )
{
int rc;
if ( ( pList ==NULL) || ( pSize == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
*pSize = pList->count;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_peek_front() - peek at the node at front of a linked list
The vos_list_peek_front() API will return a pointer to the node at the
front of a properly initialized vOS List object. The node will *not* be
removed from the list.
\param pList - Pointer to list object of the list to be 'peeked'
\param ppNode - Pointer to a pointer to the list node that exists at
the front of the list.
\return VOS_STATUS_SUCCESS - list node at the front of the list was
successfully returned.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be
removed.
VOS_STATUS_E_FAULT - pList or or ppNode is an invalid pointer.
\sa vos_list_remove_back()
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_peek_front( vos_list_t *pList, vos_list_node_t **ppNode )
{
struct list_head * listptr;
int rc;
if ( ( pList == NULL) || ( ppNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
listptr = pList->anchor.next;
*ppNode = listptr;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_peek_back() - peek at the node at back of a linked list
The vos_list_peek_back() API will return a pointer to the node at the
back of a properly initialized vOS List object. The node will *not* be
removed from the list.
\param pList - Pointer to list object of the list to be 'peeked'
\param ppNode - Pointer to a pointer to the list node that exists at
the back of the list.
\return VOS_STATUS_SUCCESS - list node at the back of the list was
successfully returned.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be
removed.
VOS_STATUS_E_FAULT - pList or or ppNode is an invalid pointer.
\sa vos_list_peek_back(), vos_list_remove_back(), vos_list_peek_front(),
vos_list_remove_front()
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_peek_back( vos_list_t *pList, vos_list_node_t **ppNode )
{
struct list_head * listptr;
int rc;
if ( ( pList == NULL) || ( ppNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
listptr = pList->anchor.prev;
*ppNode = listptr;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_peek_next() - peek at the node after the specified node
The vos_list_peek_next() API will return a pointer to the node following the
specified node on a properly initialized vOS List object. The node will
*not* be removed from the list.
\param pList - Pointer to list object of the list to be 'peeked'
\param pNode - Pointer to the node that is being 'peeked'
\param ppNode - Pointer to a pointer to the list node that follows the
pNode node on the list.
\return VOS_STATUS_SUCCESS - list node following pNode on the properly
initialized list is successfully returned.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_EMPTY - There is no 'next' node (the input node is
at the back of the list).
VOS_STATUS_E_FAULT - pList, pNode or ppNode is an invalid pointer.
\sa vos_list_remove_back()
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_peek_next( vos_list_t *pList, vos_list_node_t *pNode,
vos_list_node_t **ppNode )
{
struct list_head * listptr;
int rc, found = 0;
vos_list_node_t *tmp;
if ( ( pList == NULL) || ( pNode == NULL) || (ppNode == NULL))
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
// verify that pNode is indeed part of list pList
list_for_each(tmp, &pList->anchor)
{
if (tmp == pNode)
{
found = 1;
break;
}
}
if (found == 0)
return VOS_STATUS_E_INVAL;
listptr = pNode->next;
if (listptr == &pList->anchor)
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
*ppNode = listptr;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_peek_prev() - peek at the node before the specified node
The vos_list_peek_prev() API will return a pointer to the node before the
specified node on a properly initialized vOS List object. The node will
*not* be removed from the list.
\param pList - Pointer to list object of the list to be 'peeked'
\param pNode - Pointer to the node that is being 'peeked'
\param ppNode - Pointer to a pointer to the list node before the
pNode node on the list.
\return VOS_STATUS_SUCCESS - list node before pNode on the properly
initialized list is successfully returned.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_EMPTY - There is no 'previous' node (the input node is
at the front of the list).
VOS_STATUS_E_FAULT - pList, pNode or ppNode is an invalid pointer.
\sa vos_list_remove_back()
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_peek_prev( vos_list_t *pList, vos_list_node_t *pNode,
vos_list_node_t **ppNode )
{
struct list_head * listptr;
int rc, found = 0;
vos_list_node_t *tmp;
if ( ( pList == NULL) || ( pNode == NULL) || (ppNode == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
// verify that pNode is indeed part of list pList
list_for_each(tmp, &pList->anchor)
{
if (tmp == pNode)
{
found = 1;
break;
}
}
if (found == 0)
return VOS_STATUS_E_INVAL;
listptr = pNode->prev;
if (listptr == &pList->anchor)
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_WARN,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
*ppNode = listptr;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_insert_before() - insert node at front of a specified
list node
The vos_list_insert_before() API will insert a node onto a properly
initialized vOS List object in front of the specified list node.
\param pList - Pointer to list object where the node will be inserted
\param pNodeToInsert - Pointer to the list node to be inserted into the list.
\param pNode - Pointer to the list node where pNodeToInsert will be inserted
in front of.
\return VOS_STATUS_SUCCESS - list node was successfully inserted onto
the front of the list.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_FAULT - pList, pNodeToInsert, or pNode are
invalid pointer(s)
\sa
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_insert_before( vos_list_t *pList, vos_list_node_t *pNodeToInsert,
vos_list_node_t *pNode )
{
int rc, found = 0;
vos_list_node_t *tmp;
if ( ( pList == NULL) || ( pNode == NULL) || (pNodeToInsert == NULL))
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
// verify that pNode is indeed part of list pList
list_for_each(tmp, &pList->anchor)
{
if (tmp == pNode)
{
found = 1;
break;
}
}
if (found == 0)
return VOS_STATUS_E_INVAL;
list_add(pNodeToInsert, pNode);
pList->count++;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_insert_after() - insert node behind a specified list node
The vos_list_insert_after() API will insert a node onto a properly
initialized vOS List object after the specified list node.
\param pList - Pointer to list object where the node will be inserted
\param pNodeToInsert - Pointer to the list node to be inserted into the list.
\param pNode - Pointer to the list node where pNodeToInsert will be inserted
after.
\return VOS_STATUS_SUCCESS - list node was successfully inserted onto
the front of the list.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_FAULT - pList, pNodeToInsert, or pNode are
invalid pointer(s)
\sa
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_insert_after( vos_list_t *pList, vos_list_node_t *pNodeToInsert,
vos_list_node_t *pNode )
{
int rc, found = 0;
vos_list_node_t *tmp;
if ( ( pList == NULL) || ( pNode == NULL) || (pNodeToInsert == NULL))
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
// verify that pNode is indeed part of list pList
list_for_each(tmp, &pList->anchor)
{
if (tmp == pNode)
{
found = 1;
break;
}
}
if (found == 0)
return VOS_STATUS_E_INVAL;
list_add_tail(pNodeToInsert, pNode);
pList->count++;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}
/*----------------------------------------------------------------------------
\brief vos_list_remove_node() - remove specified node from vOS list list
The vos_list_remove_node() API will remove a specified node from the
properly initialized vOS List object.
\param pList - Pointer to list object where the node will be removed
\param ppNode - Pointer to the node to be removed from the list.
\return VOS_STATUS_SUCCESS - list node was successfully removed from
the list.
VOS_STATUS_E_INVAL - The value specified by pList is not a valid,
initialized list object.
VOS_STATUS_E_EMPTY - The specified is empty so nodes cannot be
removed.
VOS_STATUS_E_FAULT - pList or pNodeToRemove is not a valid pointer
\sa
--------------------------------------------------------------------------*/
VOS_STATUS vos_list_remove_node( vos_list_t *pList, vos_list_node_t *pNodeToRemove )
{
int rc, found = 0;
vos_list_node_t *tmp;
if ( ( pList == NULL ) || ( pNodeToRemove == NULL) )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: NULL pointer passed in", __func__);
return VOS_STATUS_E_FAULT;
}
if ( pList->cookie != VOS_LIST_COOKIE )
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list not initialized", __func__);
VOS_ASSERT(0);
return VOS_STATUS_E_INVAL;
}
rc = mutex_lock_interruptible(&pList->lock);
if (rc)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: unable to lock list", __func__);
return VOS_STATUS_E_FAULT;
}
if ( list_empty(&pList->anchor) )
{
mutex_unlock(&pList->lock);
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"%s: list empty", __func__);
return VOS_STATUS_E_EMPTY;
}
// verify that pNodeToRemove is indeed part of list pList
list_for_each(tmp, &pList->anchor)
{
if (tmp == pNodeToRemove)
{
found = 1;
break;
}
}
if (found == 0)
return VOS_STATUS_E_INVAL;
list_del(pNodeToRemove);
pList->count--;
mutex_unlock(&pList->lock);
return VOS_STATUS_SUCCESS;
}