linux-kernellockingrcu

Why does list_add_rcu only protect "prev->next"?


Following is the implementation of __list_add_rcu in include/linux/rculist.h:

static inline void __list_add_rcu(struct list_head *new,
        struct list_head *prev, struct list_head *next)
{
    new->next = next;
    new->prev = prev;
    rcu_assign_pointer(list_next_rcu(prev), new);
    next->prev = new;
}

Inside the function body, rcu-lock protects the update of prev->next, but no protection on next->prev. Why? Did I miss anything obvious here?


Solution

  • RCU-lock is unable to garantee correctness of traversing list in both directions.

    In short, such garantee would require to "protect" two pointers(next->prev and prev->next) at once. But RCU-section is not an exclusive section, so it is possible for two pointers to have values inconsistent between themselves.

    Because of that, RCU garantees correctness only for forward list traversal. For doing that, it is sufficient to protect only prev->next.

    Hint: While there are macros for reverse list traversal (such as list_for_each_entry_reverse), such macros have no RCU counterpairs. This is just because RCU doesn't support such traversal type.