Files
vmware-host-modules/vmmon-only/include/circList.h
T

480 lines
11 KiB
C

/*********************************************************
* Copyright (C) 1998-2017 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"
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct ListItem {
struct ListItem *prev;
struct ListItem *next;
} ListItem;
/*
*----------------------------------------------------------------------
*
* CircList_IsEmpty --
*
* A NULL list is an empty list.
*
* Result:
* TRUE if list is empty, FALSE otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE Bool
CircList_IsEmpty(const ListItem *item) // IN
{
return item == NULL;
}
/*
*----------------------------------------------------------------------
*
* CircList_InitItem --
*
* Initialize item as a single-element circular list.
*
* Result:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE void
CircList_InitItem(ListItem *item) // OUT
{
item->prev = item->next = item;
}
/*
*----------------------------------------------------------------------
*
* CircList_First --
*
* Return first item in the list.
*
* Result:
* First item.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
CircList_First(ListItem *item) // IN
{
return item;
}
/*
*----------------------------------------------------------------------
*
* CircList_Last --
*
* Return last item in the list.
*
* Result:
* Last item.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE ListItem *
CircList_Last(ListItem *item)
{
return item->prev;
}
/*
* CIRC_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 CIRC_LIST_CONTAINER(ptr, type, member) \
VMW_CONTAINER_OF(ptr, type, member)
/*
* Historical name, left here to reduce churn.
* TODO: remove, all LIST_CONTAINER uses should be
* VMW_CONTAINER_OF and stop depending on circList.h
* to provide the definition.
*/
#define LIST_CONTAINER(ptr, type, member) VMW_CONTAINER_OF(ptr, type, member)
/*
* 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 CIRC_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 CIRC_LIST_SCAN(p, l) \
CIRC_LIST_SCAN_FROM(p, CircList_First(l), CircList_First(l), next)
/* scan the entire list where loop element may be destroyed */
#define CIRC_LIST_SCAN_SAFE(p, pn, l) \
if (!CircList_IsEmpty(l)) \
for (p = (l), (pn) = CircList_Next(p, l); (p) != NULL; \
(p) = (pn), (pn) = CircList_Next(p, l))
/* scan the entire list backwards where loop element may be destroyed */
#define CIRC_LIST_SCAN_BACK_SAFE(p, pn, l) \
if (!CircList_IsEmpty(l)) \
for (p = CircList_Last(l), (pn) = CircList_Prev(p, l); (p) != NULL; \
(p) = (pn), (pn) = CircList_Prev(p, l))
/*
*----------------------------------------------------------------------
*
* CircList_Next --
*
* 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 *
CircList_Next(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;
}
/*
*----------------------------------------------------------------------
*
* CircList_Prev --
*
* 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 *
CircList_Prev(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;
}
/*
*----------------------------------------------------------------------
*
* CircList_DeleteItem --
*
* 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
CircList_DeleteItem(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
ListItem *next;
ASSERT(p != NULL);
ASSERT(headp != NULL);
next = p->next;
if (p == next) {
*headp = NULL;
} else {
next->prev = p->prev;
p->prev->next = next;
if (*headp == p) {
*headp = next;
}
}
}
/*
*----------------------------------------------------------------------
*
* CircList_Queue --
*
* 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
CircList_Queue(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
ListItem *head;
head = *headp;
if (CircList_IsEmpty(head)) {
CircList_InitItem(p);
*headp = p;
} else {
p->prev = head->prev;
p->next = head;
p->prev->next = p;
head->prev = p;
}
}
/*
*----------------------------------------------------------------------
*
* CircList_Push --
*
* 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
CircList_Push(ListItem *p, // IN
ListItem **headp) // IN/OUT
{
CircList_Queue(p, headp);
*headp = p;
}
/*
*----------------------------------------------------------------------
*
* CircList_Splice --
*
* 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 *
CircList_Splice(ListItem *l1, // IN
ListItem *l2) // IN
{
ListItem *l1Last, *l2Last;
if (CircList_IsEmpty(l1)) {
return l2;
}
if (CircList_IsEmpty(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;
}
#if 0 /* Presently unused, enable if a use is found */
/*
*----------------------------------------------------------------------
*
* CircList_Split --
*
* 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
CircList_Split(ListItem *p, // IN
ListItem *l, // IN
ListItem **l1p, // OUT
ListItem **l2p) // OUT
{
ListItem *last;
if (p == CircList_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;
}
#endif
/*
*----------------------------------------------------------------------
*
* CircList_Size --
*
* Return the number of items in the list.
*
* Result:
* The number of items in the list.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static INLINE int
CircList_Size(ListItem *head) // IN
{
ListItem *li;
int ret = 0;
CIRC_LIST_SCAN(li, head) {
ret++;
}
return ret;
}
#if defined(__cplusplus)
} // extern "C"
#endif
#endif /* _CIRCLIST_H_ */