180 lines
4.9 KiB
C
180 lines
4.9 KiB
C
|
#ifndef _HASH_LIST_H
|
||
|
#define _H4SH_LIST_H
|
||
|
|
||
|
/* base on /usr/src/include/linux/list.h */
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#define prefetch(data) (void)1
|
||
|
|
||
|
/*
|
||
|
* These are non-NULL pointers that will result in page faults
|
||
|
* under normal circumstances, used to verify that nobody uses
|
||
|
* non-initialized list entries.
|
||
|
*/
|
||
|
#define LIST_POISON1 ((struct hlist_node *) 0x00100100)
|
||
|
#define LIST_POISON2 ((struct hlist_node **) 0x00200200)
|
||
|
|
||
|
/*
|
||
|
* Double linked lists with a single pointer list head.
|
||
|
* Mostly useful for hash tables where the two pointer list head is
|
||
|
* too wasteful.
|
||
|
* You lose the ability to access the tail in O(1).
|
||
|
*/
|
||
|
|
||
|
struct hlist_head {
|
||
|
struct hlist_node *first;
|
||
|
};
|
||
|
|
||
|
struct hlist_node {
|
||
|
struct hlist_node *next, **pprev;
|
||
|
};
|
||
|
|
||
|
#define HLIST_HEAD_INIT { .first = NULL }
|
||
|
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
|
||
|
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
|
||
|
static inline void INIT_HLIST_NODE(struct hlist_node *h)
|
||
|
{
|
||
|
h->next = NULL;
|
||
|
h->pprev = NULL;
|
||
|
}
|
||
|
|
||
|
static inline int hlist_unhashed(const struct hlist_node *h)
|
||
|
{
|
||
|
return !h->pprev;
|
||
|
}
|
||
|
|
||
|
static inline int hlist_empty(const struct hlist_head *h)
|
||
|
{
|
||
|
return !h->first;
|
||
|
}
|
||
|
|
||
|
static inline void __hlist_del(struct hlist_node *n)
|
||
|
{
|
||
|
struct hlist_node *next = n->next;
|
||
|
struct hlist_node **pprev = n->pprev;
|
||
|
*pprev = next;
|
||
|
if (next)
|
||
|
next->pprev = pprev;
|
||
|
}
|
||
|
|
||
|
static inline void hlist_del(struct hlist_node *n)
|
||
|
{
|
||
|
__hlist_del(n);
|
||
|
n->next = LIST_POISON1;
|
||
|
n->pprev = LIST_POISON2;
|
||
|
}
|
||
|
|
||
|
static inline void hlist_del_init(struct hlist_node *n)
|
||
|
{
|
||
|
if (!hlist_unhashed(n)) {
|
||
|
__hlist_del(n);
|
||
|
INIT_HLIST_NODE(n);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
||
|
{
|
||
|
struct hlist_node *first = h->first;
|
||
|
n->next = first;
|
||
|
if (first)
|
||
|
first->pprev = &n->next;
|
||
|
h->first = n;
|
||
|
n->pprev = &h->first;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* next must be != NULL */
|
||
|
static inline void hlist_add_before(struct hlist_node *n,
|
||
|
struct hlist_node *next)
|
||
|
{
|
||
|
n->pprev = next->pprev;
|
||
|
n->next = next;
|
||
|
next->pprev = &n->next;
|
||
|
*(n->pprev) = n;
|
||
|
}
|
||
|
|
||
|
static inline void hlist_add_after(struct hlist_node *n,
|
||
|
struct hlist_node *next)
|
||
|
{
|
||
|
next->next = n->next;
|
||
|
n->next = next;
|
||
|
next->pprev = &n->next;
|
||
|
|
||
|
if(next->next)
|
||
|
next->next->pprev = &next->next;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* container_of - cast a member of a structure out to the containing structure
|
||
|
* @ptr: the pointer to the member.
|
||
|
* @type: the type of the container struct this is embedded in.
|
||
|
* @member: the name of the member within the struct.
|
||
|
*
|
||
|
*/
|
||
|
#define container_of(ptr, type, member) ({ \
|
||
|
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||
|
|
||
|
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
|
||
|
|
||
|
#define hlist_for_each(pos, head) \
|
||
|
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
|
||
|
pos = pos->next)
|
||
|
|
||
|
#define hlist_for_each_safe(pos, n, head) \
|
||
|
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
|
||
|
pos = n)
|
||
|
|
||
|
/**
|
||
|
* hlist_for_each_entry - iterate over list of given type
|
||
|
* @tpos: the type * to use as a loop cursor.
|
||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||
|
* @head: the head for your list.
|
||
|
* @member: the name of the hlist_node within the struct.
|
||
|
*/
|
||
|
#define hlist_for_each_entry(tpos, pos, head, member) \
|
||
|
for (pos = (head)->first; \
|
||
|
pos && ({ prefetch(pos->next); 1;}) && \
|
||
|
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||
|
pos = pos->next)
|
||
|
|
||
|
/**
|
||
|
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
|
||
|
* @tpos: the type * to use as a loop cursor.
|
||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||
|
* @member: the name of the hlist_node within the struct.
|
||
|
*/
|
||
|
#define hlist_for_each_entry_continue(tpos, pos, member) \
|
||
|
for (pos = (pos)->next; \
|
||
|
pos && ({ prefetch(pos->next); 1;}) && \
|
||
|
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||
|
pos = pos->next)
|
||
|
|
||
|
/**
|
||
|
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
|
||
|
* @tpos: the type * to use as a loop cursor.
|
||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||
|
* @member: the name of the hlist_node within the struct.
|
||
|
*/
|
||
|
#define hlist_for_each_entry_from(tpos, pos, member) \
|
||
|
for (; pos && ({ prefetch(pos->next); 1;}) && \
|
||
|
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||
|
pos = pos->next)
|
||
|
|
||
|
/**
|
||
|
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||
|
* @tpos: the type * to use as a loop cursor.
|
||
|
* @pos: the &struct hlist_node to use as a loop cursor.
|
||
|
* @n: another &struct hlist_node to use as temporary storage
|
||
|
* @head: the head for your list.
|
||
|
* @member: the name of the hlist_node within the struct.
|
||
|
*/
|
||
|
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
|
||
|
for (pos = (head)->first; \
|
||
|
pos && ({ n = pos->next; 1; }) && \
|
||
|
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||
|
pos = n)
|
||
|
|
||
|
#endif
|