www.pudn.com > vxworks_usb.rar > usbListLib.c
/* usbListLib.c - Linked list utility functions */ /* Copyright 2000 Wind River Systems, Inc. */ /* Modification history -------------------- 01a,10jun99,rcb First. */ /* DESCRIPTION This file inmplements a set of general-purpose linked-list functions which are portable across OS's. Linked lists are a collection of LINK structures. Each LINK structure contains a forward a backward list pointer. Each LINK structure also contains afield which points (typically) to the caller's structure which contains the LINK structure. usbListLink() and usbListUnlink() are used to add and remove LINK structures in a linked list. The LINK field may be placed anywhere in the client's structure, and the client's structure may even contain more than one LINK field - allowing the structure to be linked into multiple lists simultaneously. usbListFirst() retrieves the first structure on a linked list and usbListNext() retrieves subsequent structures. */ /* defines */ #define DEBUG_LIST /* includes */ #include "usb/usbPlatform.h" #include "usb/ossLib.h" #include "usb/usbListLib.h" /* our API */ #ifdef DEBUG_LIST #include "assert.h" #endif /* functions */ /*************************************************************************** * * usbListLink - Add an element to a linked list * * Using the LINK structure , add to the list of which the * list head is . must be LINK_HEAD or LINK_TAIL. * * RETURNS: N/A */ VOID usbListLink (pLIST_HEAD pHead, /* list head */ pVOID pStruct, /* ptr to base of structure to be linked */ pLINK pLink, /* ptr to LINK structure to be linked */ UINT16 flag /* indicates LINK_HEAD or LINK_TAIL */ ) { pLINK *ppTail; #ifdef DEBUG_LIST /* See if the indicated pStruct is already on the list. */ pVOID pElement = usbListFirst (pHead); pUINT8 pElementLink; while (pElement != NULL) { assert (pElement != pStruct); pElementLink = (pUINT8) pElement; pElementLink += ((pUINT8) pLink) - ((pUINT8) pStruct); pElement = usbListNext ((pLINK) pElementLink); } #endif /* #ifdef DEBUG_LIST */ pLink->pStruct = pStruct; if (flag == LINK_HEAD) { /* Add the Entry to the head of the list. */ pLink->linkFwd = pHead->pLink; pLink->linkBack = (pLINK) pHead; if (pHead->pLink != NULL) pHead->pLink->linkBack = pLink; pHead->pLink = pLink; } else { /* Add the entry to the tail of the list. */ for (ppTail = &pHead->pLink; *ppTail != NULL; ppTail = &((*ppTail)->linkFwd)); pLink->linkFwd = NULL; pLink->linkBack = (pLINK) ppTail; *ppTail = pLink; } } /*************************************************************************** * * usbListLinkProt - Add an element to a list guarded by a mutex * * This function is similar to linkList() with the addition that this * function will take the prior to manipulating the list. * * NOTE: The function will block forever if the mutex does not become * available. * * RETURNS: N/A */ VOID usbListLinkProt (pLIST_HEAD pHead, /* list head */ pVOID pStruct, /* ptr to base of structure to be linked */ pLINK pLink, /* ptr to LINK structure to be linked */ UINT16 flag, /* indicates LINK_HEAD or LINK_TAIL */ MUTEX_HANDLE mutex /* list guard mutex */ ) { OSS_MUTEX_TAKE (mutex, OSS_BLOCK); usbListLink (pHead, pStruct, pLink, flag); OSS_MUTEX_RELEASE (mutex); } /*************************************************************************** * * usbListUnlink - Remove an entry from a linked list * * Removes from a linked list. * * RETURNS: N/A */ VOID usbListUnlink (pLINK pLink /* LINK structure to be unlinked */ ) { /* De-link pElement from its linked-lis. */ if (pLink->linkBack) { pLink->linkBack->linkFwd = pLink->linkFwd; } if (pLink->linkFwd) { pLink->linkFwd->linkBack = pLink->linkBack; } pLink->linkBack = pLink->linkFwd = NULL; } /*************************************************************************** * * usbListUnlinkProt - Removes an element from a list guarged by a mutex * * This function is the same as usbListUnlink() with the addition that this * function will take the prior to manipulating the list. * * NOTE: The function will block forever if the mutex does not become * available. * * RETURNS: N/A */ VOID usbListUnlinkProt (pLINK pLink, /* LINK structure to be unlinked */ MUTEX_HANDLE mutex /* list guard mutex */ ) { OSS_MUTEX_TAKE (mutex, OSS_BLOCK); usbListUnlink (pLink); OSS_MUTEX_RELEASE (mutex); } /*************************************************************************** * * usbListFirst - Returns first entry on a linked list * * Returns the pointer to the first structure in a linked list given a * pointer to the LIST_HEAD. * * RETURNS: of first structure on list or NULL if list empty. */ pVOID usbListFirst (pLIST_HEAD pListHead /* head of linked list */ ) { if (pListHead == NULL || pListHead->pLink == NULL) return NULL; return pListHead->pLink->pStruct; } /*************************************************************************** * * usbListNext - Retrieves next pStruct in a linked list * * Returns the pointer to the next structure in a linked list given a * pointer. The value returned is the of the element * in the linked list which follows the current , not a pointer to * the following . (Typically, a client is more interested in * walking its own list of structures rather than the LINK structures * used to maintain the linked list. * * RETURNS: of next structure in list or NULL if end of list. */ pVOID usbListNext (pLINK pLink /* LINK structure */ ) { if (pLink == NULL || pLink->linkFwd == NULL) return NULL; return pLink->linkFwd->pStruct; } /* End of file. */