A common data structure in the Linux kernel-bi-directional list (1) __html

Source: Internet
Author: User
Tags prev

Linux kernel code, a lot of online, such as http://docs.huihoo.com/doxygen/linux/kernel/3.7/include_2linux_2types_8h_source.html
Or
Http://lxr.free-electrons.com/source/drivers/gpu/drm/radeon/mkregtable.c
Most of the two-way linked list operations are basically defined in this file.
Analysis of this file.
First macro definition, gets the offset of a member variable in the structure body

#define OFFSETOF (Type, member) ((size_t) & ((type *) 0)->member)

Analysis:
(type) 0, cast 0 to type pointer, that is, p = (type) 0 to get a null pointer of type type*, then P->member is the element of member, and & (P->member) is Menber Address, because the actual starting address of this structure is 0, this cleverly gets the offset in type. And then cast the result to size_t type is OK, size_t is actually a long int, of course, the type may be different in different digits, but it must be big enough here.
typedef __kernel_size_t SIZE_T;
typedef unsigned int __kernel_size_t;

The second macro, from the pointer to the member variable, gets the pointer to the struct that the member variable belongs to

#define CONTAINER_OF (PTR, type, member) ({          \
        const typeof ((type *) 0)->member) *__mptr = (PTR);    \
                     (Type *) ((char *) __mptr-offsetof (type, member);})

Analysis:
Here are two steps, the first step is to define a pointer to a member variable type, first to save the incoming PTR in this local variable, the second step is to force the pointer of the member variable to char*, and then subtract the member variable from the structure, and then get the first address of the structure body. The type* type that is coerced into a struct is the ultimate function of obtaining a pointer to the struct that the member variable belongs to from the pointer to the member variable.
On the basis of these two macros, a bidirectional linked list is realized.

struct List_head {
struct list_head *next, *prev;
 };

The operation of the linked list is based on the most basic two inline functions:

__list_add static inline void (struct list_head *new, struct, list_head *prev, struct list_head                               )
 65 {         next->prev = new;         new->next = next;         New->prev = prev;         prev->next = new;
 and
 109 static inline void __list_del (struct list_head *prev, struct list_head *next) 111
  next->prev = prev;
112         Prev->next = Next;
113}

Other linked-list operations are performed using these two inline functions.
Another important point is that the list is used like this:

573 struct _IOEVENTFD {
574         struct list_head     list;
575         u64                  addr;
576         int                  length;
577         struct Eventfd_ctx  *eventfd;
578         u64                  Datamatch;
579         struct Kvm_io_device dev;
580         U8                   bus_idx;
581         bool                 wildcard;
582};

Or, such as:

struct _irqfd_resampler {         struct KVM *kvm;         struct/          * List of resampling _IRQFD objects sharing this GSI.          * RCU List modified under Kvm->irqfds.resampler_lock *
 *         struct list_head list;         struct Kvm_irq_ack_notifier notifier;          * * Entry in List of kvm->irqfd.resampler_list.  Use for sharing          * Resamplers among Irqfds on the same GSI.          accessed and modified under Kvm->irqfds.resampler_lock struct         link;
 70};

See the above application, you know, its prev and next I am afraid and encountered in the general node directly see Prev and Next fields and other member variables together in the node structure of the two-way linked list is very different, such a structure can be reused in various two-way linked lists, belong to different two-way linked lists.
How to access a structure based on a linked list relies on:

346/**
347  * List_entry-get The struct for this entry
348  * @ptr: The        &struct list_head pointer .
349  * @type: The type of the struct this are       embedded in.  * @member: The     name of the List_head within the struct.
351  *
/352 #define LIST_ENTRY (PTR, type, member) \
353         container_of (PTR, type, member)

Analysis:
Fill in member with the field name of the list's structure pointer, and then PTR as the actual list's structural body pointer, type as the actual structure of the content pointed to by this list, which list_entry through the Container_ A macro can obtain a pointer to the structure of the content that the PTR corresponds to, which is finally accessible.

The complete source file is as follows:

 1/* Utility to create the Register check tables 2 * This includes inlined list.h safe for userspace.
  3 * 4 * Copyright 2009 Jerome Glisse 5 * Copyright 2009 Red Hat Inc. 6 * 7 * authors:8 * Jerome glisse 9 * Dave Airlie #include <sys/types.h> 13 # Include <stdlib.h> #include <string.h> #include <stdio.h> #include <regex.h> #incl Ude <libgen.h> #define OFFSETOF (Type, member) (size_t) & ((TYPE *) 0)->member)/** * contain
 Er_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 are embedded in.
 * @member: The name of the member within the struct. * * * #define CONTAINER_OF (PTR, type, member) ({* Const typeof ((type *) 0)->member) *_    _mptr = (PTR); \ n (Type *) (char *) __mptr-offsetof (type), Member));
 ) * * * Simple doubly linked list implementation. * * Some of the internal functions ("__xxx") are useful when * manipulating whole lists rather than Ntries, as * Sometimes we already know the Next/prev entries and we can, generate better code by using them dir
 Ectly rather than the generic single-entry routines.
 * * struct List_head {struct list_head *next, *prev;
 43}; #define LIST_HEAD_INIT (name) {& (name), & (name)} #define LIST_HEAD (name) \ MB struct LI St_head name = list_head_init (name) static inline void Init_list_head (struct list_head) Wuyi l
 Ist->next = list;
 List->prev = list;
 * * * Insert A new entry between two known consecutive entries.
 * The * This is the ' only ' for internal list manipulation where we know * the Prev/next entries already! * * * #ifndef Config_debug_liST, static inline void __list_add (struct list_head *new, struct list_head, *prev
 CT list_head *next) Next->prev = new;
 New->next = Next;
 New->prev = prev;
 Prev->next = new;  #else-__list_add (struct list_head *new, struct, list_head *prev, struct
 List_head *next);  #endif/** * List_add-add A new entry * @new: New entry to is added * @head: List head to add
 it after * i * * Insert a new entry after the specified head.
 The * is good the for implementing stacks. List_add/inline void (struct list_head *new, struct list_head *head) __list_add (new, he
 AD, Head->next);  /** * List_add_tail-add A new entry * @new: New entry to is added @head: List head to add
 it before * * Insert a new entry before the specified head. 95 * This is useful for implementing queues. inline void List_add_tail (struct list_head *new, struct list_head *head) __list_add (NE
W, Head->prev, head);
102/I * Delete a list entry by making the Prev/next entries.
The * * is ' only ' for internal list manipulation where we know Prev/next entries already! 108 * * 109 static inline void __list_del (struct list_head *prev, struct list_head *next) next->prev
= prev;
112 Prev->next = Next;
113} 114/** 116 * list_del-deletes entry from list.
117 * @entry: The element to delete from the list.
118 * NOTE:LIST_EMPTY () on entry does not return true after this, and the entry is 119 * in a undefined state. A/121 #ifndef config_debug_list 122 static inline void List_del (struct list_head *entry) 123 {124 __list_de
L (Entry->prev, Entry->next); Entry->next = (void *) 0xDEADBEEF;
126 Entry->prev = (void *) 0xBEEFDEAD;
127} 128 #else 129 extern void List_del (struct list_head);  130 #endif 131 132/** * List_replace-replace old entry by new one 134 * @old: The element to is replaced 135 *
@new: The new element to insert 136 * 137 * If @old is empty, it'll be overwritten.  138 * * 139 static inline void List_replace (struct list_head *old, struct list_head *new) 140 {New->next =
old->next;
New->next->prev = new;
143 New->prev = old->prev;
144 New->prev->next = new;  145} 146 147 static inline void List_replace_init (struct list_head *old, 148 struct List_head *new) 149 {list_replace (old, new); 151 Init_list_head (old) 152} 153 154/**
_del_init-deletes entry from list and reinitialize it.
156 * @entry: the element to delete from the list. 157 * * 158 static inline void List_del_init (struct list_Head *entry) 159 {160 __list_del (Entry->prev, Entry->next); 161 Init_list_head (entry); 162} 163 1  /** 165 * List_move-delete from one list and add as another ' s head 166 * @list: The entry to move 167 * @head: the 
Head that would precede our entry/169 static inline void List_move (struct list_head *list, struct, list_head *head) 170 {171 __list_del (List->prev, list->next); 172 List_add (list, head) 173} 174 175/** 176 * l  Ist_move_tail-delete from one list and add as another's tail 177 * @list: The entry to move 178 * @head: This head                                   Would follow our entry 179 * 180 static inline void List_move_tail (struct list_head *list, 181 struct List_head *head) 183 __list_del (List->prev, list->next); 184 List_add_tail (LIS
T, head); 185} 186 187/** 188 * List_is_last-tests Whether @list is the last entry in List @head 189 * @list: the entry to TE St 190 * @heaD:the Head of the list 191 * * Inline int list_is_last (const struct List_head, 193 const struct List_head *head) 194 {195 return list->next = head; 196} 197 198/** 199 * list_emp
Ty-tests whether a list of empty * @head: the list to test.  201/Inline int list_empty (const struct List_head *head) 203 {204 return head->next = head; 205  } 206 207/** list_empty_careful-tests Whether a list of empty and not being modified * @head: the list to Test 210 * 211 * description:212 * Tests whether a list is empty _and_ the checks that no other CPUs might be 213 * in th 
e process of modifying either member (Next or prev) 214 * 215 * note:using list_empty_careful () without synchronization 216 * can only being safe if the can happen 217 * to the list entry is List_del_init (). Eg.
It cannot be used 218 * If another CPU could re-list_add () it. 219 * * Static inlineint list_empty_careful (const struct List_head *head) 221 {222 struct List_head *next = head->next; 223
return (next = = Head) && (next = Head->prev);
224}/** list_is_singular-tests whether a list has just one entry.
228 * @head: the list to test. 229 */230 static inline int list_is_singular (const struct List_head *head) 231 {232 return!list_empty (head) &A
mp;& (Head->next = = Head->prev); 233} 234 235 static inline void __list_cut_position (struct list_head *list, 236 s Truct list_head *head, 237 struct List_head *entry) 238 {239 struct LIST_H
EAD *new_first = entry->next;
List->next = head->next;
241 List->next->prev = list;
242 List->prev = entry;
243 Entry->next = list;
244 Head->next = New_first;
245 New_first->prev = head; 246} 247 248/** 249 * List_cut_position-cut a list into two * @list: A new list of add all removed entries 251 * @head: a list with ENT  Ries 252 * @entry: A entry within head, could is the head itself 253 * And if so we won ' t cut the list 254 * 255 * This helper moves the "initial part of" @head, up to and 256 * including @entry, from @head to @list. You are should 257 * pass on @entry A element you know are on @head.
@list 258 * Should be a empty list or a list of you don't care about 259 * losing its data. * 261/262 static inline void list_cut_position (struct list_head *list, 263 s Truct list_head *head, 264 struct List_head *entry) 265 {266 if (List_empty (
Head), 267 return; 268 if (list_is_singular) && (head->next!= entry && Head!= entry))
Eturn;
270 if (entry = head) 271 init_list_head (LIST);         272Else 273 __list_cut_position (list, head, entry); 274} 275 276 static inline void __list_splice (const struct List_head, *list 277 List_head *prev, struct list_head *next) 278 {279 struct List_head *first = list->next; 280 struct LIS
T_head *last = list->prev;
281 282 First->prev = prev;
283 Prev->next = A;
284 285 last->next = next;
286 Next->prev = Last;
287} 289/** 290 * List_splice-join Two lists, this is designed for stacks 291 * @list: The new list to add.
292 * @head: The place to add it in the list. 293 * * 294 static inline void List_splice (const struct List_head *list, 295 struct  
Ad *head) 296 {297 if (!list_empty (list)) 298 __list_splice (list, head, Head->next); 299} 300 /** 302 * List_splice_tail-join two lists, each list being a queue 303 * @list: The new List to Add.
304 * @head: The place to add it in the list. 305 * * 306 static inline void List_splice_tail (struct list_head *list, 307 struct LIS 
T_head *head) 308 {309 if (!list_empty (list)) 310 __list_splice (list, Head->prev, head); 311}
312 313/** list_splice_init-join two lists and reinitialise the emptied list.
315 * @list: The new list to add.
316 * @head: The place to add it in the list. 317 * 318 * The list at @list is reinitialised 319 * * * the inline<

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.