lib/table: remove nonsensical const, add pure

Passing the struct route_table *ptr as const doesn't really help; if
anything it semantically would imply that the returned route_node is
const too since constness should propagate (but it doesn't in C.)

The right thing to do here - which actually helps the compiler optimize
the code too - is to tag functions with __attribute__((pure)).  The
compiler does this automatically if it has the function body (and the
body of all called functions) available.  That should cover most "static
inline" functions in headers, as well as functions in the same file.

However, this doesn't work (at least without LTO) for extern functions.
Hence, add "ext_pure" for this case.  (Built-in "extern" to make lines
shorter.)

Signed-off-by: David Lamparter <equinox@diac24.net>
This commit is contained in:
David Lamparter 2019-05-21 04:48:30 +02:00
parent 0734f93b8e
commit 3b18b6c03d
3 changed files with 44 additions and 32 deletions

View file

@ -76,6 +76,15 @@ extern "C" {
#define _DEPRECATED(x) deprecated
#endif
/* pure = function does not modify memory & return value is the same if
* memory hasn't changed (=> allows compiler to optimize)
*
* Mostly autodetected by the compiler if function body is available (i.e.
* static inline functions in headers). Since that implies it should only be
* used in headers for non-inline functions, the "extern" is included here.
*/
#define ext_pure extern __attribute__((pure))
/* for helper functions defined inside macros */
#define macro_inline static inline __attribute__((unused))
#define macro_pure static inline __attribute__((unused, pure))

View file

@ -191,7 +191,7 @@ static void set_link(struct route_node *node, struct route_node *new)
}
/* Find matched prefix. */
struct route_node *route_node_match(const struct route_table *table,
struct route_node *route_node_match(struct route_table *table,
union prefixconstptr pu)
{
const struct prefix *p = pu.p;
@ -221,7 +221,7 @@ struct route_node *route_node_match(const struct route_table *table,
return NULL;
}
struct route_node *route_node_match_ipv4(const struct route_table *table,
struct route_node *route_node_match_ipv4(struct route_table *table,
const struct in_addr *addr)
{
struct prefix_ipv4 p;
@ -234,7 +234,7 @@ struct route_node *route_node_match_ipv4(const struct route_table *table,
return route_node_match(table, (struct prefix *)&p);
}
struct route_node *route_node_match_ipv6(const struct route_table *table,
struct route_node *route_node_match_ipv6(struct route_table *table,
const struct in6_addr *addr)
{
struct prefix_ipv6 p;
@ -248,7 +248,7 @@ struct route_node *route_node_match_ipv6(const struct route_table *table,
}
/* Lookup same prefix node. Return NULL when we can't find route. */
struct route_node *route_node_lookup(const struct route_table *table,
struct route_node *route_node_lookup(struct route_table *table,
union prefixconstptr pu)
{
struct route_node rn, *node;
@ -260,7 +260,7 @@ struct route_node *route_node_lookup(const struct route_table *table,
}
/* Lookup same prefix node. Return NULL when we can't find route. */
struct route_node *route_node_lookup_maynull(const struct route_table *table,
struct route_node *route_node_lookup_maynull(struct route_table *table,
union prefixconstptr pu)
{
struct route_node rn, *node;
@ -272,7 +272,7 @@ struct route_node *route_node_lookup_maynull(const struct route_table *table,
}
/* Add node to routing table. */
struct route_node *route_node_get(struct route_table *const table,
struct route_node *route_node_get(struct route_table *table,
union prefixconstptr pu)
{
struct route_node search;
@ -471,7 +471,7 @@ struct route_node *route_next_until(struct route_node *node,
return NULL;
}
unsigned long route_table_count(const struct route_table *table)
unsigned long route_table_count(struct route_table *table)
{
return table->count;
}
@ -606,7 +606,7 @@ static struct route_node *route_get_subtree_next(struct route_node *node)
* @see route_table_get_next
*/
static struct route_node *
route_table_get_next_internal(const struct route_table *table,
route_table_get_next_internal(struct route_table *table,
const struct prefix *p)
{
struct route_node *node, *tmp_node;
@ -707,7 +707,7 @@ route_table_get_next_internal(const struct route_table *table,
* Find the node that occurs after the given prefix in order of
* iteration.
*/
struct route_node *route_table_get_next(const struct route_table *table,
struct route_node *route_table_get_next(struct route_table *table,
union prefixconstptr pu)
{
const struct prefix *p = pu.p;

View file

@ -198,26 +198,29 @@ static inline void route_table_set_info(struct route_table *table, void *d)
table->info = d;
}
extern void route_table_finish(struct route_table *table);
extern struct route_node *route_top(struct route_table *table);
extern struct route_node *route_next(struct route_node *node);
extern struct route_node *route_next_until(struct route_node *node,
const struct route_node *limit);
extern struct route_node *route_node_get(struct route_table *const table,
union prefixconstptr pu);
extern struct route_node *route_node_lookup(const struct route_table *table,
union prefixconstptr pu);
extern struct route_node *
route_node_lookup_maynull(const struct route_table *table,
union prefixconstptr pu);
extern struct route_node *route_node_match(const struct route_table *table,
union prefixconstptr pu);
extern struct route_node *route_node_match_ipv4(const struct route_table *table,
const struct in_addr *addr);
extern struct route_node *route_node_match_ipv6(const struct route_table *table,
const struct in6_addr *addr);
/* ext_pure => extern __attribute__((pure))
* does not modify memory (but depends on mem), allows compiler to optimize
*/
extern unsigned long route_table_count(const struct route_table *table);
extern void route_table_finish(struct route_table *table);
ext_pure struct route_node *route_top(struct route_table *table);
ext_pure struct route_node *route_next(struct route_node *node);
ext_pure struct route_node *route_next_until(struct route_node *node,
const struct route_node *limit);
extern struct route_node *route_node_get(struct route_table *table,
union prefixconstptr pu);
ext_pure struct route_node *route_node_lookup(struct route_table *table,
union prefixconstptr pu);
ext_pure struct route_node *route_node_lookup_maynull(struct route_table *table,
union prefixconstptr pu);
ext_pure struct route_node *route_node_match(struct route_table *table,
union prefixconstptr pu);
ext_pure struct route_node *route_node_match_ipv4(struct route_table *table,
const struct in_addr *addr);
ext_pure struct route_node *route_node_match_ipv6(struct route_table *table,
const struct in6_addr *addr);
ext_pure unsigned long route_table_count(struct route_table *table);
extern struct route_node *route_node_create(route_table_delegate_t *delegate,
struct route_table *table);
@ -226,10 +229,10 @@ extern void route_node_destroy(route_table_delegate_t *delegate,
struct route_table *table,
struct route_node *node);
extern struct route_node *route_table_get_next(const struct route_table *table,
union prefixconstptr pu);
extern int route_table_prefix_iter_cmp(const struct prefix *p1,
const struct prefix *p2);
ext_pure struct route_node *route_table_get_next(struct route_table *table,
union prefixconstptr pu);
ext_pure int route_table_prefix_iter_cmp(const struct prefix *p1,
const struct prefix *p2);
/*
* Iterator functions.