I didn't look at the classifier yet. Maybe it can't work the same way. On Jul 19, 2014 1:33 AM, "Jarno Rajahalme" <jrajaha...@nicira.com> wrote:
> > > Sent from my iPhone > > > On Jul 19, 2014, at 10:03 AM, Ben Pfaff <b...@nicira.com> wrote: > > > >> On Fri, Jul 18, 2014 at 11:33:38PM -0700, Ben Pfaff wrote: > >>> On Fri, Jul 18, 2014 at 09:05:49PM -0700, Jarno Rajahalme wrote: > >>> Older GCC (e.g. 4.1.2) did not like the pointer casts used for > >>> initializing the iteration cursors. This patch changes the code to > >>> avoid the void casts for GCC, and makes the classifier interface more > >>> similar to that of the cmap. These changes make the code work with > >>> GCC 4.1.2 strict aliasing rules. > >>> > >>> VMware-BZ: #1287651 > >>> > >>> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> > >> > >> I see why GCC didn't like this code. > >> > >> There are lots of tricky constraints here. We don't want to violate ISO > >> aliasing rules, we have to stick to exactly one declaration in the first > >> clause of the for statement, and we don't want to have different code > >> for GCC and other compilers if we don't have to. The proposed solution > >> here compromises on the last one. > >> > >> I spent a bunch of time experimenting and came up with what I think is > >> the outline of another solution. How about adding a 'node' member to > >> cmap_cursor, like this: > >> > >> struct cmap_cursor { > >> const struct cmap_impl *impl; > >> uint32_t bucket_idx; > >> int entry_idx; > >> struct cmap_node *node; > >> }; > >> > >> struct cmap_cursor cmap_cursor_start(const struct cmap *); > >> void cmap_cursor_advance(struct cmap_cursor *); > >> > >> #define CMAP_FOR_EACH(NODE, MEMBER, CMAP) > \ > >> for (struct cmap_cursor cursor__ = cmap_cursor_start(CMAP); \ > >> (cursor__.node \ > >> ? (ASSIGN_CONTAINER(NODE, cursor__.node, MEMBER), true) \ > >> : false); \ > >> cmap_cursor_advance(&cursor__)) > >> > >> #define CMAP_FOR_EACH_SAFE(NODE, MEMBER, CMAP) > \ > >> for (struct cmap_cursor cursor__ = cmap_cursor_start(CMAP); \ > >> (cursor__.node \ > >> ? (ASSIGN_CONTAINER(NODE, cursor__.node, MEMBER), \ > >> cmap_cursor_advance(&cursor__), \ > >> true) \ > >> : false); \ > >> ) > >> > >> with corresponding support functions: > >> > >> struct cmap_cursor > >> cmap_cursor_start(const struct cmap *cmap) > >> { > >> struct cmap_cursor cursor; > >> > >> cursor.impl = cmap_get_impl(cmap); > >> cursor.bucket_idx = 0; > >> cursor.entry_idx = 0; > >> cursor.node = NULL; > >> cmap_cursor_advance(&cursor); > >> > >> return cursor; > >> } > >> > >> void > >> cmap_cursor_advance(struct cmap_cursor *cursor) > >> { > >> const struct cmap_impl *impl = cursor->impl; > >> > >> if (cursor->node) { > >> cursor->node = cmap_node_next(cursor->node); > >> if (cursor->node) { > >> return; > >> } > >> } > >> > >> while (cursor->bucket_idx <= impl->mask) { > >> const struct cmap_bucket *b = &impl->buckets[cursor->bucket_idx]; > >> > >> while (cursor->entry_idx < CMAP_K) { > >> cursor->node = > cmap_node_next(&b->nodes[cursor->entry_idx++]); > >> if (cursor->node) { > >> return; > >> } > >> } > >> > >> cursor->bucket_idx++; > >> cursor->entry_idx = 0; > >> } > >> } > > > > Here's a fully worked out version of this idea that compiles and passes > > all the tests (at least with GCC 4.7.2). With this, the _SAFE variants > > don't take an extra named variable or really have any extra cost, so one > > thinks about just getting making the normal variant the same as _SAFE: > > > > Just a quick note, more later: Corresponding changes to classifier would > be more complex, and there is a locking difference between the normal and > safe cases. Did you consider if classifier should use this same pattern? > > Jarno > > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev