Hlist hash linked list

Source: Internet
Author: User
Tags prefetch

The hlist hash linked list is a common data structure in the kernel. Because it is different from the common linked list, we will analyze the hlist hash linked list here, hoping to help you.
In include/Linux/list. H, the list and hlist hash linked list structures are defined. Their definitions are listed below and can be compared:
struct list_head {
struct list_head *next, *prev;
};

Struct hlist_head {
Struct hlist_node * first;
};

Struct hlist_node {
Struct hlist_node * Next, ** pprev;
};

Double-ended (next, Prev) Double-chain tables are "too wasteful" for hash tables. Therefore, a dedicated hlist data structure for hash tables is designed separately-a single-finger-header double-loop linked list, the hlist header has only one pointer to the first node, but not to the End Node. In this way, the header stored in a massive hash table can reduce the space consumption by half.
Pprev has to be used because hlist is not a complete circular linked list. In the list, the table header and the node are in the same data structure. It is okay to use Prev directly. In hlist, the table header does not have Prev or next, and there is only one first. In order to uniformly modify the first pointer of the header, that is, the first pointer of the header must be changed to the newly inserted node, hlist designed pprev. The pprev of the hlist node no longer refers to the pointer of the forward node, but to the next in the forward node (may be the header) (first for the header) pointer (struct list_head ** pprev), so that the insert operation in the header can access and modify the next (or first) of the previous node through the consistent "* (node-> pprev) pointer.
Note: pprev refers to the next pointer in the previous node, and next is the pointer to hlist_node, so pprev is a pointer to hlist_node.

Note:
Pprev can be understood as a pointer to hlist_node like the prev of list. Since the first element of hlist_node, next is a pointer to hlist_node, pprev is also a pointer to next, pprev is a pointer to hlist_node.
struct hlist_node Prev;
struct hlist_node *pprev = (struct hlist_node *) Prev = (struct hlist_node *) (struct hlist_node * next) = struct hlist_node ** next;

The following are some macros commonly used in hlist:
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)

Only the hlist_add_before operation functions are listed below. The operation methods of other hlist linked list operation functions are similar. The parameter next in this function cannot be blank. It adds n nodes before next. The implementation of the function is similar to that of the corresponding function in the list.
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_add_before (struct hlist_node * n, struct hlist_node * Next)
{
N-> pprev = Next-> pprev;
N-> next = next;
Next-> pprev = & N-> next;
* (N-> pprev) = N;
}

# 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)


10. The functions of these two macros are to obtain the pointer POS pointing to each node in sequence through the header pointer.
# 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)

First, the prefetch macro is an empty implementation with a value of 1. Therefore, the second expression in the for loop is equivalent to POS.
Second, if you want to delete the node pointed to by the POs, you can only use the second macro hlist_for_each_safe (Pos, N, head ), because the first macro references the POs pointer in the third expression of the for loop, it is invalid if the node to which the POs points has been released. The traversal of the safe version won't be embarrassing, because an intermediate Variable N is used to temporarily save the next pointer of the POS.

When we want to use the hash table of the kernel to implement our own code, we will use these two macros to traverse our hash linked list. Remember: if you want to traverse and delete an operation, you must use the safe version.

11. The following three macros achieve the same function: traverse the hash linked list and obtain the pointer TPOs of its struct. The hlist_for_each_entry version starts to traverse from the header, while the hlist_for_each_entry_continue version starts to traverse from the next node of the node to which the POs points, and the hlist_for_each_entry_from version starts to traverse from that.

# 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)

# 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)

# 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)

The application of these two macros should also pay attention to security issues. Note that the third expression of the for loop does not use temporary variables to save the next pointer variable of the POS, therefore, you cannot use these two macros to traverse and delete nodes. to traverse each node securely, you must use the following macro:

12. Traverse each node from the header safely. (Security here refers to the process of traversing to delete this node)

# 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)

 

From: http://www.cnitblog.com/luofuchong/archive/2011/11/13/38986.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.