linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Peng Zhang <zhangpeng362@huawei.com>
To: <linux-mm@kvack.org>, <linux-kernel@vger.kernel.org>
Cc: <akpm@linux-foundation.org>, <dennisszhou@gmail.com>,
	<shakeelb@google.com>, <jack@suse.cz>, <surenb@google.com>,
	<kent.overstreet@linux.dev>, <mhocko@suse.cz>, <vbabka@suse.cz>,
	<yuzhao@google.com>, <yu.ma@intel.com>,
	<wangkefeng.wang@huawei.com>, <sunnanyong@huawei.com>,
	<zhangpeng362@huawei.com>
Subject: [RFC PATCH 2/3] lazy_percpu_counter: include struct percpu_counter in struct lazy_percpu_counter
Date: Fri, 12 Apr 2024 17:24:40 +0800	[thread overview]
Message-ID: <20240412092441.3112481-3-zhangpeng362@huawei.com> (raw)
In-Reply-To: <20240412092441.3112481-1-zhangpeng362@huawei.com>

From: ZhangPeng <zhangpeng362@huawei.com>

Add the struct percpu_counter fbc to struct lazy_percpu_counter.
Convert the u64 __percpu parameter of the lazy percpu counter function
to the struct percpu_counter parameter to prepare for converting
mm's rss stats into lazy_percpu_counter.

Signed-off-by: ZhangPeng <zhangpeng362@huawei.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
 include/linux/lazy-percpu-counter.h | 16 ++++--
 lib/lazy-percpu-counter.c           | 83 +++++++++++++++++++++++------
 2 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/include/linux/lazy-percpu-counter.h b/include/linux/lazy-percpu-counter.h
index 281b8dd88cb2..03ff24f0128d 100644
--- a/include/linux/lazy-percpu-counter.h
+++ b/include/linux/lazy-percpu-counter.h
@@ -20,15 +20,21 @@
 #define _LINUX_LAZY_PERCPU_COUNTER_H
 
 #include <linux/atomic.h>
+#include <linux/percpu_counter.h>
 #include <asm/percpu.h>
 
 struct lazy_percpu_counter {
 	atomic64_t			v;
 	unsigned long			last_wrap;
+	struct percpu_counter		fbc;
 };
 
-void lazy_percpu_counter_exit(struct lazy_percpu_counter *c);
+void lazy_percpu_counter_destroy_many(struct lazy_percpu_counter *c,
+				      u32 nr_counters);
 void lazy_percpu_counter_add_slowpath(struct lazy_percpu_counter *c, s64 i);
+s64 lazy_percpu_counter_read_positive(struct lazy_percpu_counter *c);
+s64 lazy_percpu_counter_sum(struct lazy_percpu_counter *c);
+s64 lazy_percpu_counter_sum_positive(struct lazy_percpu_counter *c);
 
 /*
  * We use the high bits of the atomic counter for a secondary counter, which is
@@ -48,13 +54,13 @@ void lazy_percpu_counter_add_slowpath(struct lazy_percpu_counter *c, s64 i);
  */
 #define COUNTER_IS_PCPU_BIT		1
 
-static inline u64 __percpu *lazy_percpu_counter_is_pcpu(u64 v)
+static inline struct percpu_counter *lazy_percpu_counter_is_pcpu(u64 v)
 {
 	if (!(v & COUNTER_IS_PCPU_BIT))
 		return NULL;
 
 	v ^= COUNTER_IS_PCPU_BIT;
-	return (u64 __percpu *)(unsigned long)v;
+	return (struct percpu_counter *)(unsigned long)v;
 }
 
 /**
@@ -66,10 +72,10 @@ static inline u64 __percpu *lazy_percpu_counter_is_pcpu(u64 v)
 static inline void lazy_percpu_counter_add(struct lazy_percpu_counter *c, s64 i)
 {
 	u64 v = atomic64_read(&c->v);
-	u64 __percpu *pcpu_v = lazy_percpu_counter_is_pcpu(v);
+	struct percpu_counter *pcpu_v = lazy_percpu_counter_is_pcpu(v);
 
 	if (likely(pcpu_v))
-		this_cpu_add(*pcpu_v, i);
+		percpu_counter_add(pcpu_v, i);
 	else
 		lazy_percpu_counter_add_slowpath(c, i);
 }
diff --git a/lib/lazy-percpu-counter.c b/lib/lazy-percpu-counter.c
index e1914207214d..c360903cc02a 100644
--- a/lib/lazy-percpu-counter.c
+++ b/lib/lazy-percpu-counter.c
@@ -15,45 +15,94 @@ static inline s64 lazy_percpu_counter_atomic_val(s64 v)
 
 static void lazy_percpu_counter_switch_to_pcpu(struct lazy_percpu_counter *c)
 {
-	u64 __percpu *pcpu_v = alloc_percpu_gfp(u64, GFP_ATOMIC|__GFP_NOWARN);
 	u64 old, new, v;
+	unsigned long flags;
+	bool allocated = false;
 
-	if (!pcpu_v)
-		return;
-
+	local_irq_save(flags);
 	preempt_disable();
 	v = atomic64_read(&c->v);
 	do {
-		if (lazy_percpu_counter_is_pcpu(v)) {
-			free_percpu(pcpu_v);
-			return;
+		if (lazy_percpu_counter_is_pcpu(v))
+			break;
+
+		if (!allocated) {
+			if (percpu_counter_init(&c->fbc, 0, GFP_ATOMIC|__GFP_NOWARN))
+				break;
+			allocated = true;
 		}
 
 		old = v;
-		new = (unsigned long)pcpu_v | 1;
+		new = (unsigned long)&c->fbc | 1;
 
-		*this_cpu_ptr(pcpu_v) = lazy_percpu_counter_atomic_val(v);
+		percpu_counter_set(&c->fbc, lazy_percpu_counter_atomic_val(v));
 	} while ((v = atomic64_cmpxchg(&c->v, old, new)) != old);
 	preempt_enable();
+	local_irq_restore(flags);
 }
 
 /**
- * lazy_percpu_counter_exit: Free resources associated with a
- * lazy_percpu_counter
+ * lazy_percpu_counter_destroy_many: Free resources associated with
+ * lazy_percpu_counters
  *
- * @c: counter to exit
+ * @c: counters to exit
+ * @nr_counters: number of counters
  */
-void lazy_percpu_counter_exit(struct lazy_percpu_counter *c)
+void lazy_percpu_counter_destroy_many(struct lazy_percpu_counter *c,
+				      u32 nr_counters)
+{
+	struct percpu_counter *pcpu_v;
+	u32 i;
+
+	for (i = 0; i < nr_counters; i++) {
+		pcpu_v = lazy_percpu_counter_is_pcpu(atomic64_read(&c[i].v));
+		if (pcpu_v)
+			percpu_counter_destroy(pcpu_v);
+	}
+}
+EXPORT_SYMBOL_GPL(lazy_percpu_counter_destroy_many);
+
+s64 lazy_percpu_counter_read_positive(struct lazy_percpu_counter *c)
+{
+	s64 v = atomic64_read(&c->v);
+	struct percpu_counter *pcpu_v = lazy_percpu_counter_is_pcpu(v);
+
+	if (pcpu_v)
+		return percpu_counter_read_positive(pcpu_v);
+
+	return lazy_percpu_counter_atomic_val(v);
+}
+EXPORT_SYMBOL_GPL(lazy_percpu_counter_read_positive);
+
+s64 lazy_percpu_counter_sum(struct lazy_percpu_counter *c)
+{
+	s64 v = atomic64_read(&c->v);
+	struct percpu_counter *pcpu_v = lazy_percpu_counter_is_pcpu(v);
+
+	if (pcpu_v)
+		return percpu_counter_sum(pcpu_v);
+
+	return lazy_percpu_counter_atomic_val(v);
+}
+EXPORT_SYMBOL_GPL(lazy_percpu_counter_sum);
+
+s64 lazy_percpu_counter_sum_positive(struct lazy_percpu_counter *c)
 {
-	free_percpu(lazy_percpu_counter_is_pcpu(atomic64_read(&c->v)));
+	s64 v = atomic64_read(&c->v);
+	struct percpu_counter *pcpu_v = lazy_percpu_counter_is_pcpu(v);
+
+	if (pcpu_v)
+		return percpu_counter_sum_positive(pcpu_v);
+
+	return lazy_percpu_counter_atomic_val(v);
 }
-EXPORT_SYMBOL_GPL(lazy_percpu_counter_exit);
+EXPORT_SYMBOL_GPL(lazy_percpu_counter_sum_positive);
 
 void lazy_percpu_counter_add_slowpath(struct lazy_percpu_counter *c, s64 i)
 {
 	u64 atomic_i;
 	u64 old, v = atomic64_read(&c->v);
-	u64 __percpu *pcpu_v;
+	struct percpu_counter *pcpu_v;
 
 	atomic_i  = i << COUNTER_IS_PCPU_BIT;
 	atomic_i &= ~COUNTER_MOD_MASK;
@@ -62,7 +111,7 @@ void lazy_percpu_counter_add_slowpath(struct lazy_percpu_counter *c, s64 i)
 	do {
 		pcpu_v = lazy_percpu_counter_is_pcpu(v);
 		if (pcpu_v) {
-			this_cpu_add(*pcpu_v, i);
+			percpu_counter_add(pcpu_v, i);
 			return;
 		}
 
-- 
2.25.1



  parent reply	other threads:[~2024-04-12  9:25 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-12  9:24 [RFC PATCH 0/3] mm: convert mm's rss stats into lazy_percpu_counter Peng Zhang
2024-04-12  9:24 ` [RFC PATCH 1/3] Lazy percpu counters Peng Zhang
2024-04-12  9:24 ` Peng Zhang [this message]
2024-04-12  9:24 ` [RFC PATCH 3/3] mm: convert mm's rss stats into lazy_percpu_counter Peng Zhang
2024-04-12 13:53 ` [RFC PATCH 0/3] " Jan Kara
2024-04-15 12:33   ` zhangpeng (AS)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240412092441.3112481-3-zhangpeng362@huawei.com \
    --to=zhangpeng362@huawei.com \
    --cc=akpm@linux-foundation.org \
    --cc=dennisszhou@gmail.com \
    --cc=jack@suse.cz \
    --cc=kent.overstreet@linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.cz \
    --cc=shakeelb@google.com \
    --cc=sunnanyong@huawei.com \
    --cc=surenb@google.com \
    --cc=vbabka@suse.cz \
    --cc=wangkefeng.wang@huawei.com \
    --cc=yu.ma@intel.com \
    --cc=yuzhao@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox