On Fri, Oct 24, 2014 at 01:36:38PM -0700, Jarno Rajahalme wrote: > rculist allows concurrent lockless list iteration, while a writer may > be modifying the list. Multiple writers can be supported by using a > mutex in addition to rculist. > > First user will be added in a following patch. > > Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
I think this will be useful. Thank you. Hardly anything in the original list.h is inlined. I wonder whether we should inline some of those functions. I think that the following evaluates to 0xc0000000 on 32-bit and 0xc000000000000000 on 64-bit. That's identifiable, yes, but something like 0xcccccccc is even more obvious (and somewhat customary; it is both a large number that is likely to segfault and the "trap to debugger" instruction on x86). So would you consider UINTPTR_MAX / 0xf * 0xc? > +#define RCULIST_POISON (struct rculist *)(((UINTPTR_MAX / 4) + 1) * 3) In rculist_splice_hidden(), can the first ovsrcu_set() be an ovsrcu_set_hidden()? I think that the stipulation in the comment means that the pointer being set can't be visible yet: > +/* Removes elements 'first' though 'last' (exclusive) from their current > list, > + * which may NOT be visible to any other threads (== be hidden from them), > + * then inserts them just before 'before'. */ > +static inline void > +rculist_splice_hidden(struct rculist *before, struct rculist *first, > + struct rculist *last) > + OVS_NO_THREAD_SAFETY_ANALYSIS > +{ > + struct rculist *last_next; > + > + if (first == last) { > + return; > + } > + last = last->prev; > + > + /* Cleanly remove 'first'...'last' from its current list. */ > + last_next = rculist_next_protected(last); > + last_next->prev = first->prev; > + ovsrcu_set(&first->prev->next, last_next); > + > + /* Splice 'first'...'last' into new list. */ > + first->prev = before->prev; > + ovsrcu_set(&last->next, before); > + ovsrcu_set(&before->prev->next, first); > + before->prev = last; > +} I think that the first ovsrcu_set() here can be ovsrcu_set_hidden() also: > +static inline void > +rculist_replace(struct rculist *element, struct rculist *position) > + OVS_NO_THREAD_SAFETY_ANALYSIS > +{ > + struct rculist *position_next = rculist_next_protected(position); > + > + ovsrcu_set(&element->next, position_next); > + position_next->prev = element; > + element->prev = position->prev; > + ovsrcu_set(&element->prev->next, element); > + > +#ifndef NDEBUG > + rculist_poison(position); /* XXX: Some overhead due to ovsrcu_postpone() > */ > +#endif > +} In rculist_front() and rculist_back_protected(), it looks pretty odd to write "#ifndef NDEBUG" around an ovs_assert(). I understand the idea, but if it's important enough to support NDEBUG here then maybe we should just add NDEBUG support to ovs_assert(). Acked-by: Ben Pfaff <b...@nicira.com> _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev