From: SeongJae Park <sj@kernel.org>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: SeongJae Park <sj@kernel.org>,
damon@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-mm@kvack.org
Subject: [PATCH 4/8] mm/damon/core: process damon_call_control requests on a local list
Date: Sat, 17 Jan 2026 09:52:51 -0800 [thread overview]
Message-ID: <20260117175256.82826-5-sj@kernel.org> (raw)
In-Reply-To: <20260117175256.82826-1-sj@kernel.org>
kdamond_call() handles damon_call() requests on the ->call_controls list
of damon_ctx, which is shared with damon_call() callers. To protect the
list from concurrent accesses while letting the callback function
independent of the call_controls_lock, the function does complicated
locking operations. For each damon_call_control object on the list, the
function removes the control object from the list under locking, invoke
the callback of the control object without locking, and then puts the
control object back to the list if needed, under locking. It is
complicated, and can contend the locks more frequently with other DAMON
API caller threads as the number of concurrent callback requests
increases. Contention overhead is not a big deal, but the increased
race opportunity can make headaches.
Simplify the locking sequence by moving all damon_call_control objects
from the shared list to a local list at once under the single lock
protection, processing the callback requests without locking, and adding
back repeat mode controls to the shared list again at once again, again
under the single lock protection. This change makes the number of
locking in kdamond_call() be always two, regardless of the number of the
queued requests.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 59 ++++++++++++++++++-------------------------------
1 file changed, 21 insertions(+), 38 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 0bed937b1dce..54a7ea98340a 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2649,48 +2649,31 @@ static void kdamond_usleep(unsigned long usecs)
*/
static void kdamond_call(struct damon_ctx *ctx, bool cancel)
{
- struct damon_call_control *control;
- LIST_HEAD(repeat_controls);
- int ret = 0;
-
- while (true) {
- mutex_lock(&ctx->call_controls_lock);
- control = list_first_entry_or_null(&ctx->call_controls,
- struct damon_call_control, list);
- mutex_unlock(&ctx->call_controls_lock);
- if (!control)
- break;
- if (cancel) {
+ struct damon_call_control *control, *next;
+ LIST_HEAD(controls);
+
+ mutex_lock(&ctx->call_controls_lock);
+ list_splice_tail_init(&ctx->call_controls, &controls);
+ mutex_unlock(&ctx->call_controls_lock);
+
+ list_for_each_entry_safe(control, next, &controls, list) {
+ if (!control->repeat || cancel)
+ list_del(&control->list);
+
+ if (cancel)
control->canceled = true;
- } else {
- ret = control->fn(control->data);
- control->return_code = ret;
- }
- mutex_lock(&ctx->call_controls_lock);
- list_del(&control->list);
- mutex_unlock(&ctx->call_controls_lock);
- if (!control->repeat) {
+ else
+ control->return_code = control->fn(control->data);
+
+ if (!control->repeat)
complete(&control->completion);
- } else if (control->canceled && control->dealloc_on_cancel) {
+ else if (control->canceled && control->dealloc_on_cancel)
kfree(control);
- continue;
- } else {
- list_add(&control->list, &repeat_controls);
- }
- }
- while (true) {
- control = list_first_entry_or_null(&repeat_controls,
- struct damon_call_control, list);
- if (!control)
- break;
- /* Unlink from the repeate_controls list. */
- list_del(&control->list);
- if (cancel)
- continue;
- mutex_lock(&ctx->call_controls_lock);
- list_add(&control->list, &ctx->call_controls);
- mutex_unlock(&ctx->call_controls_lock);
}
+
+ mutex_lock(&ctx->call_controls_lock);
+ list_splice_tail(&controls, &ctx->call_controls);
+ mutex_unlock(&ctx->call_controls_lock);
}
/* Returns negative error code if it's not activated but should return */
--
2.47.3
next prev parent reply other threads:[~2026-01-17 17:53 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-17 17:52 [PATCH 0/8] mm/damon: cleanup kdamond, damon_call(), damos filter and DAMON_MIN_REGION SeongJae Park
2026-01-17 17:52 ` [PATCH 1/8] mm/damon: remove damon_operations->cleanup() SeongJae Park
2026-01-17 17:52 ` [PATCH 2/8] mm/damon/core: cleanup targets and regions at once on kdamond termination SeongJae Park
2026-01-17 17:52 ` [PATCH 3/8] mm/damon/core: cancel damos_walk() before damon_ctx->kdamond reset SeongJae Park
2026-01-17 17:52 ` SeongJae Park [this message]
2026-01-17 17:52 ` [PATCH 5/8] mm/damon: document damon_call_control->dealloc_on_cancel repeat behavior SeongJae Park
2026-01-17 17:52 ` [PATCH 6/8] mm/damon/core: rename damos_filter_out() to damos_core_filter_out() SeongJae Park
2026-01-17 17:52 ` [PATCH 7/8] mm/damon: rename DAMON_MIN_REGION to DAMON_MIN_REGION_SZ SeongJae Park
2026-01-17 17:52 ` [PATCH 8/8] mm/damon: rename min_sz_region of damon_ctx to min_region_sz SeongJae Park
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=20260117175256.82826-5-sj@kernel.org \
--to=sj@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=damon@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
/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