[ovs-dev] [PATCH 4/7] lib/rculist: New RCU-iterator, single-writer doubly-linked list.
Jarno Rajahalme
jrajahalme at nicira.com
Wed Oct 29 17:05:49 UTC 2014
On Oct 28, 2014, at 4:25 PM, Ben Pfaff <blp at nicira.com> wrote:
> 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 <jrajahalme at 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’ll look into that. In general the functions are tiny, so it might make sense to just inline most of them.
>
> 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)
>
Right, I actually noticed that while debugging, but then forgot.
Thanks for the fix!
> 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:
Yes, thanks!
>> +/* 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:
Right.
>> +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().
>
OK, I’ll remove NDEBUG from those functions for now.
> Acked-by: Ben Pfaff <blp at nicira.com>
Thanks for the review, pushed to master!
Jarno
More information about the dev
mailing list