This is a minor patch set for a call_controls_lock synchronization improvement. Spinlocks are faster than mutexes, even when the mutex takes the fast path. Hence, this patch replaces the mutex call_controls_lock with a spinlock. Initial benchmarking shows the following results # bpftrace -e 'kprobe:kdamond_call { @start[tid] = nsecs; } kretprobe:kdamond_call /@start[tid]/ { @ns[comm] = hist(nsecs - @start[tid]); delete(@start[tid]); }' @ns[kdamond.0]: [16K, 32K) 22 |@@@@@@@@@@@@ | [32K, 64K) 90 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [64K, 128K) 0 | | [128K, 256K) 1 | | @ns[kdamond.0]: [16K, 32K) 19 |@@@@@@@@ | [32K, 64K) 118 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [64K, 128K) 0 | | [128K, 256K) 1 | Signed-off-by: Asier Gutierrez --- include/linux/damon.h | 2 +- mm/damon/core.c | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index 3813373a9200..43665e63a498 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -801,7 +801,7 @@ struct damon_ctx { /* lists of &struct damon_call_control */ struct list_head call_controls; - struct mutex call_controls_lock; + spinlock_t call_controls_lock; struct damos_walk_control *walk_control; struct mutex walk_control_lock; diff --git a/mm/damon/core.c b/mm/damon/core.c index f9fc0375890a..a929bdf3bc7b 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -539,7 +539,6 @@ struct damon_ctx *damon_new_ctx(void) mutex_init(&ctx->kdamond_lock); INIT_LIST_HEAD(&ctx->call_controls); - mutex_init(&ctx->call_controls_lock); mutex_init(&ctx->walk_control_lock); ctx->attrs.min_nr_regions = 10; @@ -1457,9 +1456,9 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control) control->canceled = false; INIT_LIST_HEAD(&control->list); - mutex_lock(&ctx->call_controls_lock); + spin_lock(&ctx->call_controls_lock); list_add_tail(&control->list, &ctx->call_controls); - mutex_unlock(&ctx->call_controls_lock); + spin_unlock(&ctx->call_controls_lock); if (!damon_is_running(ctx)) return -EINVAL; if (control->repeat) @@ -2549,10 +2548,10 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel) int ret = 0; while (true) { - mutex_lock(&ctx->call_controls_lock); + spin_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); + spin_unlock(&ctx->call_controls_lock); if (!control) break; if (cancel) { @@ -2561,9 +2560,9 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel) ret = control->fn(control->data); control->return_code = ret; } - mutex_lock(&ctx->call_controls_lock); + spin_lock(&ctx->call_controls_lock); list_del(&control->list); - mutex_unlock(&ctx->call_controls_lock); + spin_unlock(&ctx->call_controls_lock); if (!control->repeat) { complete(&control->completion); } else if (control->canceled && control->dealloc_on_cancel) { @@ -2577,9 +2576,9 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel) struct damon_call_control, list); if (!control || cancel) return; - mutex_lock(&ctx->call_controls_lock); + spin_lock(&ctx->call_controls_lock); list_add_tail(&control->list, &ctx->call_controls); - mutex_unlock(&ctx->call_controls_lock); + spin_unlock(&ctx->call_controls_lock); } /* Returns negative error code if it's not activated but should return */ -- 2.43.0