429 lines
9.9 KiB
C
429 lines
9.9 KiB
C
/*********************************************************
|
|
* Copyright (C) 1998-2015 VMware, Inc. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation version 2 and no later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* circList.h --
|
|
*
|
|
* macros, prototypes and struct definitions for double-linked
|
|
* circular lists.
|
|
*/
|
|
|
|
#ifndef _CIRCLIST_H_
|
|
#define _CIRCLIST_H_
|
|
|
|
#define INCLUDE_ALLOW_USERLEVEL
|
|
#define INCLUDE_ALLOW_VMMON
|
|
#define INCLUDE_ALLOW_VMCORE
|
|
#define INCLUDE_ALLOW_MODULE
|
|
#define INCLUDE_ALLOW_VMKERNEL
|
|
#include "includeCheck.h"
|
|
#include "vmware.h"
|
|
|
|
typedef struct ListItem {
|
|
struct ListItem *prev;
|
|
struct ListItem *next;
|
|
} ListItem;
|
|
|
|
/* A list with no elements is a null pointer. */
|
|
#define LIST_ITEM_DEF(name) \
|
|
ListItem * name = NULL
|
|
|
|
#define LIST_EMPTY(l) ((l) == NULL)
|
|
|
|
/* initialize list item */
|
|
#define INIT_LIST_ITEM(p) \
|
|
do { \
|
|
(p)->prev = (p)->next = (p); \
|
|
} while (0)
|
|
|
|
/* check if initialized */
|
|
#define IS_LIST_ITEM_INITIALIZED(li) \
|
|
(((li) == (li)->prev) && ((li) == (li)->next))
|
|
|
|
/* return first element in the list */
|
|
#define LIST_FIRST(l) (l)
|
|
#define LIST_FIRST_CHK(l) (l)
|
|
|
|
/* return last element in the list */
|
|
#define LIST_LAST(l) ((l)->prev)
|
|
#define LIST_LAST_CHK(l) (LIST_EMPTY(l) ? NULL : LIST_LAST(l))
|
|
|
|
/*
|
|
* LIST_CONTAINER - get the struct for this entry (like list_entry)
|
|
* @ptr: the &struct ListItem pointer.
|
|
* @type: the type of the struct this is embedded in.
|
|
* @member: the name of the list struct within the struct.
|
|
*/
|
|
#define LIST_CONTAINER(ptr, type, member) \
|
|
VMW_CONTAINER_OF(ptr, type, member)
|
|
|
|
/*
|
|
* delete item from the list
|
|
*/
|
|
#define LIST_DEL DelListItem
|
|
|
|
/*
|
|
* link two lists together
|
|
*/
|
|
#define LIST_SPLICE SpliceLists
|
|
|
|
/*
|
|
* Split a list into two lists
|
|
*/
|
|
#define LIST_SPLIT SplitLists
|
|
|
|
/*
|
|
* Add item to front of stack. List pointer points to new head.
|
|
*/
|
|
#define LIST_PUSH PushListItem
|
|
|
|
/*
|
|
* Add item at back of queue. List pointer only changes if list was empty.
|
|
*/
|
|
#define LIST_QUEUE QueueListItem
|
|
|
|
/*
|
|
* Get the list size.
|
|
*/
|
|
#define LIST_SIZE GetListSize
|
|
|
|
/*
|
|
* LIST_SCAN_FROM scans the list from "from" up until "until".
|
|
* The loop variable p should not be destroyed in the process.
|
|
* "from" is an element in the list where to start scanning.
|
|
* "until" is the element where search should stop.
|
|
* member is the field to use for the search - either "next" or "prev".
|
|
*/
|
|
#define LIST_SCAN_FROM(p, from, until, member) \
|
|
for (p = (from); (p) != NULL; \
|
|
(p) = (((p)->member == (until)) ? NULL : (p)->member))
|
|
|
|
/* scan the entire list (non-destructively) */
|
|
#define LIST_SCAN(p, l) \
|
|
LIST_SCAN_FROM(p, LIST_FIRST(l), LIST_FIRST(l), next)
|
|
|
|
|
|
/* scan a list backward from last element to first (non-destructively) */
|
|
#define LIST_SCAN_BACK(p, l) \
|
|
LIST_SCAN_FROM(p, LIST_LAST_CHK(l), LIST_LAST(l), prev)
|
|
|
|
/* scan the entire list where loop element may be destroyed */
|
|
#define LIST_SCAN_SAFE(p, pn, l) \
|
|
if (!LIST_EMPTY(l)) \
|
|
for (p = (l), (pn) = NextListItem(p, l); (p) != NULL; \
|
|
(p) = (pn), (pn) = NextListItem(p, l))
|
|
|
|
/* scan the entire list backwards where loop element may be destroyed */
|
|
#define LIST_SCAN_BACK_SAFE(p, pn, l) \
|
|
if (!LIST_EMPTY(l)) \
|
|
for (p = LIST_LAST(l), (pn) = PrevListItem(p, l); (p) != NULL; \
|
|
(p) = (pn), (pn) = PrevListItem(p, l))
|
|
|
|
|
|
/* function definitions */
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* NextListItem --
|
|
*
|
|
* Returns the next member of a doubly linked list, or NULL if last.
|
|
* Assumes: p is member of the list headed by head.
|
|
*
|
|
* Result:
|
|
* If head or p is NULL, return NULL. Otherwise,
|
|
* next list member (or null if last).
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE ListItem *
|
|
NextListItem(ListItem *p, // IN
|
|
ListItem *head) // IN
|
|
{
|
|
if (head == NULL || p == NULL) {
|
|
return NULL;
|
|
}
|
|
/* both p and head are non-null */
|
|
p = p->next;
|
|
return p == head ? NULL : p;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* PrevListItem --
|
|
*
|
|
* Returns the prev member of a doubly linked list, or NULL if first.
|
|
* Assumes: p is member of the list headed by head.
|
|
*
|
|
* Result:
|
|
* If head or prev is NULL, return NULL. Otherwise,
|
|
* prev list member (or null if first).
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE ListItem *
|
|
PrevListItem(ListItem *p, // IN
|
|
ListItem *head) // IN
|
|
{
|
|
if (head == NULL || p == NULL) {
|
|
return NULL;
|
|
}
|
|
/* both p and head are non-null */
|
|
return p == head ? NULL : p->prev;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* DelListItem --
|
|
*
|
|
* Deletes a member of a doubly linked list, possibly modifies the
|
|
* list header itself.
|
|
* Assumes neither p nor headp is null and p is a member of *headp.
|
|
*
|
|
* Result:
|
|
* None
|
|
*
|
|
* Side effects:
|
|
* Modifies *headp.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE void
|
|
DelListItem(ListItem *p, // IN
|
|
ListItem **headp) // IN/OUT
|
|
{
|
|
ListItem *next;
|
|
|
|
ASSERT(p);
|
|
ASSERT(headp);
|
|
|
|
next = p->next;
|
|
if (p == next) {
|
|
*headp = NULL;
|
|
} else {
|
|
next->prev = p->prev;
|
|
p->prev->next = next;
|
|
if (*headp == p) {
|
|
*headp = next;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* QueueListItem --
|
|
*
|
|
* Adds a new member to the back of a doubly linked list (queue)
|
|
* Assumes neither p nor headp is null and p is not a member of *headp.
|
|
*
|
|
* Result:
|
|
* None
|
|
*
|
|
* Side effects:
|
|
* Modifies *headp.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE void
|
|
QueueListItem(ListItem *p, // IN
|
|
ListItem **headp) // IN/OUT
|
|
{
|
|
ListItem *head;
|
|
|
|
head = *headp;
|
|
if (LIST_EMPTY(head)) {
|
|
INIT_LIST_ITEM(p);
|
|
*headp = p;
|
|
} else {
|
|
p->prev = head->prev;
|
|
p->next = head;
|
|
p->prev->next = p;
|
|
head->prev = p;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* PushListItem --
|
|
*
|
|
* Adds a new member to the front of a doubly linked list (stack)
|
|
* Assumes neither p nor headp is null and p is not a member of *headp.
|
|
*
|
|
* Result:
|
|
* None
|
|
*
|
|
* Side effects:
|
|
* Modifies *headp.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE void
|
|
PushListItem(ListItem *p, // IN
|
|
ListItem **headp) // IN/OUT
|
|
{
|
|
QueueListItem(p, headp);
|
|
*headp = p;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* SpliceLists --
|
|
*
|
|
* Make a single list {l1 l2} from {l1} and {l2} and return it.
|
|
* It is okay for one or both lists to be NULL.
|
|
* No checking is done. It is assumed that l1 and l2 are two
|
|
* distinct lists.
|
|
*
|
|
* Result:
|
|
* A list { l1 l2 }.
|
|
*
|
|
* Side effects:
|
|
* Modifies l1 and l2 list pointers.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE ListItem *
|
|
SpliceLists(ListItem *l1, // IN
|
|
ListItem *l2) // IN
|
|
{
|
|
ListItem *l1Last, *l2Last;
|
|
|
|
if (LIST_EMPTY(l1)) {
|
|
return l2;
|
|
}
|
|
|
|
if (LIST_EMPTY(l2)) {
|
|
return l1;
|
|
}
|
|
|
|
l1Last = l1->prev; /* last elem of l1 */
|
|
l2Last = l2->prev; /* last elem of l2 */
|
|
|
|
/*
|
|
* l1 -> ... -> l1Last l2 -> ... l2Last
|
|
*/
|
|
l1Last->next = l2;
|
|
l2->prev = l1Last;
|
|
|
|
l1->prev = l2Last;
|
|
l2Last->next = l1;
|
|
|
|
return l1;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* SplitLists --
|
|
*
|
|
* Make a list l = {l1 l2} into two separate lists {l1} and {l2}, where:
|
|
* l = { ... x -> p -> ... } split into:
|
|
* l1 = { ... -> x }
|
|
* l2 = { p -> ... }
|
|
* Assumes neither p nor l is null and p is a member of l.
|
|
* If p is the first element of l, then l1 will be NULL.
|
|
*
|
|
* Result:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Sets *l1p and *l2p to the resulting two lists.
|
|
* Modifies l's pointers.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE void
|
|
SplitLists(ListItem *p, // IN
|
|
ListItem *l, // IN
|
|
ListItem **l1p, // OUT
|
|
ListItem **l2p) // OUT
|
|
{
|
|
ListItem *last;
|
|
|
|
if (p == LIST_FIRST(l)) { /* first element */
|
|
*l1p = NULL;
|
|
*l2p = l;
|
|
return;
|
|
}
|
|
|
|
last = l->prev;
|
|
|
|
*l1p = l;
|
|
p->prev->next = l;
|
|
l->prev = p->prev;
|
|
|
|
*l2p = p;
|
|
p->prev = last;
|
|
last->next = p;
|
|
}
|
|
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
*
|
|
* GetListSize --
|
|
*
|
|
* Return the number of items in the list.
|
|
*
|
|
* Result:
|
|
* The number of items in the list.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
|
|
static INLINE int
|
|
GetListSize(ListItem *head) // IN
|
|
{
|
|
ListItem *li;
|
|
int ret = 0;
|
|
|
|
LIST_SCAN(li, head) {
|
|
ret++;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#endif /* _CIRCLIST_H_ */
|