Paolo Bonzini <pbonz...@redhat.com> writes: > Just a couple of questions, one of them on the new macro... > >> +/* prior to publication of the elm->prev->next value, some list >> + * readers may still see the removed element when following >> + * the antecedent's next pointer. >> + */ >> + >> +#define QLIST_REMOVE_RCU(elm, field) do { \ >> + if ((elm)->field.le_next != NULL) { \ >> + (elm)->field.le_next->field.le_prev = \ >> + (elm)->field.le_prev; \ >> + } \ >> + atomic_rcu_set((elm)->field.le_prev, (elm)->field.le_next); \ >> +} while (/*CONSTCOND*/0) > > Why is the barrier needed here, but not in Linux's list_del_rcu? > > I think it is not needed because all involved elements have already been > published and just have their pointers shuffled.
I read this as more than shuffling pointers. The intent here is that the previous element's next pointer is being updated to omit the current element from the list. atomic_set always deferences the pointer passed to it, and (field)->le_pre is a double pointer. So looking at the macro: #define atomic_set(ptr, i) ((*(__typeof__(*ptr) *volatile) (ptr)) = (i)) It translates to: ( ( * (__typeof(*elm->field.le_prev) *volatile) (elm)->field.le_prev) = elm->field.le_next; ) Which is: *((struct *elm) *volatile)(elm)->field.le_prev = elm->field.le_next; Which is: *(elm)->field.le_prev = elm->field.le_next; Because field.le_prev is a double pointer that has previously been set to &prev (the address of the previous list element) this is assiging the *previous* element's next pointer, the way I read it. The Linux list_del_rcu is dealing with a singly linked list and therefore does not set a value in the previous node's element. But I'm still unclear on whether or not the memory barrier is needed because the deleted element won't be reclaimed right away. Mike -- Mike Day | + 1 919 371-8786 | ncm...@ncultra.org "Endurance is a Virtue"