There are quite a few places in the kernel which implement a hashtable
in a very similar way. Instead of having implementations of a hashtable
all over the kernel, we can re-use the code.
This patch series introduces a very simple hashtable implementation, and
modifies three (random) modules to use it. I've limited it to 3 only
so that it would be easy to review and modify, and to show that even
at this number we already eliminate a big amount of duplicated code.
If this basic hashtable looks ok, future code will include:
- RCU support
- Self locking (list_bl?)
- Converting more code to use the hashtable
Changes in V3:
- Address review comments by Tejun Heo, Josh Triplett, Eric Beiderman,
Mathieu Desnoyers, Eric Dumazet and Linus Torvalds.
- Removed hash_get due to being too Gandalf.
- Rewrote the user namespaces hash implementation.
- Hashtable went back to being a simple array of buckets, but without any
of the macro tricks to get the size automatically.
- Optimize hasing if key is 32 bits long.
Changes in V2:
- Address review comments by Tejun Heo, Josh Triplett and Eric Beiderman (Thanks all!).
- Rebase on top of latest master.
- Convert more places to use the hashtable. Hopefully it will trigger more reviews by
touching more subsystems.
Sasha Levin (7):
hashtable: introduce a small and naive hashtable
user_ns: use new hashtable implementation
mm,ksm: use new hashtable implementation
workqueue: use new hashtable implementation
mm/huge_memory: use new hashtable implementation
tracepoint: use new hashtable implementation
net,9p: use new hashtable implementation
include/linux/hashtable.h | 82 +++++++++++++++++++++++++++++++++++++++++
kernel/tracepoint.c | 26 +++++--------
kernel/user.c | 35 ++++++++----------
kernel/workqueue.c | 89 +++++++++------------------------------------
mm/huge_memory.c | 56 +++++++---------------------
mm/ksm.c | 31 +++++++---------
net/9p/error.c | 21 +++++------
7 files changed, 162 insertions(+), 178 deletions(-)
create mode 100644 include/linux/hashtable.h
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
This hashtable implementation is using hlist buckets to provide a simple
hashtable to prevent it from getting reimplemented all over the kernel.
Signed-off-by: Sasha Levin <redacted>
---
include/linux/hashtable.h | 82 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 82 insertions(+), 0 deletions(-)
create mode 100644 include/linux/hashtable.h
@@ -0,0 +1,82 @@+/*+*Hashtableimplementation+*(C)2012SashaLevin<levinsasha928@gmail.com>+*/++#ifndef _LINUX_HASHTABLE_H+#define _LINUX_HASHTABLE_H++#include<linux/list.h>+#include<linux/types.h>+#include<linux/kernel.h>+#include<linux/hash.h>++#define DEFINE_HASHTABLE(name, bits) \+structhlist_headname[HASH_SIZE(bits)];++#define HASH_SIZE(bits) (1 << (bits))++/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */+#define hash_min(val, bits) ((sizeof(val)==4)?hash_32((val), (bits)):hash_long((val), (bits)))++/**+*hash_init-initializeahashtable+*@hashtable:hashtabletobeinitialized+*@bits:bitcountofhashingfunction+*+*Initializesahashtablewith2**bitsbuckets.+*/+staticinlinevoidhash_init(structhlist_head*hashtable,intbits)+{+inti;++for(i=0;i<HASH_SIZE(bits);i++)+INIT_HLIST_HEAD(hashtable+i);+}++/**+*hash_add-addanobjecttoahashtable+*@hashtable:hashtabletoaddto+*@bits:bitcountusedforhashing+*@node:the&structhlist_nodeoftheobjecttobeadded+*@key:thekeyoftheobjecttobeadded+*/+#define hash_add(hashtable, bits, node, key) \+hlist_add_head(node,&hashtable[hash_min(key,bits)]);++/**+*hash_del-removeanobjectfromahashtable+*@node:&structhlist_nodeoftheobjecttoremove+*/+staticinlinevoidhash_del(structhlist_node*node)+{+hlist_del_init(node);+}++/**+*hash_for_each-iterateoverahashtable+*@name:hashtabletoiterate+*@bits:bitcountofhashingfunctionofthehashtable+*@bkt:integertouseasbucketloopcursor+*@node:the&structlist_headtouseasaloopcursorforeachbucket+*@obj:thetype*touseasaloopcursorforeachbucket+*@member:thenameofthehlist_nodewithinthestruct+*/+#define hash_for_each(name, bits, bkt, node, obj, member) \+for(bkt=0;bkt<HASH_SIZE(bits);bkt++)\+hlist_for_each_entry(obj,node,&name[i],member)++/**+*hash_for_each_possible-iterateoverallpossibleobjectsforagiverkey+*@name:hashtabletoiterate+*@obj:thetype*touseasaloopcursorforeachbucke+*@bits:bitcountofhashingfunctionofthehashtable+*@node:the&structlist_headtouseasaloopcursorforeachbucket+*@member:thenameofthehlist_nodewithinthestruct+*@key:thekeyoftheobjectstoiterateover+*/+#define hash_for_each_possible(name, obj, bits, node, member, key) \+hlist_for_each_entry(obj,node,\+&name[hash_min(key,bits)],member)++#endif
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Switch user_ns to use the new hashtable implementation. This reduces the amount of
generic unrelated code in user_ns.
Signed-off-by: Sasha Levin <redacted>
---
kernel/user.c | 35 +++++++++++++++--------------------
1 files changed, 15 insertions(+), 20 deletions(-)
@@ -196,17 +194,14 @@ out_unlock:staticint__inituid_cache_init(void){-intn;-uid_cachep=kmem_cache_create("uid_cache",sizeof(structuser_struct),0,SLAB_HWCACHE_ALIGN|SLAB_PANIC,NULL);-for(n=0;n<UIDHASH_SZ;++n)-INIT_HLIST_HEAD(uidhash_table+n);+hash_init(uidhash_table,UIDHASH_BITS);/* Insert the root user immediately (init already runs as root) */spin_lock_irq(&uidhash_lock);-uid_hash_insert(&root_user,uidhashentry(GLOBAL_ROOT_UID));+uid_hash_insert(&root_user);spin_unlock_irq(&uidhash_lock);return0;
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Switch ksm to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the ksm module.
Signed-off-by: Sasha Levin <redacted>
---
mm/ksm.c | 31 +++++++++++++------------------
1 files changed, 13 insertions(+), 18 deletions(-)
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From: Sasha Levin <redacted>
Switch workqueues to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the workqueues.
Signed-off-by: Sasha Levin <redacted>
---
kernel/workqueue.c | 91 +++++++++++-----------------------------------------
1 files changed, 19 insertions(+), 72 deletions(-)
@@ -82,8 +83,6 @@ enum {NR_WORKER_POOLS=2,/* # worker pools per gcwq */BUSY_WORKER_HASH_ORDER=6,/* 64 pointers */-BUSY_WORKER_HASH_SIZE=1<<BUSY_WORKER_HASH_ORDER,-BUSY_WORKER_HASH_MASK=BUSY_WORKER_HASH_SIZE-1,MAX_IDLE_WORKERS_RATIO=4,/* 1/4 of busy can be idle */IDLE_WORKER_TIMEOUT=300*HZ,/* keep idle ones for 5 mins */
@@ -180,7 +179,7 @@ struct global_cwq {unsignedintflags;/* L: GCWQ_* flags *//* workers are chained either in busy_hash or pool idle_list */-structhlist_headbusy_hash[BUSY_WORKER_HASH_SIZE];+DEFINE_HASHTABLE(busy_hash,BUSY_WORKER_HASH_ORDER);/* L: hash of busy workers */structworker_poolpools[2];/* normal and highpri pools */
@@ -288,8 +287,8 @@ EXPORT_SYMBOL_GPL(system_nrt_freezable_wq);(pool)<&(gcwq)->pools[NR_WORKER_POOLS];(pool)++)#define for_each_busy_worker(worker, i, pos, gcwq) \-for(i=0;i<BUSY_WORKER_HASH_SIZE;i++)\-hlist_for_each_entry(worker,pos,&gcwq->busy_hash[i],hentry)+hash_for_each(gcwq->busy_hash,BUSY_WORKER_HASH_ORDER,i,pos,\+worker,hentry)staticinlineint__next_gcwq_cpu(intcpu,conststructcpumask*mask,unsignedintsw)
@@ -822,63 +821,6 @@ static inline void worker_clr_flags(struct worker *worker, unsigned int flags)}/**-*busy_worker_head-returnthebusyhashheadforawork-*@gcwq:gcwqofinterest-*@work:worktobehashed-*-*Returnhashheadof@gcwqfor@work.-*-*CONTEXT:-*spin_lock_irq(gcwq->lock).-*-*RETURNS:-*Pointertothehashhead.-*/-staticstructhlist_head*busy_worker_head(structglobal_cwq*gcwq,-structwork_struct*work)-{-constintbase_shift=ilog2(sizeof(structwork_struct));-unsignedlongv=(unsignedlong)work;--/* simple shift and fold hash, do we need something better? */-v>>=base_shift;-v+=v>>BUSY_WORKER_HASH_ORDER;-v&=BUSY_WORKER_HASH_MASK;--return&gcwq->busy_hash[v];-}--/**-*__find_worker_executing_work-findworkerwhichisexecutingawork-*@gcwq:gcwqofinterest-*@bwh:hashheadasreturnedbybusy_worker_head()-*@work:worktofindworkerfor-*-*Findaworkerwhichisexecuting@workon@gcwq.@bwhshouldbe-*thehashheadobtainedbycallingbusy_worker_head()withthesame-*work.-*-*CONTEXT:-*spin_lock_irq(gcwq->lock).-*-*RETURNS:-*Pointertoworkerwhichisexecuting@workiffound,NULL-*otherwise.-*/-staticstructworker*__find_worker_executing_work(structglobal_cwq*gcwq,-structhlist_head*bwh,-structwork_struct*work)-{-structworker*worker;-structhlist_node*tmp;--hlist_for_each_entry(worker,tmp,bwh,hentry)-if(worker->current_work==work)-returnworker;-returnNULL;-}--/***find_worker_executing_work-findworkerwhichisexecutingawork*@gcwq:gcwqofinterest*@work:worktofindworkerfor
@@ -1972,7 +1920,8 @@ __acquires(&gcwq->lock)/* claim and process */debug_work_deactivate(work);-hlist_add_head(&worker->hentry,bwh);+hash_add(gcwq->busy_hash,BUSY_WORKER_HASH_ORDER,&worker->hentry,+(unsignedlong)worker);worker->current_work=work;worker->current_cwq=cwq;work_color=get_work_color(work);
@@ -3704,8 +3652,7 @@ static int __init init_workqueues(void)gcwq->cpu=cpu;gcwq->flags|=GCWQ_DISASSOCIATED;-for(i=0;i<BUSY_WORKER_HASH_SIZE;i++)-INIT_HLIST_HEAD(&gcwq->busy_hash[i]);+hash_init(gcwq->busy_hash,BUSY_WORKER_HASH_ORDER);for_each_worker_pool(pool,gcwq){pool->gcwq=gcwq;
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Switch hugemem to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the hugemem.
This also removes the dymanic allocation of the hash table. The size of the table is
constant so there's no point in paying the price of an extra dereference when accessing
it.
Signed-off-by: Sasha Levin <redacted>
---
mm/huge_memory.c | 56 +++++++++++++----------------------------------------
1 files changed, 14 insertions(+), 42 deletions(-)
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Switch 9p error table to use the new hashtable implementation. This reduces the amount of
generic unrelated code in 9p.
Signed-off-by: Sasha Levin <redacted>
---
net/9p/error.c | 21 ++++++++++-----------
1 files changed, 10 insertions(+), 11 deletions(-)
@@ -223,13 +222,13 @@ int p9_errstr2errno(char *errstr, int len)interrno;structhlist_node*p;structerrormap*c;-intbucket;+u32hash;errno=0;p=NULL;c=NULL;-bucket=jhash(errstr,len,0)%ERRHASHSZ;-hlist_for_each_entry(c,p,&hash_errmap[bucket],list){+hash=jhash(errstr,len,0);+hash_for_each_possible(hash_errmap,c,ERR_HASH_BITS,p,list,hash){if(c->namelen==len&&!memcmp(c->name,errstr,len)){errno=c->val;break;
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Switch tracepoints to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the tracepoints.
Signed-off-by: Sasha Levin <redacted>
---
kernel/tracepoint.c | 26 ++++++++++----------------
1 files changed, 10 insertions(+), 16 deletions(-)
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
Switch workqueues to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the workqueues.
Signed-off-by: Sasha Levin <redacted>
---
kernel/workqueue.c | 89 ++++++++++-----------------------------------------
1 files changed, 18 insertions(+), 71 deletions(-)
@@ -82,8 +83,6 @@ enum {NR_WORKER_POOLS=2,/* # worker pools per gcwq */BUSY_WORKER_HASH_ORDER=6,/* 64 pointers */-BUSY_WORKER_HASH_SIZE=1<<BUSY_WORKER_HASH_ORDER,-BUSY_WORKER_HASH_MASK=BUSY_WORKER_HASH_SIZE-1,MAX_IDLE_WORKERS_RATIO=4,/* 1/4 of busy can be idle */IDLE_WORKER_TIMEOUT=300*HZ,/* keep idle ones for 5 mins */
@@ -180,7 +179,7 @@ struct global_cwq {unsignedintflags;/* L: GCWQ_* flags *//* workers are chained either in busy_hash or pool idle_list */-structhlist_headbusy_hash[BUSY_WORKER_HASH_SIZE];+DEFINE_HASHTABLE(busy_hash,BUSY_WORKER_HASH_ORDER);/* L: hash of busy workers */structworker_poolpools[2];/* normal and highpri pools */
@@ -288,8 +287,8 @@ EXPORT_SYMBOL_GPL(system_nrt_freezable_wq);(pool)<&(gcwq)->pools[NR_WORKER_POOLS];(pool)++)#define for_each_busy_worker(worker, i, pos, gcwq) \-for(i=0;i<BUSY_WORKER_HASH_SIZE;i++)\-hlist_for_each_entry(worker,pos,&gcwq->busy_hash[i],hentry)+hash_for_each(gcwq->busy_hash,BUSY_WORKER_HASH_ORDER,i,pos,\+worker,hentry)staticinlineint__next_gcwq_cpu(intcpu,conststructcpumask*mask,unsignedintsw)
@@ -822,63 +821,6 @@ static inline void worker_clr_flags(struct worker *worker, unsigned int flags)}/**-*busy_worker_head-returnthebusyhashheadforawork-*@gcwq:gcwqofinterest-*@work:worktobehashed-*-*Returnhashheadof@gcwqfor@work.-*-*CONTEXT:-*spin_lock_irq(gcwq->lock).-*-*RETURNS:-*Pointertothehashhead.-*/-staticstructhlist_head*busy_worker_head(structglobal_cwq*gcwq,-structwork_struct*work)-{-constintbase_shift=ilog2(sizeof(structwork_struct));-unsignedlongv=(unsignedlong)work;--/* simple shift and fold hash, do we need something better? */-v>>=base_shift;-v+=v>>BUSY_WORKER_HASH_ORDER;-v&=BUSY_WORKER_HASH_MASK;--return&gcwq->busy_hash[v];-}--/**-*__find_worker_executing_work-findworkerwhichisexecutingawork-*@gcwq:gcwqofinterest-*@bwh:hashheadasreturnedbybusy_worker_head()-*@work:worktofindworkerfor-*-*Findaworkerwhichisexecuting@workon@gcwq.@bwhshouldbe-*thehashheadobtainedbycallingbusy_worker_head()withthesame-*work.-*-*CONTEXT:-*spin_lock_irq(gcwq->lock).-*-*RETURNS:-*Pointertoworkerwhichisexecuting@workiffound,NULL-*otherwise.-*/-staticstructworker*__find_worker_executing_work(structglobal_cwq*gcwq,-structhlist_head*bwh,-structwork_struct*work)-{-structworker*worker;-structhlist_node*tmp;--hlist_for_each_entry(worker,tmp,bwh,hentry)-if(worker->current_work==work)-returnworker;-returnNULL;-}--/***find_worker_executing_work-findworkerwhichisexecutingawork*@gcwq:gcwqofinterest*@work:worktofindworkerfor
@@ -1972,7 +1920,8 @@ __acquires(&gcwq->lock)/* claim and process */debug_work_deactivate(work);-hlist_add_head(&worker->hentry,bwh);+hash_add(gcwq->busy_hash,BUSY_WORKER_HASH_ORDER,&worker->hentry,+(unsignedlong)worker);worker->current_work=work;worker->current_cwq=cwq;work_color=get_work_color(work);
@@ -3704,8 +3652,7 @@ static int __init init_workqueues(void)gcwq->cpu=cpu;gcwq->flags|=GCWQ_DISASSOCIATED;-for(i=0;i<BUSY_WORKER_HASH_SIZE;i++)-INIT_HLIST_HEAD(&gcwq->busy_hash[i]);+hash_init(gcwq->busy_hash,BUSY_WORKER_HASH_ORDER);for_each_worker_pool(pool,gcwq){pool->gcwq=gcwq;
--
1.7.8.6
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits) ((sizeof(val)==4)?hash_32((val), (bits)):hash_long((val), (bits)))
This is a pretty long line. It doesn't use normal kernel spacing
style and it has unnecessary parentheses.
Maybe:
#define hash_min(val, bits) \
(sizeof(val) == 4 ? hash_32(val, bits) : hash_long(val, bits))
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ * @bits: bit count of hashing function
+ *
+ * Initializes a hash table with 2**bits buckets.
+ */
+static inline void hash_init(struct hlist_head *hashtable, int bits)
+{
+ int i;
+
+ for (i = 0; i < HASH_SIZE(bits); i++)
+ INIT_HLIST_HEAD(hashtable + i);
+}
Maybe use a struct hlist_head *last_hash_entry as a loop variable
{
struct hlist_head *eo_hash = hashtable + HASH_SIZE(bits);
while (hashtable < eo_hash)
INIT_HLIST_HEAD(hashtable++);
}
The compiler might generate the same code anyway...
[]
+/**
+ * hash_for_each_possible - iterate over all possible objects for a giver key
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each bucke
bucket
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
From: Joe Perches <joe@perches.com> Date: 2012-08-07 01:19:21
On Tue, 2012-08-07 at 02:45 +0200, Sasha Levin wrote:
From: Sasha Levin <redacted>
Switch workqueues to use the new hashtable implementation. This reduces the amount of
generic unrelated code in the workqueues.
* @worker: self
* @work: work to process
*
- * Process @work. This function contains all the logics necessary to
+ * Process @work. This? function contains all the logics necessary to
Odd ? and the grammar also seems odd.
* process a single work including synchronization against and
* interaction with other workers on the same cpu, queueing and
* flushing. As long as context requirement is met, any worker can
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
This hashtable implementation is using hlist buckets to provide a simple
hashtable to prevent it from getting reimplemented all over the kernel.
Signed-off-by: Sasha Levin <redacted>
---
include/linux/hashtable.h | 82 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 82 insertions(+), 0 deletions(-)
create mode 100644 include/linux/hashtable.h
@@ -0,0 +1,82 @@+/*+*Hashtableimplementation+*(C)2012SashaLevin<levinsasha928@gmail.com>+*/++#ifndef _LINUX_HASHTABLE_H+#define _LINUX_HASHTABLE_H++#include<linux/list.h>+#include<linux/types.h>+#include<linux/kernel.h>+#include<linux/hash.h>++#define DEFINE_HASHTABLE(name, bits) \+structhlist_headname[HASH_SIZE(bits)];++#define HASH_SIZE(bits) (1 << (bits))++/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */+#define hash_min(val, bits) ((sizeof(val)==4)?hash_32((val), (bits)):hash_long((val), (bits)))++/**+*hash_init-initializeahashtable+*@hashtable:hashtabletobeinitialized+*@bits:bitcountofhashingfunction+*+*Initializesahashtablewith2**bitsbuckets.+*/+staticinlinevoidhash_init(structhlist_head*hashtable,intbits)+{+inti;++for(i=0;i<HASH_SIZE(bits);i++)+INIT_HLIST_HEAD(hashtable+i);+}++/**+*hash_add-addanobjecttoahashtable+*@hashtable:hashtabletoaddto+*@bits:bitcountusedforhashing+*@node:the&structhlist_nodeoftheobjecttobeadded+*@key:thekeyoftheobjecttobeadded+*/+#define hash_add(hashtable, bits, node, key) \+hlist_add_head(node,&hashtable[hash_min(key,bits)]);++/**+*hash_del-removeanobjectfromahashtable+*@node:&structhlist_nodeoftheobjecttoremove+*/+staticinlinevoidhash_del(structhlist_node*node)+{+hlist_del_init(node);+}++/**+*hash_for_each-iterateoverahashtable+*@name:hashtabletoiterate+*@bits:bitcountofhashingfunctionofthehashtable+*@bkt:integertouseasbucketloopcursor+*@node:the&structlist_headtouseasaloopcursorforeachbucket+*@obj:thetype*touseasaloopcursorforeachbucket+*@member:thenameofthehlist_nodewithinthestruct+*/+#define hash_for_each(name, bits, bkt, node, obj, member) \+for(bkt=0;bkt<HASH_SIZE(bits);bkt++)\+hlist_for_each_entry(obj,node,&name[i],member)
Where is the 'i' coming from? maybe &name[bkt]?
+
+/**
+ * hash_for_each_possible - iterate over all possible objects for a giver key
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each bucke
+ * @bits: bit count of hashing function of the hashtable
+ * @node: the &struct list_head to use as a loop cursor for each bucket
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, bits, node, member, key) \
+ hlist_for_each_entry(obj, node, \
+ &name[hash_min(key, bits)], member)
+
+#endif
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bits: bit count of hashing function of the hashtable
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each bucket
+ * @obj: the type * to use as a loop cursor for each bucket
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bits, bkt, node, obj, member) \
+ for (bkt = 0; bkt < HASH_SIZE(bits); bkt++) \
+ hlist_for_each_entry(obj, node, &name[i], member)
Where is the 'i' coming from? maybe &name[bkt]?
Heh, yeah. And the only place that uses this macro had 'i' declared as the loop counter, so it didn't trigger any issues during testing.
Thanks!
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Tue, Aug 07, 2012 at 02:45:10AM +0200, Sasha Levin wrote:
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @bits: bit count used for hashing
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, bits, node, key) \
+ hlist_add_head(node, &hashtable[hash_min(key, bits)]);
Any particular reason to make this a macro rather than a static inline?
Also, even if you do make it a macro, don't include the semicolon.
+/**
+ * hash_for_each_possible - iterate over all possible objects for a giver key
s/giver/given/
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each bucke
s/bucke/bucket/
- Josh Triplett
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
On Tue, Aug 07, 2012 at 02:45:10AM +0200, Sasha Levin wrote:
quoted
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @bits: bit count used for hashing
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, bits, node, key) \
+ hlist_add_head(node, &hashtable[hash_min(key, bits)]);
Any particular reason to make this a macro rather than a static inline?
Yes. As Eric Dumazet pointed out, hash_64() is slower than hash_32() so we should be calling hash_32() if possible (if key size is 32bits long).
This way we can call hash_min() without knowing the key size. See also the definition of hash_min() above.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>