summaryrefslogtreecommitdiff
path: root/wilink_6_1/utils/queue.c
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2009-05-12 12:22:02 -0700
committerDmitry Shmidt <dimitrysh@google.com>2009-05-12 12:22:02 -0700
commit981801b95b81e6d1c7a2085967406e86af0f08fc (patch)
tree3cf403b311a43d23c0b605827913f9637b136763 /wilink_6_1/utils/queue.c
parent02d7515eca810acbc93be9324751d712af6d38c7 (diff)
downloadti-981801b95b81e6d1c7a2085967406e86af0f08fc.tar.gz
Initial code package of WiLink_Driver_6.1.0.0.84
Diffstat (limited to 'wilink_6_1/utils/queue.c')
-rw-r--r--wilink_6_1/utils/queue.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/wilink_6_1/utils/queue.c b/wilink_6_1/utils/queue.c
new file mode 100644
index 0000000..2ce3fbc
--- /dev/null
+++ b/wilink_6_1/utils/queue.c
@@ -0,0 +1,414 @@
+/*
+ * queue.c
+ *
+ * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Texas Instruments nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+/** \file queue.c
+ * \brief This module provides generic queueing services, including enqueue, dequeue
+ * and requeue of any object that contains TQueNodeHdr in its structure.
+ *
+ * \see queue.h
+ */
+
+
+
+#define __FILE_ID__ FILE_ID_130
+#include "report.h"
+#include "queue.h"
+
+
+/* Queue structure */
+typedef struct
+{
+ TQueNodeHdr tHead; /* The queue first node */
+ TI_UINT32 uCount; /* Current number of nodes in queue */
+ TI_UINT32 uLimit; /* Upper limit of nodes in queue */
+ TI_UINT32 uMaxCount; /* Maximum uCount value (for debug) */
+ TI_UINT32 uOverflow; /* Number of overflow occurences - couldn't insert node (for debug) */
+ TI_UINT32 uNodeHeaderOffset; /* Offset of NodeHeader field from the entry of the queued item */
+ TI_HANDLE hOs;
+ TI_HANDLE hReport;
+} TQueue;
+
+
+
+/*
+ * INTERNAL FUNCTIONS
+ * ===============================
+ */
+
+
+/*
+ * InsertNode(): Insert new node between pPrev and pNext
+ */
+static INLINE void InsertNode( TQueNodeHdr *pNode, TQueNodeHdr *pPrev, TQueNodeHdr *pNext)
+{
+ pNext->pPrev = pNode;
+ pNode->pNext = pNext;
+ pNode->pPrev = pPrev;
+ pPrev->pNext = pNode;
+}
+
+/*
+ * RemoveNode(): Remove node from between pPrev and pNext
+ */
+static INLINE void RemoveNode( TQueNodeHdr *pPrev, TQueNodeHdr *pNext)
+{
+ pNext->pPrev = pPrev;
+ pPrev->pNext = pNext;
+}
+
+/*
+ * AddToHead(): Add node to queue head (last in queue)
+ */
+static INLINE void AddToHead( TQueNodeHdr *pNode, TQueNodeHdr *pListHead)
+{
+ InsertNode (pNode, pListHead, pListHead->pNext);
+}
+
+/*
+ * AddToTail(): Add node to queue tail (first in queue)
+ */
+static INLINE void AddToTail( TQueNodeHdr *pNode, TQueNodeHdr *pListHead)
+{
+ InsertNode( pNode, pListHead->pPrev, pListHead );
+}
+
+/*
+ * DelFromTail(): Delete node from queue tail (first in queue)
+ */
+static INLINE void DelFromTail (TQueNodeHdr *pNode)
+{
+ RemoveNode (pNode->pPrev, pNode->pNext);
+}
+
+
+
+/*
+ * EXTERNAL FUNCTIONS
+ * ===============================
+ */
+
+
+/**
+ * \fn que_Create
+ * \brief Create a queue.
+ *
+ * Allocate and init a queue object.
+ *
+ * \note
+ * \param hOs - Handle to Os Abstraction Layer
+ * \param hReport - Handle to report module
+ * \param uLimit - Maximum items to store in queue
+ * \param uNodeHeaderOffset - Offset of NodeHeader field from the entry of the queued item.
+ * \return Handle to the allocated queue
+ * \sa que_Destroy
+ */
+TI_HANDLE que_Create (TI_HANDLE hOs, TI_HANDLE hReport, TI_UINT32 uLimit, TI_UINT32 uNodeHeaderOffset)
+{
+ TQueue *pQue;
+
+ /* allocate queue module */
+ pQue = os_memoryAlloc (hOs, sizeof(TQueue));
+
+ if (!pQue)
+ {
+ WLAN_OS_REPORT (("Error allocating the Queue Module\n"));
+ return NULL;
+ }
+
+ os_memoryZero (hOs, pQue, sizeof(TQueue));
+
+ /* Intialize the queue header */
+ pQue->tHead.pNext = pQue->tHead.pPrev = &pQue->tHead;
+
+ /* Set the Queue parameters */
+ pQue->hOs = hOs;
+ pQue->hReport = hReport;
+ pQue->uLimit = uLimit;
+ pQue->uNodeHeaderOffset = uNodeHeaderOffset;
+
+ return (TI_HANDLE)pQue;
+}
+
+
+/**
+ * \fn que_Destroy
+ * \brief Destroy the queue.
+ *
+ * Free the queue memory.
+ *
+ * \note The queue's owner should first free the queued items!
+ * \param hQue - The queue object
+ * \return TI_OK on success or TI_NOK on failure
+ * \sa que_Create
+ */
+TI_STATUS que_Destroy (TI_HANDLE hQue)
+{
+ TQueue *pQue = (TQueue *)hQue;
+
+ /* Alert if the queue is unloaded before it was cleared from items */
+ if (pQue->uCount)
+ {
+ TRACE0(pQue->hReport, REPORT_SEVERITY_ERROR, "que_Destroy() Queue Not Empty!!");
+ }
+ /* free Queue object */
+ os_memoryFree (pQue->hOs, pQue, sizeof(TQueue));
+
+ return TI_OK;
+}
+
+
+/**
+ * \fn que_Init
+ * \brief Init required handles
+ *
+ * Init required handles.
+ *
+ * \note
+ * \param hQue - The queue object
+ * \param hOs - Handle to Os Abstraction Layer
+ * \param hReport - Handle to report module
+ * \return TI_OK on success or TI_NOK on failure
+ * \sa
+ */
+TI_STATUS que_Init (TI_HANDLE hQue, TI_HANDLE hOs, TI_HANDLE hReport)
+{
+ TQueue *pQue = (TQueue *)hQue;
+
+ pQue->hOs = hOs;
+ pQue->hReport = hReport;
+
+ return TI_OK;
+}
+
+
+/**
+ * \fn que_Enqueue
+ * \brief Enqueue an item
+ *
+ * Enqueue an item at the queue's head (last in queue).
+ *
+ * \note
+ * \param hQue - The queue object
+ * \param hItem - Handle to queued item
+ * \return TI_OK if item was queued, or TI_NOK if not queued due to overflow
+ * \sa que_Dequeue, que_Requeue
+ */
+TI_STATUS que_Enqueue (TI_HANDLE hQue, TI_HANDLE hItem)
+{
+ TQueue *pQue = (TQueue *)hQue;
+ TQueNodeHdr *pQueNodeHdr; /* the Node-Header in the given item */
+
+
+ /* Check queue limit */
+ if(pQue->uCount < pQue->uLimit)
+ {
+ /* Find NodeHeader in the given item */
+ pQueNodeHdr = (TQueNodeHdr *)((TI_UINT8*)hItem + pQue->uNodeHeaderOffset);
+
+ #if 0
+ /* Check that (pNext == NULL) --> Sanity check that this item was dequeued before */
+ if (pQueNodeHdr->pNext)
+ {
+ TRACE0(pQue->hReport, REPORT_SEVERITY_ERROR, "que_Enqueue(): Trying to enqueue an item that wasn't dequeued!");
+ return TI_NOK;
+ }
+ #endif
+
+ /* Enqueue item and increment items counter */
+ AddToHead (pQueNodeHdr, &pQue->tHead);
+ pQue->uCount++;
+
+ #ifdef TI_DBG
+ if (pQue->uCount > pQue->uMaxCount)
+ {
+ pQue->uMaxCount = pQue->uCount;
+ }
+ TRACE0(pQue->hReport, REPORT_SEVERITY_INFORMATION , "que_Enqueue(): Enqueued Successfully\n");
+ #endif
+
+ return TI_OK;
+ }
+
+ /*
+ * Queue is overflowed, return TI_NOK.
+ */
+#ifdef TI_DBG
+ pQue->uOverflow++;
+TRACE0(pQue->hReport, REPORT_SEVERITY_WARNING , "que_Enqueue(): Queue Overflow\n");
+#endif
+
+ return TI_NOK;
+}
+
+
+/**
+ * \fn que_Dequeue
+ * \brief Dequeue an item
+ *
+ * Dequeue an item from the queue's tail (first in queue).
+ *
+ * \note
+ * \param hQue - The queue object
+ * \return pointer to dequeued item or NULL if queue is empty
+ * \sa que_Enqueue, que_Requeue
+ */
+TI_HANDLE que_Dequeue (TI_HANDLE hQue)
+{
+ TQueue *pQue = (TQueue *)hQue;
+ TI_HANDLE hItem;
+
+ if (pQue->uCount)
+ {
+ /* Queue is not empty, take packet from the queue tail */
+
+ /* find pointer to the node entry */
+ hItem = (TI_HANDLE)((TI_UINT8*)pQue->tHead.pPrev - pQue->uNodeHeaderOffset);
+
+ DelFromTail (pQue->tHead.pPrev); /* remove node from the queue */
+ pQue->uCount--;
+
+ #ifdef TI_DBG
+ /* Clear the pNext so we can do a sanity check when enqueuing this structre in the future */
+ ((TQueNodeHdr *)((TI_UINT8*)hItem + pQue->uNodeHeaderOffset))->pNext = NULL;
+ #endif
+
+ return (hItem);
+ }
+
+ /* Queue is empty */
+ TRACE0(pQue->hReport, REPORT_SEVERITY_INFORMATION , "que_Dequeue(): Queue is empty\n");
+ return NULL;
+}
+
+
+/**
+ * \fn que_Requeue
+ * \brief Requeue an item
+ *
+ * Requeue an item at the queue's tail (first in queue).
+ *
+ * \note
+ * \param hQue - The queue object
+ * \param hItem - Handle to queued item
+ * \return TI_OK if item was queued, or TI_NOK if not queued due to overflow
+ * \sa que_Enqueue, que_Dequeue
+ */
+TI_STATUS que_Requeue (TI_HANDLE hQue, TI_HANDLE hItem)
+{
+ TQueue *pQue = (TQueue *)hQue;
+ TQueNodeHdr *pQueNodeHdr; /* the NodeHeader in the given item */
+
+ /*
+ * If queue's limits not exceeded add the packet to queue's tail and return TI_OK
+ */
+ if (pQue->uCount < pQue->uLimit)
+ {
+ /* Find NodeHeader in the given item */
+ pQueNodeHdr = (TQueNodeHdr *)((TI_UINT8*)hItem + pQue->uNodeHeaderOffset);
+
+ /* Enqueue item and increment items counter */
+ AddToTail (pQueNodeHdr, &pQue->tHead);
+ pQue->uCount++;
+
+#ifdef TI_DBG
+ if (pQue->uCount > pQue->uMaxCount)
+ pQue->uMaxCount = pQue->uCount;
+TRACE0(pQue->hReport, REPORT_SEVERITY_INFORMATION , "que_Requeue(): Requeued successfully\n");
+#endif
+
+ return TI_OK;
+ }
+
+
+ /*
+ * Queue is overflowed, return TI_NOK.
+ * Note: This is not expected in the current design, since Tx packet may be requeued
+ * only right after it was dequeued in the same context so the queue can't be full.
+ */
+#ifdef TI_DBG
+ pQue->uOverflow++;
+TRACE0(pQue->hReport, REPORT_SEVERITY_ERROR , "que_Requeue(): Queue Overflow\n");
+#endif
+
+ return TI_NOK;
+}
+
+
+/**
+ * \fn que_Size
+ * \brief Return queue size
+ *
+ * Return number of items in queue.
+ *
+ * \note
+ * \param hQue - The queue object
+ * \return TI_UINT32 - the items count
+ * \sa
+ */
+TI_UINT32 que_Size (TI_HANDLE hQue)
+{
+ TQueue *pQue = (TQueue *)hQue;
+
+ return (pQue->uCount);
+}
+
+
+/**
+ * \fn que_Print
+ * \brief Print queue status
+ *
+ * Print the queue's parameters (not the content).
+ *
+ * \note
+ * \param hQue - The queue object
+ * \return void
+ * \sa
+ */
+
+#ifdef TI_DBG
+
+void que_Print(TI_HANDLE hQue)
+{
+ TQueue *pQue = (TQueue *)hQue;
+
+ WLAN_OS_REPORT(("que_Print: Count=%u MaxCount=%u Limit=%u Overflow=%u NodeHeaderOffset=%u Next=0x%x Prev=0x%x\n",
+ pQue->uCount, pQue->uMaxCount, pQue->uLimit, pQue->uOverflow,
+ pQue->uNodeHeaderOffset, pQue->tHead.pNext, pQue->tHead.pPrev));
+}
+
+#endif /* TI_DBG */
+
+
+