| /* |
| * 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; |
| } |