: Introduce a percpu inuse counting array.
Subsystems (3)
PATCH 2/5 : Introduce a percpu inuse counting array.
And redirect sock_prot_inuse_add|_get to use one.
As far as the dereferences are concerned. Before the patch we made 1 dereference to proto->inuse.add call, the call itself and then made a __get_cpu_var() on a static variable. After the patch we make a direct call, then one dereference to proto->inuse_idx and then the same __get_cpu_var() on a still static variable. So this patch doesn't seem to produce performance penalty on SMP.
Besides, add a sanity check into inuse_idx generator.
This is net per-net yet, but I will deliberately make this case separated from NET_NS=n, since it'll cost us one-or-two more dereferences to get the struct net and the inuse counter.
Signed-off-by Pavel Emelyanov <[email protected]>
--- include/net/sock.h | 13 +++++-------- net/core/sock.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-)
include/net/sock.h +5 -8
@@ -639,18 +639,15 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)# define DEFINE_PROTO_INUSE (NAME ) DEFINE_PCOUNTER(NAME)# define REF_PROTO_INUSE (NAME ) PCOUNTER_MEMBER_INITIALIZER(NAME, .inuse)/* Called with local bh disabled */ -static inline void sock_prot_inuse_add (struct proto *prot,int inc) -{ -pcounter_add (&prot->inuse, inc); -} +extern void sock_prot_inuse_add (struct proto *prot,int inc); +static inline int sock_prot_inuse_init (struct proto *proto) {return pcounter_alloc (&proto->inuse); } -static inline int sock_prot_inuse_get (struct proto *proto) -{ -return pcounter_getval (&proto->inuse); -} + +extern int sock_prot_inuse_get (struct proto *proto); +static inline void sock_prot_inuse_free (struct proto *proto) {pcounter_free (&proto->inuse);
net/core/sock.c +34 -0
@@ -1940,11 +1940,45 @@ EXPORT_SYMBOL(sk_common_release);static DEFINE_RWLOCK (proto_list_lock);static LIST_HEAD (proto_list); +#ifdef CONFIG_PROC_FS +#define PROTO_INUSE_NR 64/* should be enough for the first time */ + +struct prot_inuse { +int val[PROTO_INUSE_NR ]; +}; + +static DEFINE_PER_CPU(struct prot_inuse, prot_inuse); + +void sock_prot_inuse_add (struct proto *prot,int val) +{ +__get_cpu_var (prot_inuse).val[prot->inuse_idx] += val; +} +EXPORT_SYMBOL_GPL (sock_prot_inuse_add); + +int sock_prot_inuse_get (struct proto *prot) +{ +int cpu, idx = prot->inuse_idx; +int res =0 ; + +for_each_possible_cpu (cpu) + res +=per_cpu (prot_inuse, cpu).val[idx]; + +return res >=0 ? res :0 ; +} +EXPORT_SYMBOL_GPL (sock_prot_inuse_get); +#endif +static void assign_proto_idx (struct proto *prot) {#ifdef CONFIG_PROC_FS static unsigned int idx =0 ; +if (unlikely (idx ==PROTO_INUSE_NR -1 )) { +printk (KERN_ERR "PROTO_INUSE_NR exhausted\n" ); + prot->inuse_idx = idx; +return ; + } + prot->inuse_idx = idx++;#endif }
Signature · 1 line
1.5.3.4