Messages in this thread Patch in this message | | | Date | Thu, 4 Aug 2011 09:45:32 -0500 (CDT) | From | Christoph Lameter <> | Subject | [listll] Fix fetching of head->first in lockless lists. |
| |
The fetching of head->first must occur in the cmpxchg loop.
With the current code head->first may change after the content were assigned to the "entry" variable. Entry then not be change anymore in the loop and be used as old_entry for the cmpxchg. The cmpxchg will then therefore compare "entry" to list->head. This will always fail if list->head has changed. The restarting of the loop will not fetch head->first again. So we could have a hang there.
I guess this only works now because the compiler optimizations pull the fetching of head->first into the loop.
Signed-off-by: Christoph Lameter <cl@linux.com>
--- lib/llist.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Index: linux-2.6/lib/llist.c =================================================================== --- linux-2.6.orig/lib/llist.c 2011-08-04 09:34:30.000000000 -0500 +++ linux-2.6/lib/llist.c 2011-08-04 09:35:08.000000000 -0500 @@ -42,8 +42,8 @@ void llist_add(struct llist_node *new, s BUG_ON(in_nmi()); #endif
- entry = head->first; do { + entry = head->first; old_entry = entry; new->next = entry; cpu_relax(); @@ -66,8 +66,8 @@ void llist_add_batch(struct llist_node * BUG_ON(in_nmi()); #endif
- entry = head->first; do { + entry = head->first; old_entry = entry; new_last->next = entry; cpu_relax(); @@ -97,8 +97,8 @@ struct llist_node *llist_del_first(struc BUG_ON(in_nmi()); #endif
- entry = head->first; do { + entry = head->first; if (entry == NULL) return NULL; old_entry = entry;
| |