Skip to content

Commit

Permalink
Staging: batman-adv: Remove hashdata_compare_cb from hash
Browse files Browse the repository at this point in the history
Function pointers cannot be inlined by a compiler and thus always has
the overhead of an call. hashdata_compare_cb's are one of the most often
called function pointers and its overhead must kept relative low.

As first step, every function which uses this function pointer takes it
as parameter instead of storing it inside the hash abstraction
structure.

This not generate any performance gain right now. The called functions
must also be able to be inlined by the calling functions to enable
inlining of the function pointer.

Reported-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Sven Eckelmann authored and Greg Kroah-Hartman committed Nov 29, 2010
1 parent 1341a00 commit 51f3d8a
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 62 deletions.
2 changes: 1 addition & 1 deletion drivers/staging/batman-adv/TODO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
* remove own list functionality from hash
* use hlist_head, hlist_node in hash
* don't use callbacks for compare+choose in hash
* don't use callbacks for choose in hash
* think about more efficient ways instead of abstraction of hash
* Request a new review
* Process the comments from the review
Expand Down
25 changes: 13 additions & 12 deletions drivers/staging/batman-adv/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ struct hash_it_t *hash_iterate(struct hashtable_t *hash,
}

/* allocates and clears the hash */
struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
hashdata_choose_cb choose)
struct hashtable_t *hash_new(int size, hashdata_choose_cb choose)
{
struct hashtable_t *hash;

Expand All @@ -157,14 +156,13 @@ struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,

hash_init(hash);

hash->compare = compare;
hash->choose = choose;

return hash;
}

/* adds data to the hashtable. returns 0 on success, -1 on error */
int hash_add(struct hashtable_t *hash, void *data)
int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare, void *data)
{
int index;
struct element_t *bucket, *prev_bucket = NULL;
Expand All @@ -176,7 +174,7 @@ int hash_add(struct hashtable_t *hash, void *data)
bucket = hash->table[index];

while (bucket != NULL) {
if (hash->compare(bucket->data, data))
if (compare(bucket->data, data))
return -1;

prev_bucket = bucket;
Expand Down Expand Up @@ -204,7 +202,8 @@ int hash_add(struct hashtable_t *hash, void *data)

/* finds data, based on the key in keydata. returns the found data on success,
* or NULL on error */
void *hash_find(struct hashtable_t *hash, void *keydata)
void *hash_find(struct hashtable_t *hash, hashdata_compare_cb compare,
void *keydata)
{
int index;
struct element_t *bucket;
Expand All @@ -216,7 +215,7 @@ void *hash_find(struct hashtable_t *hash, void *keydata)
bucket = hash->table[index];

while (bucket != NULL) {
if (hash->compare(bucket->data, keydata))
if (compare(bucket->data, keydata))
return bucket->data;

bucket = bucket->next;
Expand Down Expand Up @@ -250,7 +249,8 @@ void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t)
* can remove the used structure yourself, or NULL on error . data could be the
* structure you use with just the key filled, we just need the key for
* comparing. */
void *hash_remove(struct hashtable_t *hash, void *data)
void *hash_remove(struct hashtable_t *hash, hashdata_compare_cb compare,
void *data)
{
struct hash_it_t hash_it_t;

Expand All @@ -259,7 +259,7 @@ void *hash_remove(struct hashtable_t *hash, void *data)
hash_it_t.prev_bucket = NULL;

while (hash_it_t.bucket != NULL) {
if (hash->compare(hash_it_t.bucket->data, data)) {
if (compare(hash_it_t.bucket->data, data)) {
hash_it_t.first_bucket =
(hash_it_t.bucket ==
hash->table[hash_it_t.index] ?
Expand All @@ -276,14 +276,15 @@ void *hash_remove(struct hashtable_t *hash, void *data)

/* resize the hash, returns the pointer to the new hash or NULL on
* error. removes the old hash on success. */
struct hashtable_t *hash_resize(struct hashtable_t *hash, int size)
struct hashtable_t *hash_resize(struct hashtable_t *hash,
hashdata_compare_cb compare, int size)
{
struct hashtable_t *new_hash;
struct element_t *bucket;
int i;

/* initialize a new hash with the new size */
new_hash = hash_new(size, hash->compare, hash->choose);
new_hash = hash_new(size, hash->choose);

if (new_hash == NULL)
return NULL;
Expand All @@ -293,7 +294,7 @@ struct hashtable_t *hash_resize(struct hashtable_t *hash, int size)
bucket = hash->table[i];

while (bucket != NULL) {
hash_add(new_hash, bucket->data);
hash_add(new_hash, compare, bucket->data);
bucket = bucket->next;
}
}
Expand Down
23 changes: 12 additions & 11 deletions drivers/staging/batman-adv/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
.prev_bucket = NULL, \
.first_bucket = NULL }


/* callback to a compare function. should
* compare 2 element datas for their keys,
* return 0 if same and not 0 if not
* same */
typedef int (*hashdata_compare_cb)(void *, void *);
typedef int (*hashdata_choose_cb)(void *, int);
typedef void (*hashdata_free_cb)(void *, void *);
Expand All @@ -48,18 +51,13 @@ struct hashtable_t {
struct element_t **table; /* the hashtable itself, with the buckets */
int elements; /* number of elements registered */
int size; /* size of hashtable */
hashdata_compare_cb compare;/* callback to a compare function. should
* compare 2 element datas for their keys,
* return 0 if same and not 0 if not
* same */
hashdata_choose_cb choose; /* the hashfunction, should return an index
* based on the key in the data of the first
* argument and the size the second */
};

/* allocates and clears the hash */
struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
hashdata_choose_cb choose);
struct hashtable_t *hash_new(int size, hashdata_choose_cb choose);

/* remove bucket (this might be used in hash_iterate() if you already found the
* bucket you want to delete and don't need the overhead to find it again with
Expand All @@ -76,21 +74,24 @@ void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb, void *arg);
void hash_destroy(struct hashtable_t *hash);

/* adds data to the hashtable. returns 0 on success, -1 on error */
int hash_add(struct hashtable_t *hash, void *data);
int hash_add(struct hashtable_t *hash, hashdata_compare_cb compare, void *data);

/* removes data from hash, if found. returns pointer do data on success, so you
* can remove the used structure yourself, or NULL on error . data could be the
* structure you use with just the key filled, we just need the key for
* comparing. */
void *hash_remove(struct hashtable_t *hash, void *data);
void *hash_remove(struct hashtable_t *hash, hashdata_compare_cb compare,
void *data);

/* finds data, based on the key in keydata. returns the found data on success,
* or NULL on error */
void *hash_find(struct hashtable_t *hash, void *keydata);
void *hash_find(struct hashtable_t *hash, hashdata_compare_cb compare,
void *keydata);

/* resize the hash, returns the pointer to the new hash or NULL on
* error. removes the old hash on success */
struct hashtable_t *hash_resize(struct hashtable_t *hash, int size);
struct hashtable_t *hash_resize(struct hashtable_t *hash,
hashdata_compare_cb compare, int size);

/* iterate though the hash. first element is selected with iter_in NULL. use
* the returned iterator to access the elements until hash_it_t returns NULL. */
Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/batman-adv/icmp_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "send.h"
#include "types.h"
#include "hash.h"
#include "originator.h"
#include "hard-interface.h"


Expand Down Expand Up @@ -225,6 +226,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,

spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
compare_orig,
icmp_packet->dst));

if (!orig_node)
Expand Down
7 changes: 0 additions & 7 deletions drivers/staging/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,6 @@ void dec_module_count(void)
module_put(THIS_MODULE);
}

/* returns 1 if they are the same originator */

int compare_orig(void *data1, void *data2)
{
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}

/* hashfunction to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
int choose_orig(void *data, int32_t size)
Expand Down
1 change: 0 additions & 1 deletion drivers/staging/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ int mesh_init(struct net_device *soft_iface);
void mesh_free(struct net_device *soft_iface);
void inc_module_count(void);
void dec_module_count(void);
int compare_orig(void *data1, void *data2);
int choose_orig(void *data, int32_t size);
int is_my_mac(uint8_t *addr);
int is_bcast(uint8_t *addr);
Expand Down
9 changes: 5 additions & 4 deletions drivers/staging/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int originator_init(struct bat_priv *bat_priv)
return 1;

spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
bat_priv->orig_hash = hash_new(128, compare_orig, choose_orig);
bat_priv->orig_hash = hash_new(128, choose_orig);

if (!bat_priv->orig_hash)
goto err;
Expand Down Expand Up @@ -129,7 +129,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
struct hashtable_t *swaphash;
int size;

orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, addr));
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
compare_orig, addr));

if (orig_node)
return orig_node;
Expand Down Expand Up @@ -166,11 +167,11 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
if (!orig_node->bcast_own_sum)
goto free_bcast_own;

if (hash_add(bat_priv->orig_hash, orig_node) < 0)
if (hash_add(bat_priv->orig_hash, compare_orig, orig_node) < 0)
goto free_bcast_own_sum;

if (bat_priv->orig_hash->elements * 4 > bat_priv->orig_hash->size) {
swaphash = hash_resize(bat_priv->orig_hash,
swaphash = hash_resize(bat_priv->orig_hash, compare_orig,
bat_priv->orig_hash->size * 2);

if (!swaphash)
Expand Down
7 changes: 7 additions & 0 deletions drivers/staging/batman-adv/originator.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@ int orig_seq_print_text(struct seq_file *seq, void *offset);
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);


/* returns 1 if they are the same originator */
static inline int compare_orig(void *data1, void *data2)
{
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}

#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
15 changes: 10 additions & 5 deletions drivers/staging/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
compare_orig,
icmp_packet->orig));
ret = NET_RX_DROP;

Expand Down Expand Up @@ -873,7 +874,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, icmp_packet->orig));
hash_find(bat_priv->orig_hash, compare_orig,
icmp_packet->orig));
ret = NET_RX_DROP;

if ((orig_node != NULL) &&
Expand Down Expand Up @@ -967,7 +969,8 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, icmp_packet->dst));
hash_find(bat_priv->orig_hash, compare_orig,
icmp_packet->dst));

if ((orig_node != NULL) &&
(orig_node->router != NULL)) {
Expand Down Expand Up @@ -1038,7 +1041,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
router_orig->orig, ETH_ALEN) == 0) {
primary_orig_node = router_orig;
} else {
primary_orig_node = hash_find(bat_priv->orig_hash,
primary_orig_node = hash_find(bat_priv->orig_hash, compare_orig,
router_orig->primary_addr);

if (!primary_orig_node)
Expand Down Expand Up @@ -1144,7 +1147,8 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
/* get routing information */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, unicast_packet->dest));
hash_find(bat_priv->orig_hash, compare_orig,
unicast_packet->dest));

router = find_router(bat_priv, orig_node, recv_if);

Expand Down Expand Up @@ -1290,7 +1294,8 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)

spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, bcast_packet->orig));
hash_find(bat_priv->orig_hash, compare_orig,
bcast_packet->orig));

if (orig_node == NULL) {
spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
Expand Down
1 change: 1 addition & 0 deletions drivers/staging/batman-adv/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "types.h"
#include "vis.h"
#include "aggregation.h"
#include "originator.h"


static void send_outstanding_bcast_packet(struct work_struct *work);
Expand Down
Loading

0 comments on commit 51f3d8a

Please sign in to comment.