|
@@ -233,18 +233,43 @@ static inline void list_splice_init_rcu(struct list_head *list,
|
|
|
})
|
|
|
|
|
|
/**
|
|
|
- * list_first_entry_rcu - get the first element from a list
|
|
|
+ * Where are list_empty_rcu() and list_first_entry_rcu()?
|
|
|
+ *
|
|
|
+ * Implementing those functions following their counterparts list_empty() and
|
|
|
+ * list_first_entry() is not advisable because they lead to subtle race
|
|
|
+ * conditions as the following snippet shows:
|
|
|
+ *
|
|
|
+ * if (!list_empty_rcu(mylist)) {
|
|
|
+ * struct foo *bar = list_first_entry_rcu(mylist, struct foo, list_member);
|
|
|
+ * do_something(bar);
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * The list may not be empty when list_empty_rcu checks it, but it may be when
|
|
|
+ * list_first_entry_rcu rereads the ->next pointer.
|
|
|
+ *
|
|
|
+ * Rereading the ->next pointer is not a problem for list_empty() and
|
|
|
+ * list_first_entry() because they would be protected by a lock that blocks
|
|
|
+ * writers.
|
|
|
+ *
|
|
|
+ * See list_first_or_null_rcu for an alternative.
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * list_first_or_null_rcu - 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_struct within the struct.
|
|
|
*
|
|
|
- * Note, that list is expected to be not empty.
|
|
|
+ * Note that if the list is empty, it returns NULL.
|
|
|
*
|
|
|
* This primitive may safely run concurrently with the _rcu list-mutation
|
|
|
* primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
|
|
|
*/
|
|
|
-#define list_first_entry_rcu(ptr, type, member) \
|
|
|
- list_entry_rcu((ptr)->next, type, member)
|
|
|
+#define list_first_or_null_rcu(ptr, type, member) \
|
|
|
+ ({struct list_head *__ptr = (ptr); \
|
|
|
+ struct list_head __rcu *__next = list_next_rcu(__ptr); \
|
|
|
+ likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \
|
|
|
+ })
|
|
|
|
|
|
/**
|
|
|
* list_for_each_entry_rcu - iterate over rcu list of given type
|