* [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction [not found] <20250210075703.79125-1-gmonaco@redhat.com> @ 2025-02-10 7:57 ` Gabriele Monaco 2025-02-10 14:53 ` Mathieu Desnoyers 0 siblings, 1 reply; 5+ messages in thread From: Gabriele Monaco @ 2025-02-10 7:57 UTC (permalink / raw) To: Mathieu Desnoyers, Peter Zijlstra, Paul E. McKenney, Shuah Khan, linux-kernel, linux-kselftest Cc: Gabriele Monaco A task in the kernel (task_mm_cid_work) runs somewhat periodically to compact the mm_cid for each process. Add a test to validate that it runs correctly and timely. The test spawns 1 thread pinned to each CPU, then each thread, including the main one, runs in short bursts for some time. During this period, the mm_cids should be spanning all numbers between 0 and nproc. At the end of this phase, a thread with high enough mm_cid (>= nproc/2) is selected to be the new leader, all other threads terminate. After some time, the only running thread should see 0 as mm_cid, if that doesn't happen, the compaction mechanism didn't work and the test fails. The test never fails if only 1 core is available, in which case, we cannot test anything as the only available mm_cid is 0. To: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Gabriele Monaco <gmonaco@redhat.com> --- tools/testing/selftests/rseq/.gitignore | 1 + tools/testing/selftests/rseq/Makefile | 2 +- .../selftests/rseq/mm_cid_compaction_test.c | 200 ++++++++++++++++++ 3 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/rseq/mm_cid_compaction_test.c diff --git a/tools/testing/selftests/rseq/.gitignore b/tools/testing/selftests/rseq/.gitignore index 16496de5f6ce4..2c89f97e4f737 100644 --- a/tools/testing/selftests/rseq/.gitignore +++ b/tools/testing/selftests/rseq/.gitignore @@ -3,6 +3,7 @@ basic_percpu_ops_test basic_percpu_ops_mm_cid_test basic_test basic_rseq_op_test +mm_cid_compaction_test param_test param_test_benchmark param_test_compare_twice diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile index 5a3432fceb586..ce1b38f46a355 100644 --- a/tools/testing/selftests/rseq/Makefile +++ b/tools/testing/selftests/rseq/Makefile @@ -16,7 +16,7 @@ OVERRIDE_TARGETS = 1 TEST_GEN_PROGS = basic_test basic_percpu_ops_test basic_percpu_ops_mm_cid_test param_test \ param_test_benchmark param_test_compare_twice param_test_mm_cid \ - param_test_mm_cid_benchmark param_test_mm_cid_compare_twice + param_test_mm_cid_benchmark param_test_mm_cid_compare_twice mm_cid_compaction_test TEST_GEN_PROGS_EXTENDED = librseq.so diff --git a/tools/testing/selftests/rseq/mm_cid_compaction_test.c b/tools/testing/selftests/rseq/mm_cid_compaction_test.c new file mode 100644 index 0000000000000..701719b320049 --- /dev/null +++ b/tools/testing/selftests/rseq/mm_cid_compaction_test.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: LGPL-2.1 +#define _GNU_SOURCE +#include <assert.h> +#include <pthread.h> +#include <sched.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> + +#include "../kselftest.h" +#include "rseq.h" + +#define VERBOSE 0 +#define printf_verbose(fmt, ...) \ + do { \ + if (VERBOSE) \ + printf(fmt, ##__VA_ARGS__); \ + } while (0) + +/* 0.5 s */ +#define RUNNER_PERIOD 500000 +/* Number of runs before we terminate or get the token */ +#define THREAD_RUNS 5 + +/* + * Number of times we check that the mm_cid were compacted. + * Checks are repeated every RUNNER_PERIOD. + */ +#define MM_CID_COMPACT_TIMEOUT 10 + +struct thread_args { + int cpu; + int num_cpus; + pthread_mutex_t *token; + pthread_barrier_t *barrier; + pthread_t *tinfo; + struct thread_args *args_head; +}; + +static void __noreturn *thread_runner(void *arg) +{ + struct thread_args *args = arg; + int i, ret, curr_mm_cid; + cpu_set_t cpumask; + + CPU_ZERO(&cpumask); + CPU_SET(args->cpu, &cpumask); + ret = pthread_setaffinity_np(pthread_self(), sizeof(cpumask), &cpumask); + if (ret) { + errno = ret; + perror("Error: failed to set affinity"); + abort(); + } + pthread_barrier_wait(args->barrier); + + for (i = 0; i < THREAD_RUNS; i++) + usleep(RUNNER_PERIOD); + curr_mm_cid = rseq_current_mm_cid(); + /* + * We select one thread with high enough mm_cid to be the new leader + * all other threads (including the main thread) will terminate. + * After some time, the mm_cid of the only remaining thread should + * converge to 0, if not, the test fails. + */ + if (curr_mm_cid >= args->num_cpus / 2 && + !pthread_mutex_trylock(args->token)) { + printf_verbose( + "cpu%d has mm_cid=%d and will be the new leader.\n", + sched_getcpu(), curr_mm_cid); + for (i = 0; i < args->num_cpus; i++) { + if (args->tinfo[i] == pthread_self()) + continue; + ret = pthread_join(args->tinfo[i], NULL); + if (ret) { + errno = ret; + perror("Error: failed to join thread"); + abort(); + } + } + pthread_barrier_destroy(args->barrier); + free(args->tinfo); + free(args->token); + free(args->barrier); + free(args->args_head); + + for (i = 0; i < MM_CID_COMPACT_TIMEOUT; i++) { + curr_mm_cid = rseq_current_mm_cid(); + printf_verbose("run %d: mm_cid=%d on cpu%d.\n", i, + curr_mm_cid, sched_getcpu()); + if (curr_mm_cid == 0) + exit(EXIT_SUCCESS); + usleep(RUNNER_PERIOD); + } + exit(EXIT_FAILURE); + } + printf_verbose("cpu%d has mm_cid=%d and is going to terminate.\n", + sched_getcpu(), curr_mm_cid); + pthread_exit(NULL); +} + +int test_mm_cid_compaction(void) +{ + cpu_set_t affinity; + int i, j, ret = 0, num_threads; + pthread_t *tinfo; + pthread_mutex_t *token; + pthread_barrier_t *barrier; + struct thread_args *args; + + sched_getaffinity(0, sizeof(affinity), &affinity); + num_threads = CPU_COUNT(&affinity); + tinfo = calloc(num_threads, sizeof(*tinfo)); + if (!tinfo) { + perror("Error: failed to allocate tinfo"); + return -1; + } + args = calloc(num_threads, sizeof(*args)); + if (!args) { + perror("Error: failed to allocate args"); + ret = -1; + goto out_free_tinfo; + } + token = malloc(sizeof(*token)); + if (!token) { + perror("Error: failed to allocate token"); + ret = -1; + goto out_free_args; + } + barrier = malloc(sizeof(*barrier)); + if (!barrier) { + perror("Error: failed to allocate barrier"); + ret = -1; + goto out_free_token; + } + if (num_threads == 1) { + fprintf(stderr, "Cannot test on a single cpu. " + "Skipping mm_cid_compaction test.\n"); + /* only skipping the test, this is not a failure */ + goto out_free_barrier; + } + pthread_mutex_init(token, NULL); + ret = pthread_barrier_init(barrier, NULL, num_threads); + if (ret) { + errno = ret; + perror("Error: failed to initialise barrier"); + goto out_free_barrier; + } + for (i = 0, j = 0; i < CPU_SETSIZE && j < num_threads; i++) { + if (!CPU_ISSET(i, &affinity)) + continue; + args[j].num_cpus = num_threads; + args[j].tinfo = tinfo; + args[j].token = token; + args[j].barrier = barrier; + args[j].cpu = i; + args[j].args_head = args; + if (!j) { + /* The first thread is the main one */ + tinfo[0] = pthread_self(); + ++j; + continue; + } + ret = pthread_create(&tinfo[j], NULL, thread_runner, &args[j]); + if (ret) { + errno = ret; + perror("Error: failed to create thread"); + abort(); + } + ++j; + } + printf_verbose("Started %d threads.\n", num_threads); + + /* Also main thread will terminate if it is not selected as leader */ + thread_runner(&args[0]); + + /* only reached in case of errors */ +out_free_barrier: + free(barrier); +out_free_token: + free(token); +out_free_args: + free(args); +out_free_tinfo: + free(tinfo); + + return ret; +} + +int main(int argc, char **argv) +{ + if (!rseq_mm_cid_available()) { + fprintf(stderr, "Error: rseq_mm_cid unavailable\n"); + return -1; + } + if (test_mm_cid_compaction()) + return -1; + return 0; +} -- 2.48.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction 2025-02-10 7:57 ` [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction Gabriele Monaco @ 2025-02-10 14:53 ` Mathieu Desnoyers 2025-02-10 15:25 ` Gabriele Monaco 0 siblings, 1 reply; 5+ messages in thread From: Mathieu Desnoyers @ 2025-02-10 14:53 UTC (permalink / raw) To: Gabriele Monaco, Peter Zijlstra, Paul E. McKenney, Shuah Khan, linux-kernel, linux-kselftest On 2025-02-10 08:57, Gabriele Monaco wrote: > A task in the kernel (task_mm_cid_work) runs somewhat periodically to > compact the mm_cid for each process. Add a test to validate that it runs > correctly and timely. > > The test spawns 1 thread pinned to each CPU, then each thread, including > the main one, runs in short bursts for some time. During this period, the > mm_cids should be spanning all numbers between 0 and nproc. > > At the end of this phase, a thread with high enough mm_cid (>= nproc/2) > is selected to be the new leader, all other threads terminate. > > After some time, the only running thread should see 0 as mm_cid, if that > doesn't happen, the compaction mechanism didn't work and the test fails. > > The test never fails if only 1 core is available, in which case, we > cannot test anything as the only available mm_cid is 0. > > To: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> tiny nit below: > + usleep(RUNNER_PERIOD); > + curr_mm_cid = rseq_current_mm_cid(); > + /* > + * We select one thread with high enough mm_cid to be the new leader Missing punctuation here (...new leader. All other...) > + * all other threads (including the main thread) will terminate. > + * After some time, the mm_cid of the only remaining thread should > + * converge to 0, if not, the test fails. > + */ Thanks, Mathieu -- Mathieu Desnoyers EfficiOS Inc. https://www.efficios.com ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction 2025-02-10 14:53 ` Mathieu Desnoyers @ 2025-02-10 15:25 ` Gabriele Monaco 2025-02-18 23:45 ` Shuah Khan 0 siblings, 1 reply; 5+ messages in thread From: Gabriele Monaco @ 2025-02-10 15:25 UTC (permalink / raw) To: Mathieu Desnoyers Cc: Peter Zijlstra, Paul E. McKenney, Shuah Khan, Ingo Molnar, linux-kernel, linux-kselftest On Mon, 2025-02-10 at 15:53 +0100, Mathieu Desnoyers wrote: > On 2025-02-10 08:57, Gabriele Monaco wrote: > > A task in the kernel (task_mm_cid_work) runs somewhat periodically > > to > > compact the mm_cid for each process. Add a test to validate that it > > runs > > correctly and timely. > > > > The test spawns 1 thread pinned to each CPU, then each thread, > > including > > the main one, runs in short bursts for some time. During this > > period, the > > mm_cids should be spanning all numbers between 0 and nproc. > > > > At the end of this phase, a thread with high enough mm_cid (>= > > nproc/2) > > is selected to be the new leader, all other threads terminate. > > > > After some time, the only running thread should see 0 as mm_cid, if > > that > > doesn't happen, the compaction mechanism didn't work and the test > > fails. > > > > The test never fails if only 1 core is available, in which case, we > > cannot test anything as the only available mm_cid is 0. > > > > To: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > > Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > > tiny nit below: > > > + usleep(RUNNER_PERIOD); > > + curr_mm_cid = rseq_current_mm_cid(); > > + /* > > + * We select one thread with high enough mm_cid to be the > > new leader > > Missing punctuation here (...new leader. All other...) I guess I'm allergic to those ;) Thanks for finding it! I wonder if checkpatch should be able to catch this kind of problem, but that's for another day. Do I need to send a v6 for this or just reply here with the fixed patch? Thanks, Gabriele ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction 2025-02-10 15:25 ` Gabriele Monaco @ 2025-02-18 23:45 ` Shuah Khan 2025-02-19 10:28 ` Gabriele Monaco 0 siblings, 1 reply; 5+ messages in thread From: Shuah Khan @ 2025-02-18 23:45 UTC (permalink / raw) To: Gabriele Monaco, Mathieu Desnoyers Cc: Peter Zijlstra, Paul E. McKenney, Shuah Khan, Ingo Molnar, linux-kernel, linux-kselftest, Shuah Khan On 2/10/25 08:25, Gabriele Monaco wrote: > > > On Mon, 2025-02-10 at 15:53 +0100, Mathieu Desnoyers wrote: >> On 2025-02-10 08:57, Gabriele Monaco wrote: >>> A task in the kernel (task_mm_cid_work) runs somewhat periodically >>> to >>> compact the mm_cid for each process. Add a test to validate that it >>> runs >>> correctly and timely. >>> >>> The test spawns 1 thread pinned to each CPU, then each thread, >>> including >>> the main one, runs in short bursts for some time. During this >>> period, the >>> mm_cids should be spanning all numbers between 0 and nproc. >>> >>> At the end of this phase, a thread with high enough mm_cid (>= >>> nproc/2) >>> is selected to be the new leader, all other threads terminate. >>> >>> After some time, the only running thread should see 0 as mm_cid, if >>> that >>> doesn't happen, the compaction mechanism didn't work and the test >>> fails. >>> >>> The test never fails if only 1 core is available, in which case, we >>> cannot test anything as the only available mm_cid is 0. >>> >>> To: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> >> >> Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> >> >> tiny nit below: >> >>> + usleep(RUNNER_PERIOD); >>> + curr_mm_cid = rseq_current_mm_cid(); >>> + /* >>> + * We select one thread with high enough mm_cid to be the >>> new leader >> >> Missing punctuation here (...new leader. All other...) > > I guess I'm allergic to those ;) Thanks for finding it! > I wonder if checkpatch should be able to catch this kind of problem, > but that's for another day. > > Do I need to send a v6 for this or just reply here with the fixed > patch? Please send v6 with the suggested changes. Also change the commit summary to "selftests/rseq" thanks, -- Shuah ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction 2025-02-18 23:45 ` Shuah Khan @ 2025-02-19 10:28 ` Gabriele Monaco 0 siblings, 0 replies; 5+ messages in thread From: Gabriele Monaco @ 2025-02-19 10:28 UTC (permalink / raw) To: Shuah Khan, Mathieu Desnoyers Cc: Peter Zijlstra, Paul E. McKenney, Shuah Khan, Ingo Molnar, linux-kernel, linux-kselftest On Tue, 2025-02-18 at 16:45 -0700, Shuah Khan wrote: > > Please send v6 with the suggested changes. Also change the commit > summary to > > "selftests/rseq" Sure, will do. There was actually a V6 already, so I'm sending a V7. In the meanwhile there was a discussion about the approach. I'm going to send as V7 what is closer to the approach in V6. I opened another series for the other approach (scan in batches), which we may continue depending on the review of V7. The test should be mostly independent on the approach though. Thanks, Gabriele ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-02-19 10:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250210075703.79125-1-gmonaco@redhat.com>
2025-02-10 7:57 ` [PATCH v5 3/3] rseq/selftests: Add test for mm_cid compaction Gabriele Monaco
2025-02-10 14:53 ` Mathieu Desnoyers
2025-02-10 15:25 ` Gabriele Monaco
2025-02-18 23:45 ` Shuah Khan
2025-02-19 10:28 ` Gabriele Monaco
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox