]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: list: add missing store barriers when updating elements and head
authorWilly Tarreau <w@1wt.eu>
Thu, 28 Feb 2019 10:14:22 +0000 (11:14 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 28 Feb 2019 14:59:31 +0000 (15:59 +0100)
Commit a8434ec14 ("MINOR: lists: Implement locked variations.")
introduced locked lists which use the elements pointers as locks
for concurrent operations. Under heavy stress the lists occasionally
fail. The cause is a missing barrier at some points when updating
the list element and the head : nothing prevents the compiler (or
CPU) from updating the list head first before updating the element,
making another thread jump to a wrong location. This patch simply
adds the missing barriers before these two opeations.

This will have to be backported if the commit above is backported.

include/common/mini-clist.h

index aefff82fa0d09bd3170b57c0d7cbb4556756f2c9..d8fcb159970fbf92a200b36f03f3b69268b14a72 100644 (file)
@@ -189,6 +189,7 @@ struct cond_wordlist {
                        }                                                  \
                        (el)->n = n;                                       \
                        (el)->p = p;                                       \
+                       __ha_barrier_store();                              \
                        n->p = (el);                                       \
                        __ha_barrier_store();                              \
                        p->n = (el);                                       \
@@ -214,6 +215,7 @@ struct cond_wordlist {
                        }                                                  \
                        (el)->n = n;                                       \
                        (el)->p = p;                                       \
+                       __ha_barrier_store();                              \
                        n->p = (el);                                       \
                        __ha_barrier_store();                              \
                        p->n = (el);                                       \
@@ -276,6 +278,7 @@ struct cond_wordlist {
                                 continue;                                 \
                         if (n == (lh)) {                                  \
                                 (lh)->n = lh;                             \
+                                __ha_barrier_store();                     \
                                 _ret = NULL;                              \
                                 break;                                    \
                         }                                                 \
@@ -288,6 +291,7 @@ struct cond_wordlist {
                         n2 = HA_ATOMIC_XCHG(&n->n, LLIST_BUSY);           \
                         if (n2 == LLIST_BUSY) {                           \
                                 n->p = p;                                 \
+                                __ha_barrier_store();                     \
                                 (lh)->n = n;                              \
                                 __ha_barrier_store();                     \
                                 continue;                                 \
@@ -296,6 +300,7 @@ struct cond_wordlist {
                         if (p2 == LLIST_BUSY) {                           \
                                 n->n = n2;                                \
                                 n->p = p;                                 \
+                                __ha_barrier_store();                     \
                                 (lh)->n = n;                              \
                                 __ha_barrier_store();                     \
                                 continue;                                 \