On Wed, Jun 25, 2014 at 04:15:54AM -0700, Jarno Rajahalme wrote: > Factor out the priority vector code from the classifier. > > Making the classifier use RCU instead of locking requires parallel > access to the priority vector, pointing to subtables in descending > priority order. When a new subtable is added, a new copy of the > priority vector is allocated, while the current readers can keep on > using the old copy they started with. Adding and removing subtables > is usually less frequent than adding and removing rules, so this > should not have a visible performance implication. As an optimization > for the userspace datapath use, where all the subtables have the same > priority, new subtables can be added to the end of the vector without > reallocation and without disturbing readers. > > cls_subtables_reset() is now removed, as it served its purpose in bug > hunting. Checks on the new pvector are now incorporated into > tests/test-classifier.c. > > Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> > --- > v2: Addressed comments by Ben Pfaff, intergrating lookahead and priority > handling into pvector iterator.
Thanks! pvector_cursor has an n_lookahead member. pvector_cursor_lookahead() has a pointer to a pvector_cursor but also takes an equivalent parameter. It might generate better code, especially in the n_lookahead == 0 case, to eliminate the member and just pass n_lookahead directly from the PVECTOR_FOR_EACH* macros to pvector_cursor_next(). (I didn't check.) I don't like the cast to void ** inside the iterator macros. It runs the risk that someone might accidentally supply a non-pointer variable and not even get a warning. What about using a void * return instead, like this? I don't think that we allow storing null pointers inside pvectors, so presumably it's OK to use a null pointer as a sentinel. diff --git a/lib/pvector.h b/lib/pvector.h index fd15ed2..5c22c07 100644 --- a/lib/pvector.h +++ b/lib/pvector.h @@ -135,20 +135,20 @@ struct pvector_cursor { static inline struct pvector_cursor pvector_cursor_init(const struct pvector *, size_t n_ahead, size_t obj_size); -static inline bool pvector_cursor_next(struct pvector_cursor *, void **, - int64_t stop_at_priority); +static inline void *pvector_cursor_next(struct pvector_cursor *, + int64_t stop_at_priority); static inline void pvector_cursor_lookahead(const struct pvector_cursor *, int n, size_t size); #define PVECTOR_FOR_EACH(PTR, PVECTOR) \ for (struct pvector_cursor cursor__ = pvector_cursor_init(PVECTOR, 0, 0); \ - pvector_cursor_next(&cursor__, (void **)&(PTR), -1); ) + ((PTR) = pvector_cursor_next(&cursor__, -1)) != NULL; ) /* Loop while priority is higher than 'PRIORITY' and prefetch objects * of size 'SZ' 'N' objects ahead from the current object. */ #define PVECTOR_FOR_EACH_PRIORITY(PTR, PRIORITY, N, SZ, PVECTOR) \ for (struct pvector_cursor cursor__ = pvector_cursor_init(PVECTOR, N, SZ); \ - pvector_cursor_next(&cursor__, (void **)&(PTR), PRIORITY); ) + ((PTR) = pvector_cursor_next(&cursor__, PRIORITY)) != NULL; ) /* Inline implementations. */ @@ -177,8 +177,8 @@ pvector_cursor_init(const struct pvector *pvec, return cursor; } -static inline bool pvector_cursor_next(struct pvector_cursor *cursor, - void **ptr, int64_t stop_at_priority) +static inline void *pvector_cursor_next(struct pvector_cursor *cursor, + int64_t stop_at_priority) { if (++cursor->entry_idx < cursor->size && cursor->vector[cursor->entry_idx].priority > stop_at_priority) { @@ -186,10 +186,9 @@ static inline bool pvector_cursor_next(struct pvector_cursor *cursor, pvector_cursor_lookahead(cursor, cursor->n_lookahead, cursor->obj_size); } - *ptr = cursor->vector[cursor->entry_idx].ptr; - return true; + return cursor->vector[cursor->entry_idx].ptr; } - return false; + return NULL; } static inline void pvector_cursor_lookahead(const struct pvector_cursor *cursor, Acked-by: Ben Pfaff <b...@nicira.com> _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev