diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2015-09-20 20:03:16 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2015-11-23 13:37:35 -0500 |
commit | 1658d35ead5d8dd76f2b2d6ad0e32c08d123faa2 (patch) | |
tree | b237b079d8c057cb77e54f7e21baec00196b448f | |
parent | 1c97be677f72b3c338312aecd36d8fff20322f32 (diff) |
list: Use READ_ONCE() when testing for empty lists
Most of the list-empty-check macros (list_empty(), hlist_empty(),
hlist_bl_empty(), hlist_nulls_empty(), and hlist_nulls_empty()) use
an unadorned load to check the list header. Given that these macros
are sometimes invoked without the protection of a lock, this is
not sufficient. This commit therefore adds READ_ONCE() calls to
them. This commit does not touch llist_empty() because it already
has the needed ACCESS_ONCE().
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r-- | include/linux/list.h | 4 | ||||
-rw-r--r-- | include/linux/list_bl.h | 2 | ||||
-rw-r--r-- | include/linux/list_nulls.h | 2 |
3 files changed, 4 insertions, 4 deletions
diff --git a/include/linux/list.h b/include/linux/list.h index d7e31fe398b3..06c2d887a918 100644 --- a/include/linux/list.h +++ b/include/linux/list.h | |||
@@ -186,7 +186,7 @@ static inline int list_is_last(const struct list_head *list, | |||
186 | */ | 186 | */ |
187 | static inline int list_empty(const struct list_head *head) | 187 | static inline int list_empty(const struct list_head *head) |
188 | { | 188 | { |
189 | return head->next == head; | 189 | return READ_ONCE(head->next) == head; |
190 | } | 190 | } |
191 | 191 | ||
192 | /** | 192 | /** |
@@ -608,7 +608,7 @@ static inline int hlist_unhashed(const struct hlist_node *h) | |||
608 | 608 | ||
609 | static inline int hlist_empty(const struct hlist_head *h) | 609 | static inline int hlist_empty(const struct hlist_head *h) |
610 | { | 610 | { |
611 | return !h->first; | 611 | return !READ_ONCE(h->first); |
612 | } | 612 | } |
613 | 613 | ||
614 | static inline void __hlist_del(struct hlist_node *n) | 614 | static inline void __hlist_del(struct hlist_node *n) |
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h index 8132214e8efd..ee7229a6c06a 100644 --- a/include/linux/list_bl.h +++ b/include/linux/list_bl.h | |||
@@ -70,7 +70,7 @@ static inline void hlist_bl_set_first(struct hlist_bl_head *h, | |||
70 | 70 | ||
71 | static inline int hlist_bl_empty(const struct hlist_bl_head *h) | 71 | static inline int hlist_bl_empty(const struct hlist_bl_head *h) |
72 | { | 72 | { |
73 | return !((unsigned long)h->first & ~LIST_BL_LOCKMASK); | 73 | return !((unsigned long)READ_ONCE(h->first) & ~LIST_BL_LOCKMASK); |
74 | } | 74 | } |
75 | 75 | ||
76 | static inline void hlist_bl_add_head(struct hlist_bl_node *n, | 76 | static inline void hlist_bl_add_head(struct hlist_bl_node *n, |
diff --git a/include/linux/list_nulls.h b/include/linux/list_nulls.h index 444d2b1313bd..b01fe1009084 100644 --- a/include/linux/list_nulls.h +++ b/include/linux/list_nulls.h | |||
@@ -57,7 +57,7 @@ static inline int hlist_nulls_unhashed(const struct hlist_nulls_node *h) | |||
57 | 57 | ||
58 | static inline int hlist_nulls_empty(const struct hlist_nulls_head *h) | 58 | static inline int hlist_nulls_empty(const struct hlist_nulls_head *h) |
59 | { | 59 | { |
60 | return is_a_nulls(h->first); | 60 | return is_a_nulls(READ_ONCE(h->first)); |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline void hlist_nulls_add_head(struct hlist_nulls_node *n, | 63 | static inline void hlist_nulls_add_head(struct hlist_nulls_node *n, |