List_for_each and list_for_each_entry

Source: Internet
Author: User
Tags prefetch

1. list_for_each

1. list_for_each prototype
# Define list_for_each (pos, head )\
For (pos = (head)-> next, prefetch (pos-> next); pos! = (Head );\
Pos = pos-> next, prefetch (pos-> next ))
It is actually a for loop. It uses the input pos as the cyclic variable, starting from the header, moving the pos one by one (next) until it returns to the head (prefetch () this parameter can be left blank and used for prefetch to increase the traversal speed ).
Note: This macro must place list_head In the first member of the data structure. At this point, its address is the address of the structure variable.

2. usage (take the sub-process accessing the current process as an example ):

Struct list_head {
Struct list_head * next, * prev;
};

The following definitions are available in struct task_struct:
Struct list_head children;

So

Struct task_struct * task;

Struct list_head * list;

List_for_each (list, & current-> chilidren ){

Task = list_entry (list, struct task_struct, sibling);/* The task points to the current subprocess */

}

The list_entry () function is used ():
The function is used in figure 1 to obtain the pointer (address) of the entire struct through a known pointer to the member subitem)
# Define list_entry (ptr, type, member )\
Container_of (ptr, type, member)

Ii. list_for_each_entry:
In the Linux kernel source code, you often need to operate the linked list. One of the most important macros is list_for_each_entry:
The meaning is roughly as follows:
Assuming there are only two nodes, the first member represents the head,
List_for_each_entry cyclically traverses the member subitem in each pos.
Figure 1:
Pos:
_______________________
|
|
| ...... |
|
|
| Member: | _________ |__> member |
| {|
| * Prev; |
| * Next; -- | ---------- | * next ;-------------
|}| |
|-^ ---- | ____________ |
|
|
| _________________________________________________ |
Macro list_for_each_entry:

# Define list_for_each_entry (pos, head, member )\
For (pos = list_entry (head)-> next, typeof (* pos), member );\
Prefetch (pos-> member. next), & pos-> member! = (Head );\
Pos = list_entry (pos-> member. next, typeof (* pos), member ))

List_entry (head)-> next, typeof (* pos), member) returns (head)-> next after the position of the physical pointer minus offsetof () bytes of data, physical address of the parent variable pos. the type of the parent variable is automatically returned by typeof (* pos) during compilation.
Therefore, list_for_each_entry traverses the childs struct of Type typeof (* pos) mounted under the head. Of course, each child struct contains similar two-way linked list list_head items such as struct list_head node, in this way, the cyclic pos will point to each child on the two-way linked list in turn. (member is the variable name defined in the child type)
The list_entry () function is used ():
The function is used in figure 1 to obtain the pointer (address) of the entire struct through a known pointer to the member subitem)
# Define list_entry (ptr, type, member )\

Container_of (ptr, type, member)
And function prefetch:
# Define prefetch (x) _ builtin_prefetch (x)

Builtin_prefetch is used:
Prefetch means to tell the cpu elements that may be used immediately and tell the cpu to prefetch, which can increase the speed.
The container_of () function is used here ():
493 # define container_of (ptr, type, member )({\
494 const typeof (type *) 0)-> member) * _ mptr = (ptr );\
495 (type *) (char *) _ mptr-offsetof (type, member ));})
Here, the offsetof () function is used:
Source code found on lxr:
# Define offset_of (type, memb )\
47 (unsigned long) (& (type *) 0)-> memb ))
Offsetof (TYPE, MEMBER)
This macro is defined in Linux kernel code (version 2.6.22) as follows:
# Define offsetof (TYPE, MEMBER) (size_t) & (TYPE *) 0)-> MEMBER );
Analysis:
(TYPE *) 0, force convert 0 to TYPE pointer, note p = (TYPE *) 0, p is the pointer to TYPE, its value is 0. Then p-> MEMBER is the element of MEMBER, and & (p-> MEMBER) is the address of MENBER, and the base address is 0, which is cleverly converted to the offset in TYPE. It is OK to forcibly convert the result to the size_t type. size_t is actually an int.
Typedef _ kernel_size_t size_t;
Typedef unsigned int _ kernel_size_t;
It can be seen that the macro is used to find the offset of MEMBER in TYPE.

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.