o list.h: improve hlist

This changeset:

1. Implements hlist_add_after
2. uses prefetch in hlist_for_each, using a trick that ends up being
   equivalent to having the prefetch instruction in the first block
   of the hlist_for_each for block, the compiler optimizes the second
   "test" away, as its result is constant
3. implements hlist_for_each_entry and hlist_for_each_entry safe,
   using a struct hlist_node as iterator to avoid the extra branches a
   similar implementation to list_for_each_entry would have if used
   a typed iterator, but while avoiding having to have the explicit
   hlist_entry as in hlist_for_each.

4. Converts the hlist_for_each users that had explicit prefetches, i.e.
   removed the explicit prefetch

5. fix a harmless list_entry use in a hlist_for_each in inode.c
   
parent 542f238e
......@@ -983,8 +983,6 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
struct dentry *dentry;
unsigned long move_count;
struct qstr * qstr;
prefetch(node->next);
smp_read_barrier_depends();
dentry = hlist_entry(node, struct dentry, d_hash);
......@@ -1072,7 +1070,6 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
spin_lock(&dcache_lock);
base = d_hash(dparent, dentry->d_name.hash);
hlist_for_each(lhp,base) {
prefetch(lhp->next);
/* read_barrier_depends() not required for d_hash list
* as it is parsed under dcache_lock
*/
......
......@@ -484,7 +484,6 @@ static struct inode * find_inode(struct super_block * sb, struct hlist_head *hea
repeat:
hlist_for_each (node, head) {
prefetch(node->next);
inode = hlist_entry(node, struct inode, i_hash);
if (inode->i_sb != sb)
continue;
......@@ -510,8 +509,7 @@ static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head
repeat:
hlist_for_each (node, head) {
prefetch(node->next);
inode = list_entry(node, struct inode, i_hash);
inode = hlist_entry(node, struct inode, i_hash);
if (inode->i_ino != ino)
continue;
if (inode->i_sb != sb)
......
......@@ -443,17 +443,50 @@ static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node
*(n->pprev) = n;
}
static __inline__ void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
*(next->pprev) = n;
n->next = next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
/* Cannot easily do prefetch unfortunately */
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos; \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; n = pos ? pos->next : 0, pos; \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#else
#warning "don't include kernel headers in userspace"
#endif /* __KERNEL__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment