|
@@ -84,65 +84,6 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
|
|
__list_add(new, head->prev, head);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * 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_rcu(struct list_head * new,
|
|
|
- struct list_head * prev, struct list_head * next)
|
|
|
-{
|
|
|
- new->next = next;
|
|
|
- new->prev = prev;
|
|
|
- smp_wmb();
|
|
|
- next->prev = new;
|
|
|
- prev->next = new;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * list_add_rcu - add a new entry to rcu-protected list
|
|
|
- * @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.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as list_add_rcu()
|
|
|
- * or list_del_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * list_for_each_entry_rcu().
|
|
|
- */
|
|
|
-static inline void list_add_rcu(struct list_head *new, struct list_head *head)
|
|
|
-{
|
|
|
- __list_add_rcu(new, head, head->next);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * list_add_tail_rcu - add a new entry to rcu-protected list
|
|
|
- * @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.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as list_add_tail_rcu()
|
|
|
- * or list_del_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * list_for_each_entry_rcu().
|
|
|
- */
|
|
|
-static inline void list_add_tail_rcu(struct list_head *new,
|
|
|
- struct list_head *head)
|
|
|
-{
|
|
|
- __list_add_rcu(new, head->prev, head);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Delete a list entry by making the prev/next entries
|
|
|
* point to each other.
|
|
@@ -173,36 +114,6 @@ static inline void list_del(struct list_head *entry)
|
|
|
extern void list_del(struct list_head *entry);
|
|
|
#endif
|
|
|
|
|
|
-/**
|
|
|
- * list_del_rcu - deletes entry from list without re-initialization
|
|
|
- * @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. It is useful for RCU based
|
|
|
- * lockfree traversal.
|
|
|
- *
|
|
|
- * In particular, it means that we can not poison the forward
|
|
|
- * pointers that may still be used for walking the list.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as list_del_rcu()
|
|
|
- * or list_add_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * list_for_each_entry_rcu().
|
|
|
- *
|
|
|
- * Note that the caller is not permitted to immediately free
|
|
|
- * the newly deleted entry. Instead, either synchronize_rcu()
|
|
|
- * or call_rcu() must be used to defer freeing until an RCU
|
|
|
- * grace period has elapsed.
|
|
|
- */
|
|
|
-static inline void list_del_rcu(struct list_head *entry)
|
|
|
-{
|
|
|
- __list_del(entry->prev, entry->next);
|
|
|
- entry->prev = LIST_POISON2;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* list_replace - replace old entry by new one
|
|
|
* @old : the element to be replaced
|
|
@@ -226,25 +137,6 @@ static inline void list_replace_init(struct list_head *old,
|
|
|
INIT_LIST_HEAD(old);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * list_replace_rcu - replace old entry by new one
|
|
|
- * @old : the element to be replaced
|
|
|
- * @new : the new element to insert
|
|
|
- *
|
|
|
- * The @old entry will be replaced with the @new entry atomically.
|
|
|
- * Note: @old should not be empty.
|
|
|
- */
|
|
|
-static inline void list_replace_rcu(struct list_head *old,
|
|
|
- struct list_head *new)
|
|
|
-{
|
|
|
- new->next = old->next;
|
|
|
- new->prev = old->prev;
|
|
|
- smp_wmb();
|
|
|
- new->next->prev = new;
|
|
|
- new->prev->next = new;
|
|
|
- old->prev = LIST_POISON2;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* list_del_init - deletes entry from list and reinitialize it.
|
|
|
* @entry: the element to delete from the list.
|
|
@@ -368,62 +260,6 @@ static inline void list_splice_init(struct list_head *list,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * list_splice_init_rcu - splice an RCU-protected list into an existing list.
|
|
|
- * @list: the RCU-protected list to splice
|
|
|
- * @head: the place in the list to splice the first list into
|
|
|
- * @sync: function to sync: synchronize_rcu(), synchronize_sched(), ...
|
|
|
- *
|
|
|
- * @head can be RCU-read traversed concurrently with this function.
|
|
|
- *
|
|
|
- * Note that this function blocks.
|
|
|
- *
|
|
|
- * Important note: the caller must take whatever action is necessary to
|
|
|
- * prevent any other updates to @head. In principle, it is possible
|
|
|
- * to modify the list as soon as sync() begins execution.
|
|
|
- * If this sort of thing becomes necessary, an alternative version
|
|
|
- * based on call_rcu() could be created. But only if -really-
|
|
|
- * needed -- there is no shortage of RCU API members.
|
|
|
- */
|
|
|
-static inline void list_splice_init_rcu(struct list_head *list,
|
|
|
- struct list_head *head,
|
|
|
- void (*sync)(void))
|
|
|
-{
|
|
|
- struct list_head *first = list->next;
|
|
|
- struct list_head *last = list->prev;
|
|
|
- struct list_head *at = head->next;
|
|
|
-
|
|
|
- if (list_empty(head))
|
|
|
- return;
|
|
|
-
|
|
|
- /* "first" and "last" tracking list, so initialize it. */
|
|
|
-
|
|
|
- INIT_LIST_HEAD(list);
|
|
|
-
|
|
|
- /*
|
|
|
- * At this point, the list body still points to the source list.
|
|
|
- * Wait for any readers to finish using the list before splicing
|
|
|
- * the list body into the new list. Any new readers will see
|
|
|
- * an empty list.
|
|
|
- */
|
|
|
-
|
|
|
- sync();
|
|
|
-
|
|
|
- /*
|
|
|
- * Readers are finished with the source list, so perform splice.
|
|
|
- * The order is important if the new list is global and accessible
|
|
|
- * to concurrent RCU readers. Note that RCU readers are not
|
|
|
- * permitted to traverse the prev pointers without excluding
|
|
|
- * this function.
|
|
|
- */
|
|
|
-
|
|
|
- last->next = at;
|
|
|
- smp_wmb();
|
|
|
- head->next = first;
|
|
|
- first->prev = head;
|
|
|
- at->prev = last;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* list_entry - get the struct for this entry
|
|
|
* @ptr: the &struct list_head pointer.
|
|
@@ -629,57 +465,6 @@ static inline void list_splice_init_rcu(struct list_head *list,
|
|
|
&pos->member != (head); \
|
|
|
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
|
|
|
|
|
|
-/**
|
|
|
- * list_for_each_rcu - iterate over an rcu-protected list
|
|
|
- * @pos: the &struct list_head to use as a loop cursor.
|
|
|
- * @head: the head for your list.
|
|
|
- *
|
|
|
- * This list-traversal primitive may safely run concurrently with
|
|
|
- * the _rcu list-mutation primitives such as list_add_rcu()
|
|
|
- * as long as the traversal is guarded by rcu_read_lock().
|
|
|
- */
|
|
|
-#define list_for_each_rcu(pos, head) \
|
|
|
- for (pos = rcu_dereference((head)->next); \
|
|
|
- prefetch(pos->next), pos != (head); \
|
|
|
- pos = rcu_dereference(pos->next))
|
|
|
-
|
|
|
-#define __list_for_each_rcu(pos, head) \
|
|
|
- for (pos = rcu_dereference((head)->next); \
|
|
|
- pos != (head); \
|
|
|
- pos = rcu_dereference(pos->next))
|
|
|
-
|
|
|
-/**
|
|
|
- * list_for_each_entry_rcu - iterate over rcu 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_struct within the struct.
|
|
|
- *
|
|
|
- * This list-traversal primitive may safely run concurrently with
|
|
|
- * the _rcu list-mutation primitives such as list_add_rcu()
|
|
|
- * as long as the traversal is guarded by rcu_read_lock().
|
|
|
- */
|
|
|
-#define list_for_each_entry_rcu(pos, head, member) \
|
|
|
- for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), member); \
|
|
|
- prefetch(pos->member.next), &pos->member != (head); \
|
|
|
- pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos), member))
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * list_for_each_continue_rcu
|
|
|
- * @pos: the &struct list_head to use as a loop cursor.
|
|
|
- * @head: the head for your list.
|
|
|
- *
|
|
|
- * Iterate over an rcu-protected list, continuing after current point.
|
|
|
- *
|
|
|
- * This list-traversal primitive may safely run concurrently with
|
|
|
- * the _rcu list-mutation primitives such as list_add_rcu()
|
|
|
- * as long as the traversal is guarded by rcu_read_lock().
|
|
|
- */
|
|
|
-#define list_for_each_continue_rcu(pos, head) \
|
|
|
- for ((pos) = rcu_dereference((pos)->next); \
|
|
|
- prefetch((pos)->next), (pos) != (head); \
|
|
|
- (pos) = rcu_dereference((pos)->next))
|
|
|
-
|
|
|
/*
|
|
|
* Double linked lists with a single pointer list head.
|
|
|
* Mostly useful for hash tables where the two pointer list head is
|
|
@@ -730,31 +515,6 @@ static inline void hlist_del(struct hlist_node *n)
|
|
|
n->pprev = LIST_POISON2;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * hlist_del_rcu - deletes entry from hash list without re-initialization
|
|
|
- * @n: the element to delete from the hash list.
|
|
|
- *
|
|
|
- * Note: list_unhashed() on entry does not return true after this,
|
|
|
- * the entry is in an undefined state. It is useful for RCU based
|
|
|
- * lockfree traversal.
|
|
|
- *
|
|
|
- * In particular, it means that we can not poison the forward
|
|
|
- * pointers that may still be used for walking the hash list.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as hlist_add_head_rcu()
|
|
|
- * or hlist_del_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * hlist_for_each_entry().
|
|
|
- */
|
|
|
-static inline void hlist_del_rcu(struct hlist_node *n)
|
|
|
-{
|
|
|
- __hlist_del(n);
|
|
|
- n->pprev = LIST_POISON2;
|
|
|
-}
|
|
|
-
|
|
|
static inline void hlist_del_init(struct hlist_node *n)
|
|
|
{
|
|
|
if (!hlist_unhashed(n)) {
|
|
@@ -763,27 +523,6 @@ static inline void hlist_del_init(struct hlist_node *n)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * hlist_replace_rcu - replace old entry by new one
|
|
|
- * @old : the element to be replaced
|
|
|
- * @new : the new element to insert
|
|
|
- *
|
|
|
- * The @old entry will be replaced with the @new entry atomically.
|
|
|
- */
|
|
|
-static inline void hlist_replace_rcu(struct hlist_node *old,
|
|
|
- struct hlist_node *new)
|
|
|
-{
|
|
|
- struct hlist_node *next = old->next;
|
|
|
-
|
|
|
- new->next = next;
|
|
|
- new->pprev = old->pprev;
|
|
|
- smp_wmb();
|
|
|
- if (next)
|
|
|
- new->next->pprev = &new->next;
|
|
|
- *new->pprev = new;
|
|
|
- old->pprev = LIST_POISON2;
|
|
|
-}
|
|
|
-
|
|
|
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
|
|
{
|
|
|
struct hlist_node *first = h->first;
|
|
@@ -794,38 +533,6 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
|
|
n->pprev = &h->first;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-/**
|
|
|
- * hlist_add_head_rcu
|
|
|
- * @n: the element to add to the hash list.
|
|
|
- * @h: the list to add to.
|
|
|
- *
|
|
|
- * Description:
|
|
|
- * Adds the specified element to the specified hlist,
|
|
|
- * while permitting racing traversals.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as hlist_add_head_rcu()
|
|
|
- * or hlist_del_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * hlist_for_each_entry_rcu(), used to prevent memory-consistency
|
|
|
- * problems on Alpha CPUs. Regardless of the type of CPU, the
|
|
|
- * list-traversal primitive must be guarded by rcu_read_lock().
|
|
|
- */
|
|
|
-static inline void hlist_add_head_rcu(struct hlist_node *n,
|
|
|
- struct hlist_head *h)
|
|
|
-{
|
|
|
- struct hlist_node *first = h->first;
|
|
|
- n->next = first;
|
|
|
- n->pprev = &h->first;
|
|
|
- smp_wmb();
|
|
|
- if (first)
|
|
|
- first->pprev = &n->next;
|
|
|
- h->first = n;
|
|
|
-}
|
|
|
-
|
|
|
/* next must be != NULL */
|
|
|
static inline void hlist_add_before(struct hlist_node *n,
|
|
|
struct hlist_node *next)
|
|
@@ -847,63 +554,6 @@ static inline void hlist_add_after(struct hlist_node *n,
|
|
|
next->next->pprev = &next->next;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * hlist_add_before_rcu
|
|
|
- * @n: the new element to add to the hash list.
|
|
|
- * @next: the existing element to add the new element before.
|
|
|
- *
|
|
|
- * Description:
|
|
|
- * Adds the specified element to the specified hlist
|
|
|
- * before the specified node while permitting racing traversals.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as hlist_add_head_rcu()
|
|
|
- * or hlist_del_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * hlist_for_each_entry_rcu(), used to prevent memory-consistency
|
|
|
- * problems on Alpha CPUs.
|
|
|
- */
|
|
|
-static inline void hlist_add_before_rcu(struct hlist_node *n,
|
|
|
- struct hlist_node *next)
|
|
|
-{
|
|
|
- n->pprev = next->pprev;
|
|
|
- n->next = next;
|
|
|
- smp_wmb();
|
|
|
- next->pprev = &n->next;
|
|
|
- *(n->pprev) = n;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * hlist_add_after_rcu
|
|
|
- * @prev: the existing element to add the new element after.
|
|
|
- * @n: the new element to add to the hash list.
|
|
|
- *
|
|
|
- * Description:
|
|
|
- * Adds the specified element to the specified hlist
|
|
|
- * after the specified node while permitting racing traversals.
|
|
|
- *
|
|
|
- * The caller must take whatever precautions are necessary
|
|
|
- * (such as holding appropriate locks) to avoid racing
|
|
|
- * with another list-mutation primitive, such as hlist_add_head_rcu()
|
|
|
- * or hlist_del_rcu(), running on this same list.
|
|
|
- * However, it is perfectly legal to run concurrently with
|
|
|
- * the _rcu list-traversal primitives, such as
|
|
|
- * hlist_for_each_entry_rcu(), used to prevent memory-consistency
|
|
|
- * problems on Alpha CPUs.
|
|
|
- */
|
|
|
-static inline void hlist_add_after_rcu(struct hlist_node *prev,
|
|
|
- struct hlist_node *n)
|
|
|
-{
|
|
|
- n->next = prev->next;
|
|
|
- n->pprev = &prev->next;
|
|
|
- smp_wmb();
|
|
|
- prev->next = n;
|
|
|
- if (n->next)
|
|
|
- n->next->pprev = &n->next;
|
|
|
-}
|
|
|
-
|
|
|
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
|
|
|
|
|
|
#define hlist_for_each(pos, head) \
|
|
@@ -964,21 +614,4 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
|
|
|
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
|
|
pos = n)
|
|
|
|
|
|
-/**
|
|
|
- * hlist_for_each_entry_rcu - iterate over rcu 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.
|
|
|
- *
|
|
|
- * This list-traversal primitive may safely run concurrently with
|
|
|
- * the _rcu list-mutation primitives such as hlist_add_head_rcu()
|
|
|
- * as long as the traversal is guarded by rcu_read_lock().
|
|
|
- */
|
|
|
-#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
|
|
|
- for (pos = rcu_dereference((head)->first); \
|
|
|
- pos && ({ prefetch(pos->next); 1;}) && \
|
|
|
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
|
|
- pos = rcu_dereference(pos->next))
|
|
|
-
|
|
|
#endif
|