当前位置: 首页 > news >正文

南京一等一网站建设/查排名

南京一等一网站建设,查排名,注册500万的空壳公司,东莞网站建设培训一、前言 linux内核链表在include/linux/list.h文件中,内核中实现的链表比较简洁,实用性很强,因此想把它单独移植出来使用。 内核中的代码只能使用gnuc编译器编译,stdc编译器编译是会报错的,主要是因为typeof这个宏是…

一、前言

linux内核链表在include/linux/list.h文件中,内核中实现的链表比较简洁,实用性很强,因此想把它单独移植出来使用。

内核中的代码只能使用gnuc编译器编译,stdc编译器编译是会报错的,主要是因为typeof这个宏是gnuc特有的扩展,stdc中没有此扩展。

本篇文章就是来解决这个问题的,移植得到一个在stdc下运行的list,方便其他平台使用。

二、移植过程

  • 1、将include/linux/list.h单独扣出来,保存为list.h文件。

  • 2、修改头文件,并添加list_head的定义,还有部分宏定义,以下为添加部分:

    #include <stdbool.h>
    #include <stddef.h>struct list_head {struct list_head *next, *prev;
    };struct hlist_head {struct hlist_node *first;
    };struct hlist_node {struct hlist_node *next, **pprev;
    };#define WRITE_ONCE(var, val)    ((var) = (val))
    #define READ_ONCE(var)          (var)/* container_of */
    #ifndef offsetof
    #define offsetof(type, member)  (size_t)(&((type*)0)->member)
    #endif
    #define container_of(ptr, type, member)     ((type *)((char *)(ptr) - offsetof(type, member)))
    

    修改并添加了以下宏,改完后可以在stdc下编译:

    • 1、WRITE_ONCEREAD_ONCE
    • 2、container_of,去除了typeof的使用。
  • 3、删除所有使用typeof的定义,将以下所有使用到typeof的代码删除:

/*** list_next_entry - get the next element in list* @pos:	the type * to cursor* @member:	the name of the list_head within the struct.*/
#define list_next_entry(pos, member) \list_entry((pos)->member.next, typeof(*(pos)), member)/*** list_prev_entry - get the prev element in list* @pos:	the type * to cursor* @member:	the name of the list_head within the struct.*/
#define list_prev_entry(pos, member) \list_entry((pos)->member.prev, typeof(*(pos)), member)/*** list_for_each_entry	-	iterate over list of given type* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_for_each_entry(pos, head, member)				\for (pos = list_first_entry(head, typeof(*pos), member);	\&pos->member != (head);					\pos = list_next_entry(pos, member))/*** list_for_each_entry_reverse - iterate backwards over list of given type.* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_for_each_entry_reverse(pos, head, member)			\for (pos = list_last_entry(head, typeof(*pos), member);		\&pos->member != (head); 					\pos = list_prev_entry(pos, member))/*** list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()* @pos:	the type * to use as a start point* @head:	the head of the list* @member:	the name of the list_head within the struct.** Prepares a pos entry for use as a start point in list_for_each_entry_continue().*/
#define list_prepare_entry(pos, head, member) \((pos) ? : list_entry(head, typeof(*pos), member))/*** list_for_each_entry_safe - iterate over list of given type safe against removal of list entry* @pos:	the type * to use as a loop cursor.* @n:		another type * to use as temporary storage* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_for_each_entry_safe(pos, n, head, member)			\for (pos = list_first_entry(head, typeof(*pos), member),	\n = list_next_entry(pos, member);			\&pos->member != (head); 					\pos = n, n = list_next_entry(n, member))/*** list_for_each_entry_safe_reverse - iterate backwards over list safe against removal* @pos:	the type * to use as a loop cursor.* @n:		another type * to use as temporary storage* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Iterate backwards over list of given type, safe against removal* of list entry.*/
#define list_for_each_entry_safe_reverse(pos, n, head, member)		\for (pos = list_last_entry(head, typeof(*pos), member),		\n = list_prev_entry(pos, member);			\&pos->member != (head); 					\pos = n, n = list_prev_entry(n, member))#define hlist_entry_safe(ptr, type, member) \({ typeof(ptr) ____ptr = (ptr); \____ptr ? hlist_entry(____ptr, type, member) : NULL; \})/*** hlist_for_each_entry	- iterate over list of given type* @pos:	the type * 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(pos, head, member)				\for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\pos;							\pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))/*** hlist_for_each_entry_continue - iterate over a hlist continuing after current point* @pos:	the type * to use as a loop cursor.* @member:	the name of the hlist_node within the struct.*/
#define hlist_for_each_entry_continue(pos, member)			\for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\pos;							\pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))/*** hlist_for_each_entry_from - iterate over a hlist continuing from current point* @pos:	the type * to use as a loop cursor.* @member:	the name of the hlist_node within the struct.*/
#define hlist_for_each_entry_from(pos, member)				\for (; pos;							\pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))/*** hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry* @pos:	the type * 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(pos, n, head, member) 		\for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\pos && ({ n = pos->member.next; 1; });			\pos = hlist_entry_safe(n, typeof(*pos), member))

至此,移植完成。

三、移植好的list.h文件

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H#include <stdbool.h>
#include <stddef.h>struct list_head {struct list_head *next, *prev;
};struct hlist_head {struct hlist_node *first;
};struct hlist_node {struct hlist_node *next, **pprev;
};#define WRITE_ONCE(var, val)    ((var) = (val))
#define READ_ONCE(var)          (var)/* container_of */
#ifndef offsetof
#define offsetof(type, member)  (size_t)(&((type*)0)->member)
#endif
#define container_of(ptr, type, member)     ((type *)((char *)(ptr) - offsetof(type, member)))/** Circular doubly linked list implementation.** Some of the internal functions ("__xxx") are useful when* manipulating whole lists rather than single entries, as* sometimes we already know the next/prev entries and we can* generate better code by using them directly rather than* using the generic single-entry routines.*/#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \struct list_head name = LIST_HEAD_INIT(name)/*** INIT_LIST_HEAD - Initialize a list_head structure* @list: list_head structure to be initialized.** Initializes the list_head to point to itself.  If it is a list header,* the result is an empty list.*/
static inline void INIT_LIST_HEAD(struct list_head *list)
{WRITE_ONCE(list->next, list);list->prev = list;
}static inline bool __list_add_valid(struct list_head *new,struct list_head *prev,struct list_head *next)
{return true;
}
static inline bool __list_del_entry_valid(struct list_head *entry)
{return true;
}/** Insert a new entry between two known consecutive entries.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{if (!__list_add_valid(new, prev, next))return;next->prev = new;new->next = next;new->prev = prev;WRITE_ONCE(prev->next, new);
}/*** list_add - add a new entry* @new: new entry to be added* @head: list head to add it after** Insert a new entry after the specified head.* This is good for implementing stacks.*/
static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}/*** list_add_tail - add a new entry* @new: new entry to be added* @head: list head to add it before** Insert a new entry before the specified head.* This is useful for implementing queues.*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}/** Delete a list entry by making the prev/next entries* point to each other.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{next->prev = prev;WRITE_ONCE(prev->next, next);
}/** Delete a list entry and clear the 'prev' pointer.** This is a special-purpose list clearing method used in the networking code* for lists allocated as per-cpu, where we don't want to incur the extra* WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this* needs to check the node 'prev' pointer instead of calling list_empty().*/
static inline void __list_del_clearprev(struct list_head *entry)
{__list_del(entry->prev, entry->next);entry->prev = NULL;
}static inline void __list_del_entry(struct list_head *entry)
{if (!__list_del_entry_valid(entry))return;__list_del(entry->prev, entry->next);
}/*** list_del - deletes entry from list.* @entry: the element to delete from the list.* Note: list_empty() on entry does not return true after this, the entry is* in an undefined state.*/
static inline void list_del(struct list_head *entry)
{__list_del_entry(entry);entry->next = NULL;entry->prev = NULL;
}/*** list_replace - replace old entry by new one* @old : the element to be replaced* @new : the new element to insert** If @old was empty, it will be overwritten.*/
static inline void list_replace(struct list_head *old,struct list_head *new)
{new->next = old->next;new->next->prev = new;new->prev = old->prev;new->prev->next = new;
}/*** list_replace_init - replace old entry by new one and initialize the old one* @old : the element to be replaced* @new : the new element to insert** If @old was empty, it will be overwritten.*/
static inline void list_replace_init(struct list_head *old,struct list_head *new)
{list_replace(old, new);INIT_LIST_HEAD(old);
}/*** list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position* @entry1: the location to place entry2* @entry2: the location to place entry1*/
static inline void list_swap(struct list_head *entry1,struct list_head *entry2)
{struct list_head *pos = entry2->prev;list_del(entry2);list_replace(entry1, entry2);if (pos == entry1)pos = entry2;list_add(entry1, pos);
}/*** list_del_init - deletes entry from list and reinitialize it.* @entry: the element to delete from the list.*/
static inline void list_del_init(struct list_head *entry)
{__list_del_entry(entry);INIT_LIST_HEAD(entry);
}/*** list_move - delete from one list and add as another's head* @list: the entry to move* @head: the head that will precede our entry*/
static inline void list_move(struct list_head *list, struct list_head *head)
{__list_del_entry(list);list_add(list, head);
}/*** list_move_tail - delete from one list and add as another's tail* @list: the entry to move* @head: the head that will follow our entry*/
static inline void list_move_tail(struct list_head *list,struct list_head *head)
{__list_del_entry(list);list_add_tail(list, head);
}/*** list_bulk_move_tail - move a subsection of a list to its tail* @head: the head that will follow our entry* @first: first entry to move* @last: last entry to move, can be the same as first** Move all entries between @first and including @last before @head.* All three entries must belong to the same linked list.*/
static inline void list_bulk_move_tail(struct list_head *head,struct list_head *first,struct list_head *last)
{first->prev->next = last->next;last->next->prev = first->prev;head->prev->next = first;first->prev = head->prev;last->next = head;head->prev = last;
}/*** list_is_first -- tests whether @list is the first entry in list @head* @list: the entry to test* @head: the head of the list*/
static inline int list_is_first(const struct list_head *list, const struct list_head *head)
{return list->prev == head;
}/*** list_is_last - tests whether @list is the last entry in list @head* @list: the entry to test* @head: the head of the list*/
static inline int list_is_last(const struct list_head *list, const struct list_head *head)
{return list->next == head;
}/*** list_is_head - tests whether @list is the list @head* @list: the entry to test* @head: the head of the list*/
static inline int list_is_head(const struct list_head *list, const struct list_head *head)
{return list == head;
}/*** list_empty - tests whether a list is empty* @head: the list to test.*/
static inline int list_empty(const struct list_head *head)
{return READ_ONCE(head->next) == head;
}/*** list_del_init_careful - deletes entry from list and reinitialize it.* @entry: the element to delete from the list.** This is the same as list_del_init(), except designed to be used* together with list_empty_careful() in a way to guarantee ordering* of other memory operations.** Any memory operations done before a list_del_init_careful() are* guaranteed to be visible after a list_empty_careful() test.*/
static inline void list_del_init_careful(struct list_head *entry)
{__list_del_entry(entry);entry->prev = entry;WRITE_ONCE(entry->next, entry);
}/*** list_empty_careful - tests whether a list is empty and not being modified* @head: the list to test** Description:* tests whether a list is empty _and_ checks that no other CPU might be* in the process of modifying either member (next or prev)** NOTE: using list_empty_careful() without synchronization* can only be safe if the only activity that can happen* to the list entry is list_del_init(). Eg. it cannot be used* if another CPU could re-list_add() it.*/
static inline int list_empty_careful(const struct list_head *head)
{struct list_head *next = READ_ONCE(head->next);return list_is_head(next, head) && (next == head->prev);
}/*** list_rotate_left - rotate the list to the left* @head: the head of the list*/
static inline void list_rotate_left(struct list_head *head)
{struct list_head *first;if (!list_empty(head)) {first = head->next;list_move_tail(first, head);}
}/*** list_rotate_to_front() - Rotate list to specific item.* @list: The desired new front of the list.* @head: The head of the list.** Rotates list so that @list becomes the new front of the list.*/
static inline void list_rotate_to_front(struct list_head *list,struct list_head *head)
{/** Deletes the list head from the list denoted by @head and* places it as the tail of @list, this effectively rotates the* list so that @list is at the front.*/list_move_tail(head, list);
}/*** list_is_singular - tests whether a list has just one entry.* @head: the list to test.*/
static inline int list_is_singular(const struct list_head *head)
{return !list_empty(head) && (head->next == head->prev);
}static inline void __list_cut_position(struct list_head *list,struct list_head *head, struct list_head *entry)
{struct list_head *new_first = entry->next;list->next = head->next;list->next->prev = list;list->prev = entry;entry->next = list;head->next = new_first;new_first->prev = head;
}/*** list_cut_position - cut a list into two* @list: a new list to add all removed entries* @head: a list with entries* @entry: an entry within head, could be the head itself*	and if so we won't cut the list** This helper moves the initial part of @head, up to and* including @entry, from @head to @list. You should* pass on @entry an element you know is on @head. @list* should be an empty list or a list you do not care about* losing its data.**/
static inline void list_cut_position(struct list_head *list,struct list_head *head, struct list_head *entry)
{if (list_empty(head))return;if (list_is_singular(head) && !list_is_head(entry, head) && (entry != head->next))return;if (list_is_head(entry, head))INIT_LIST_HEAD(list);else__list_cut_position(list, head, entry);
}/*** list_cut_before - cut a list into two, before given entry* @list: a new list to add all removed entries* @head: a list with entries* @entry: an entry within head, could be the head itself** This helper moves the initial part of @head, up to but* excluding @entry, from @head to @list.  You should pass* in @entry an element you know is on @head.  @list should* be an empty list or a list you do not care about losing* its data.* If @entry == @head, all entries on @head are moved to* @list.*/
static inline void list_cut_before(struct list_head *list,struct list_head *head,struct list_head *entry)
{if (head->next == entry) {INIT_LIST_HEAD(list);return;}list->next = head->next;list->next->prev = list;list->prev = entry->prev;list->prev->next = list;head->next = entry;entry->prev = head;
}static inline void __list_splice(const struct list_head *list,struct list_head *prev,struct list_head *next)
{struct list_head *first = list->next;struct list_head *last = list->prev;first->prev = prev;prev->next = first;last->next = next;next->prev = last;
}/*** list_splice - join two lists, this is designed for stacks* @list: the new list to add.* @head: the place to add it in the first list.*/
static inline void list_splice(const struct list_head *list,struct list_head *head)
{if (!list_empty(list))__list_splice(list, head, head->next);
}/*** list_splice_tail - join two lists, each list being a queue* @list: the new list to add.* @head: the place to add it in the first list.*/
static inline void list_splice_tail(struct list_head *list,struct list_head *head)
{if (!list_empty(list))__list_splice(list, head->prev, head);
}/*** list_splice_init - join two lists and reinitialise the emptied list.* @list: the new list to add.* @head: the place to add it in the first list.** The list at @list is reinitialised*/
static inline void list_splice_init(struct list_head *list,struct list_head *head)
{if (!list_empty(list)) {__list_splice(list, head, head->next);INIT_LIST_HEAD(list);}
}/*** list_splice_tail_init - join two lists and reinitialise the emptied list* @list: the new list to add.* @head: the place to add it in the first list.** Each of the lists is a queue.* The list at @list is reinitialised*/
static inline void list_splice_tail_init(struct list_head *list,struct list_head *head)
{if (!list_empty(list)) {__list_splice(list, head->prev, head);INIT_LIST_HEAD(list);}
}/*** list_entry - get the struct for this entry* @ptr:	the &struct list_head pointer.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_head within the struct.*/
#define list_entry(ptr, type, member) \container_of(ptr, type, member)/*** list_first_entry - get the first element from a list* @ptr:	the list head to take the element from.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_head within the struct.** Note, that list is expected to be not empty.*/
#define list_first_entry(ptr, type, member) \list_entry((ptr)->next, type, member)/*** list_last_entry - get the last element from a list* @ptr:	the list head to take the element from.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_head within the struct.** Note, that list is expected to be not empty.*/
#define list_last_entry(ptr, type, member) \list_entry((ptr)->prev, type, member)/*** list_first_entry_or_null - get the first element from a list* @ptr:	the list head to take the element from.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_head within the struct.** Note that if the list is empty, it returns NULL.*/
#define list_first_entry_or_null(ptr, type, member) ({ \struct list_head *head__ = (ptr); \struct list_head *pos__ = READ_ONCE(head__->next); \pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
})/*** list_for_each	-	iterate over a list* @pos:	the &struct list_head to use as a loop cursor.* @head:	the head for your list.*/
#define list_for_each(pos, head) \for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next)/*** list_for_each_continue - continue iteration over a list* @pos:	the &struct list_head to use as a loop cursor.* @head:	the head for your list.** Continue to iterate over a list, continuing after the current position.*/
#define list_for_each_continue(pos, head) \for (pos = pos->next; !list_is_head(pos, (head)); pos = pos->next)/*** list_for_each_prev	-	iterate over a list backwards* @pos:	the &struct list_head to use as a loop cursor.* @head:	the head for your list.*/
#define list_for_each_prev(pos, head) \for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev)/*** list_for_each_safe - iterate over a list safe against removal of list entry* @pos:	the &struct list_head to use as a loop cursor.* @n:		another &struct list_head to use as temporary storage* @head:	the head for your list.*/
#define list_for_each_safe(pos, n, head) \for (pos = (head)->next, n = pos->next; \!list_is_head(pos, (head)); \pos = n, n = pos->next)/*** list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry* @pos:	the &struct list_head to use as a loop cursor.* @n:		another &struct list_head to use as temporary storage* @head:	the head for your list.*/
#define list_for_each_prev_safe(pos, n, head) \for (pos = (head)->prev, n = pos->prev; \!list_is_head(pos, (head)); \pos = n, n = pos->prev)/*** list_entry_is_head - test if the entry points to the head of the list* @pos:	the type * to cursor* @head:	the head for your list.* @member:	the name of the list_head within the struct.*/
#define list_entry_is_head(pos, head, member)				\(&pos->member == (head))/*** list_for_each_entry_continue - continue iteration over list of given type* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Continue to iterate over list of given type, continuing after* the current position.*/
#define list_for_each_entry_continue(pos, head, member) 		\for (pos = list_next_entry(pos, member);			\!list_entry_is_head(pos, head, member);			\pos = list_next_entry(pos, member))/*** list_for_each_entry_continue_reverse - iterate backwards from the given point* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Start to iterate over list of given type backwards, continuing after* the current position.*/
#define list_for_each_entry_continue_reverse(pos, head, member)		\for (pos = list_prev_entry(pos, member);			\!list_entry_is_head(pos, head, member);			\pos = list_prev_entry(pos, member))/*** list_for_each_entry_from - iterate over list of given type from the current point* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Iterate over list of given type, continuing from current position.*/
#define list_for_each_entry_from(pos, head, member) 			\for (; !list_entry_is_head(pos, head, member);			\pos = list_next_entry(pos, member))/*** list_for_each_entry_from_reverse - iterate backwards over list of given type*                                    from the current point* @pos:	the type * to use as a loop cursor.* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Iterate backwards over list of given type, continuing from current position.*/
#define list_for_each_entry_from_reverse(pos, head, member)		\for (; !list_entry_is_head(pos, head, member);			\pos = list_prev_entry(pos, member))/*** list_for_each_entry_safe_continue - continue list iteration safe against removal* @pos:	the type * to use as a loop cursor.* @n:		another type * to use as temporary storage* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Iterate over list of given type, continuing after current point,* safe against removal of list entry.*/
#define list_for_each_entry_safe_continue(pos, n, head, member) 		\for (pos = list_next_entry(pos, member), 				\n = list_next_entry(pos, member);				\!list_entry_is_head(pos, head, member);				\pos = n, n = list_next_entry(n, member))/*** list_for_each_entry_safe_from - iterate over list from current point safe against removal* @pos:	the type * to use as a loop cursor.* @n:		another type * to use as temporary storage* @head:	the head for your list.* @member:	the name of the list_head within the struct.** Iterate over list of given type from current point, safe against* removal of list entry.*/
#define list_for_each_entry_safe_from(pos, n, head, member) 			\for (n = list_next_entry(pos, member);					\!list_entry_is_head(pos, head, member);				\pos = n, n = list_next_entry(n, member))/*** list_safe_reset_next - reset a stale list_for_each_entry_safe loop* @pos:	the loop cursor used in the list_for_each_entry_safe loop* @n:		temporary storage used in list_for_each_entry_safe* @member:	the name of the list_head within the struct.** list_safe_reset_next is not safe to use in general if the list may be* modified concurrently (eg. the lock is dropped in the loop body). An* exception to this is if the cursor element (pos) is pinned in the list,* and list_safe_reset_next is called after re-taking the lock and before* completing the current iteration of the loop body.*/
#define list_safe_reset_next(pos, n, member)				\n = list_next_entry(pos, member)/** 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).*/#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;
}/*** hlist_unhashed - Has node been removed from list and reinitialized?* @h: Node to be checked** Not that not all removal functions will leave a node in unhashed* state.  For example, hlist_nulls_del_init_rcu() does leave the* node in unhashed state, but hlist_nulls_del() does not.*/
static inline int hlist_unhashed(const struct hlist_node *h)
{return !h->pprev;
}/*** hlist_unhashed_lockless - Version of hlist_unhashed for lockless use* @h: Node to be checked** This variant of hlist_unhashed() must be used in lockless contexts* to avoid potential load-tearing.  The READ_ONCE() is paired with the* various WRITE_ONCE() in hlist helpers that are defined below.*/
static inline int hlist_unhashed_lockless(const struct hlist_node *h)
{return !READ_ONCE(h->pprev);
}/*** hlist_empty - Is the specified hlist_head structure an empty hlist?* @h: Structure to check.*/
static inline int hlist_empty(const struct hlist_head *h)
{return !READ_ONCE(h->first);
}static inline void __hlist_del(struct hlist_node *n)
{struct hlist_node *next = n->next;struct hlist_node **pprev = n->pprev;WRITE_ONCE(*pprev, next);if (next)WRITE_ONCE(next->pprev, pprev);
}/*** hlist_del - Delete the specified hlist_node from its list* @n: Node to delete.** Note that this function leaves the node in hashed state.  Use* hlist_del_init() or similar instead to unhash @n.*/
static inline void hlist_del(struct hlist_node *n)
{__hlist_del(n);n->next = NULL;n->pprev = NULL;
}/*** hlist_del_init - Delete the specified hlist_node from its list and initialize* @n: Node to delete.** Note that this function leaves the node in unhashed state.*/
static inline void hlist_del_init(struct hlist_node *n)
{if (!hlist_unhashed(n)) {__hlist_del(n);INIT_HLIST_NODE(n);}
}/*** hlist_add_head - add a new entry at the beginning of the hlist* @n: new entry to be added* @h: hlist head to add it after** Insert a new entry after the specified head.* This is good for implementing stacks.*/
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{struct hlist_node *first = h->first;WRITE_ONCE(n->next, first);if (first)WRITE_ONCE(first->pprev, &n->next);WRITE_ONCE(h->first, n);WRITE_ONCE(n->pprev, &h->first);
}/*** hlist_add_before - add a new entry before the one specified* @n: new entry to be added* @next: hlist node to add it before, which must be non-NULL*/
static inline void hlist_add_before(struct hlist_node *n,struct hlist_node *next)
{WRITE_ONCE(n->pprev, next->pprev);WRITE_ONCE(n->next, next);WRITE_ONCE(next->pprev, &n->next);WRITE_ONCE(*(n->pprev), n);
}/*** hlist_add_behind - add a new entry after the one specified* @n: new entry to be added* @prev: hlist node to add it after, which must be non-NULL*/
static inline void hlist_add_behind(struct hlist_node *n,struct hlist_node *prev)
{WRITE_ONCE(n->next, prev->next);WRITE_ONCE(prev->next, n);WRITE_ONCE(n->pprev, &prev->next);if (n->next)WRITE_ONCE(n->next->pprev, &n->next);
}/*** hlist_add_fake - create a fake hlist consisting of a single headless node* @n: Node to make a fake list out of** This makes @n appear to be its own predecessor on a headless hlist.* The point of this is to allow things like hlist_del() to work correctly* in cases where there is no list.*/
static inline void hlist_add_fake(struct hlist_node *n)
{n->pprev = &n->next;
}/*** hlist_fake: Is this node a fake hlist?* @h: Node to check for being a self-referential fake hlist.*/
static inline bool hlist_fake(struct hlist_node *h)
{return h->pprev == &h->next;
}/*** hlist_is_singular_node - is node the only element of the specified hlist?* @n: Node to check for singularity.* @h: Header for potentially singular list.** Check whether the node is the only node of the head without* accessing head, thus avoiding unnecessary cache misses.*/
static inline bool
hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
{return !n->next && n->pprev == &h->first;
}/*** hlist_move_list - Move an hlist* @old: hlist_head for old list.* @new: hlist_head for new list.** Move a list from one list head to another. Fixup the pprev* reference of the first entry if it exists.*/
static inline void hlist_move_list(struct hlist_head *old,struct hlist_head *new)
{new->first = old->first;if (new->first)new->first->pprev = &new->first;old->first = NULL;
}#define hlist_entry(ptr, type, member) container_of(ptr,type,member)#define hlist_for_each(pos, head) \for (pos = (head)->first; pos ; pos = pos->next)#define hlist_for_each_safe(pos, n, head) \for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \pos = n)#endif

四、使用方法

  • 4.1、初始化链表
struct mailbox_data {u8 chan;u32 cmd;u32 data;int (*func)(struct mailbox_data *mailbox);struct list_head head;
};LIST_HEAD(mailbox_list_head);

struct mailbox_data {u8 chan;u32 cmd;u32 data;int (*func)(struct mailbox_data *mailbox);struct list_head head;
};struct mailbox_head mailbox_list_head;
INIT_LIST_HEAD(&mailbox_list_head);
  • 4.2、添加链表
struct mailbox_data* mailbox = calloc(1, sizeof(*mailbox));
list_add_tail(&mailbox->head, &mailbox_list_head);
  • 4.3、遍历链表
struct list_head* pos = NULL;
struct list_head* pt = NULL;
struct mailbox_data* mailbox = NULL;list_for_each_safe(pos, pt, &mailbox_list_head) {mailbox = list_entry(pos, struct mailbox_data, head);if (mailbox->func) {mailbox->func(mailbox);}list_del(&mailbox ->head);free(mailbox);
}
  • 4.4、删除链表
list_del(&mailbox ->head);

相关文章:

Linux内核链表(list)移植到任意平台

一、前言 linux内核链表在include/linux/list.h文件中&#xff0c;内核中实现的链表比较简洁&#xff0c;实用性很强&#xff0c;因此想把它单独移植出来使用。 内核中的代码只能使用gnuc编译器编译&#xff0c;stdc编译器编译是会报错的&#xff0c;主要是因为typeof这个宏是…...

【操作系统】聊聊什么是CPU上下文切换

对于linux来说&#xff0c;本身就是一个多任务运行的操作系统&#xff0c;运行远大于CPU核心数的程序&#xff0c;从用户视角来看是并发执行&#xff0c;而在CPU视角看其实是将不同的CPU时间片进行分割&#xff0c;每个程序执行一下&#xff0c;就切换到别的程序执行。那么这个…...

CMake教程-第 2 步 添加一个库

CMake教程-第 2 步 添加一个库 1 CMake教程介绍2 学习步骤Step 1: A Basic Starting PointStep 2: Adding a LibraryStep 3: Adding Usage Requirements for a LibraryStep 4: Adding Generator ExpressionsStep 5: Installing and TestingStep 6: Adding Support for a Testin…...

DS 顺序表--类实现(C++数据结构题)

实现顺序表的用 C 语言和类实现顺序表 属性包括&#xff1a;数组、实际长度、最大长度&#xff08;设定为 1000 &#xff09; 操作包括&#xff1a;创建、插入、删除、查找 类定义参考 #include<iostream> using namespace std; #define ok 0 #define error -1 // 顺…...

0.UML

1.图 1.1类图含义 第一层显示类的名称,如果是抽象类,则就用斜体显示。第二层是类的特性,通常就是字段和属性。第三层是类的操作,通常是方法或行为。注意前面的符号, ,表示public,-,表示private,#,表示protected。 1.2接口图 与类图的区别主要是顶端有<< interface >…...

PostgreSQL设置主键为自增

1、创建自增序列 CREATE SEQUENCE table_name_id_seq START 1; 2、设置字段默认值 字段默认值中设置 nextval(table_name_id_seq) 3、常用查询 -- 查询所有序列 select * from information_schema.sequences where sequence_schema public; -- 查询自增序列的当前值 select cu…...

input修改checkbox复选框默认选中样式

问题描述&#xff1a; <input type"checkbox" /> input修改checkbox默认选中样式&#xff0c;直接设置选中后的样式不生效&#xff0c;需要先给复选框设置-webkit-appearance: none&#xff08;取消默认样式&#xff09;&#xff0c; 再设置样式才会生效。 …...

高云FPGA系列教程(10):letter-shell移植

文章目录 letter-shell简介letter-shell源码获取letter-shell移植函数和变量应用示例 本文是高云FPGA系列教程的第10篇文章。 shell&#xff0c;中文是外壳的意思&#xff0c;就是操作系统的外壳。通过shell命令可以操作和控制操作系统&#xff0c;比如Linux中的Shell命令就包括…...

【C语言学习笔记---指针进阶02】

C语言程序设计笔记---017 C语言进阶之回调函数1、函数指针数组2、回调函数3、 回调函数的应用 --- qsort库函数4、模拟qsort函数5、结语 C语言进阶之回调函数 前言&#xff1a; 通过C语言进阶前篇的指针进阶01的知识&#xff0c;继续学习。这篇引用一个简易计算器的程序进行深…...

低功耗蓝牙物联网:未来连接的无限可能

物联网是连接各种设备和传感器的网络&#xff0c;其目的是实现信息的交换和共享&#xff0c;提高效率并优化生活。在这个领域&#xff0c;低功耗蓝牙&#xff08;BLE&#xff09;正在发挥着越来越重要的作用。 低功耗蓝牙是一种无线通信技术&#xff0c;它的主要特点是低功耗和…...

安装社区版本OB

获取一键安装包 https://www.oceanbase.com/softwarecenter 离线安装 [admintest001 ~]$ tar -xzf oceanbase-all-in-one-*.tar.gz [admintest001 ~]$ cd oceanbase-all-in-one/bin/ [admintest001 bin]$ ./install.sh [admintest001 bin]$ source ~/.oceanbase-all-in-one/…...

JSON 串和 Java 对象的相互转换

JSON 串和 Java 对象的相互转换 以 json 格式的数据进行前后端交互 前端发送请求时&#xff0c;如果是复杂的数据就会以 json 提交给后端&#xff1b; 而后端如果需要响应一些复杂的数据时&#xff0c;也需要以 json 格式将数据响应回给浏览器 为达到以上目的就需要重点学习…...

爬虫 — App 爬虫(一)

目录 一、介绍二、APP 爬虫常见反爬三、APP 抓包常用工具四、模拟器五、安装 APP1、下载 APP2、安装 APP 六、fiddler1、工作原理2、安装3、基本介绍 七、环境配置1、fiddler 的配置2、夜神模拟器的配置 八、案例 一、介绍 爬虫分类——数据来源 1、PC 端爬虫&#xff08;网页…...

如何使用正则表达式实现Java日志信息的抓取与收集

首先&#xff0c;什么是Java日志信息&#xff1f;简单来说&#xff0c;Java应用程序在运行过程中会输出一些信息&#xff0c;这些信息可以用来追踪程序运行状态、调试错误等。而Java日志信息就是这些输出信息的集合。 那么为什么要抓取和收集Java日志信息呢&#xff1f;一方面…...

C/C++算法入门 | 简单模拟

不爱生姜不吃醋⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 &#x1f334;前言&#x1f334;一、害死人不偿命的&#xff08;3n1&#xff09;猜想1.题目&#xff08;PAT B1001&#xff09;2.思路3.代码实现 &am…...

stm32学习-芯片系列/选型/开发方式

【03】STM32HAL库开发-初识STM32 | STM概念、芯片分类、命名规则、选型 | STM32原理图设计、看数据手册、最小系统的组成 、STM32IO分配_小浪宝宝的博客-CSDN博客  STM32&#xff1a;ST是意法半导体&#xff0c;M是MCU/MPU&#xff0c;32是32位。  ST累计推出了&#xff1a…...

mnist数据集

训练模型 import tensorflow as tfimport keras from keras.models import Sequential from keras.layers import Dense,Dropout, Flatten,Conv2D, MaxPooling2D # from keras.optimizers import SGD from tensorflow.keras.optimizers import Adam,Nadam, SGDfrom PIL import…...

Java之IO概述以及

1.1 什么是IO 生活中&#xff0c;你肯定经历过这样的场景。当你编辑一个文本文件&#xff0c;忘记了ctrls &#xff0c;可能文件就白白编辑了。当你电脑上插入一个U盘&#xff0c;可以把一个视频&#xff0c;拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢&#xff1f;键…...

Spring WebFlux—Reactive 核心

一、概述 spring-web 模块包含以下对响应式Web应用的基础支持&#xff1a; 对于服务器请求处理&#xff0c;有两个级别的支持。 HttpHandler: 用于HTTP请求处理的基本约定&#xff0c;具有非阻塞I/O和Reactive Streams背压&#xff0c;以及Reactor Netty、Undertow、Tomcat、…...

由于找不到d3dx9_43.dll,无法继续执行代码要怎么解决

D3DX9_43.dll是一个动态链接库文件&#xff0c;它是DirectX的一个组件&#xff0c;主要用于支持一些旧版本的游戏和软件。当电脑缺少这个文件时&#xff0c;可能会导致这些游戏和软件无法正常运行。例如&#xff0c;一些老游戏可能需要D3DX9_43.dll来支持图形渲染等功能。此外&…...

git安装配置教程

目录 git安装配置1. 安装git2. git 配置3.生成ssh key:4. 获取生产的密钥3. gitee或者github添加ssh-key4.git使用5. git 使用-本地仓库与远程仓库建立连接第一步&#xff1a;进入项目文件夹&#xff0c;初始化本地仓库第二步&#xff1a;建立远程仓库。 建立远程连接的小技巧 …...

要如何选择报修工单管理系统?需要注意哪些核心功能?

现如今&#xff0c;越来越多的企业已经离不开报修工单管理系统&#xff0c;但市面上的产品繁多&#xff0c;很难寻找到一款特别符合企业需求的系统。企业采购报修工单管理系统的主要目的在于利用其核心功能&#xff0c;如工单流转等&#xff0c;来解决工作事件的流程问题&#…...

面对大数据量渲染,前端工程师如何保证页面流畅性?

一、问题背景 在web前端开发中,需要渲染大量数据是很常见的需求。拿一般的业务系统来说,一个模块中往往需要显示成百上千条记录,这已经属于比较大的数据量。而一些大型系统,如数据分析平台、监控系统等,需要同时渲染的 数据量可能达到几十万甚至上百万。 面对大数据量渲染的需…...

2023年浙工商MBA新生奖学金名单公布,如何看待?

浙工商MBA项目官方最新公布了2023年的非全日制新生奖学金名单&#xff0c;按照政策约定&#xff0c;共分为特等奖学金1名&#xff0c;一等奖学金10名&#xff0c;二等奖学金15名&#xff0c;三等奖学金30名&#xff0c;额度对应3万、1万、0.8万、0.5万不等&#xff0c;主要名单…...

关于时空数据的培训 GAN:实用指南(第 02/3 部分)

一、说明 在本系列关于训练 GAN 实用指南的第 1 部分中&#xff0c;我们讨论了 a&#xff09; 鉴别器 &#xff08;D&#xff09; 和生成器 &#xff08;G&#xff09; 训练之间的不平衡如何导致模式崩溃和由于梯度消失而导致静音学习&#xff0c;以及 b&#xff09; GAN 对超参…...

UNIAPP利用canvas绘制图片和文字,并跟随鼠标移动

最近有个项目&#xff0c;要触摸组件&#xff0c;产生一条图片跟随移动&#xff0c;并显示相应的文字&#xff0c;在网上找了一些资料&#xff0c;终于完成构想&#xff0c;废话少说&#xff0c;直接上代码&#xff08;测试通过&#xff09; <template> <view>…...

【智能电表数据接入物联网平台实践】

智能电表数据接入物联网平台实践 设备接线准备设备调试代码实现Modbus TCP Client 读取电表数据读取寄存器数据转成32bit Float格式然后使用modbusTCP Client 读取数据 使用mqtt协议接入物联网平台最终代码实现 设备接线准备 设备调试 代码实现 Modbus TCP Client 读取电表数…...

Docker--network命令的用法

原文网址&#xff1a;Docker--network命令的用法_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Docker的network网络命令的用法。 官网网址 docker network | Docker Documentation 命令概述 所有命令 命令名称 说明 docker network connect 将容器连接到网络 dock…...

优维低代码实践:图片和搜索

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…...

[Qt]控件

文章摘于 爱编程的大丙 文章目录 1. 按钮类型控件1.1 按钮基类 QAbstractButton1.1.1 标题和图标1.1.2 按钮的 Check 属性1.1.3 信号1.1.4 槽函数 1.2 QPushButton1.2.1 常用API1.2.2 按钮的使用 1.3 QToolButton1.3.1 常用API1.3.2 按钮的使用 1.4 QRadioButton1.4.1 常用API…...