Messages in this thread | | | From | Namhyung Kim <> | Date | Thu, 15 Jul 2021 16:56:10 -0700 | Subject | Re: [RFC PATCH 04/10] perf workqueue: add threadpool execute and wait functions |
| |
On Tue, Jul 13, 2021 at 5:11 AM Riccardo Mancini <rickyman7@gmail.com> wrote: > > This patch adds: > - execute_in_threadpool: assigns a task to the threads to execute > asynchronously. > - wait_threadpool: waits for the task to complete on all threads. > Furthermore, testing for these new functions is added. > > This patch completes the threadpool. > > Signed-off-by: Riccardo Mancini <rickyman7@gmail.com> > --- > tools/perf/tests/workqueue.c | 86 ++++++++++++++++++++- > tools/perf/util/workqueue/threadpool.c | 103 +++++++++++++++++++++++++ > tools/perf/util/workqueue/threadpool.h | 5 ++ > 3 files changed, 193 insertions(+), 1 deletion(-) > > diff --git a/tools/perf/tests/workqueue.c b/tools/perf/tests/workqueue.c > index be377e9897bab4e9..3c64db8203556847 100644 > --- a/tools/perf/tests/workqueue.c > +++ b/tools/perf/tests/workqueue.c > @@ -1,13 +1,59 @@ > // SPDX-License-Identifier: GPL-2.0 > +#include <stdlib.h> > #include <linux/kernel.h> > +#include <linux/zalloc.h> > #include "tests.h" > #include "util/debug.h" > #include "util/workqueue/threadpool.h" > > +#define DUMMY_FACTOR 100000 > +#define N_DUMMY_WORK_SIZES 7 > + > struct threadpool_test_args_t { > int pool_size; > }; > > +struct test_task { > + struct task_struct task; > + int n_threads; > + int *array; > +}; > + > +/** > + * dummy_work - calculates DUMMY_FACTOR * (idx % N_DUMMY_WORK_SIZES) inefficiently > + * > + * This function uses modulus to create work items of different sizes. > + */ > +static void dummy_work(int idx) > +{ > + int prod = 0;
I'm not sure but having 'volatile' would prevent some kind of possible compiler optimizations..
> + int k = idx % N_DUMMY_WORK_SIZES; > + int i, j; > + > + for (i = 0; i < DUMMY_FACTOR; i++) > + for (j = 0; j < k; j++) > + prod ++; > + > + pr_debug3("dummy: %d * %d = %d\n", DUMMY_FACTOR, k, prod); > +} > + > +static void test_task_fn1(int tidx, struct task_struct *task) > +{ > + struct test_task *mtask = container_of(task, struct test_task, task); > + > + dummy_work(tidx); > + mtask->array[tidx] = tidx+1; > +} > + > +static void test_task_fn2(int tidx, struct task_struct *task) > +{ > + struct test_task *mtask = container_of(task, struct test_task, task); > + > + dummy_work(tidx); > + mtask->array[tidx] = tidx*2; > +} > + > + > static int __threadpool__prepare(struct threadpool_struct **pool, int pool_size) > { > int ret; > @@ -38,21 +84,59 @@ static int __threadpool__teardown(struct threadpool_struct *pool) > return 0; > } > > +static int __threadpool__exec_wait(struct threadpool_struct *pool, > + struct task_struct *task) > +{ > + int ret; > + > + ret = execute_in_threadpool(pool, task); > + TEST_ASSERT_VAL("threadpool execute failure", ret == 0); > + TEST_ASSERT_VAL("threadpool is not executing", threadpool_is_busy(pool)); > + > + ret = wait_threadpool(pool); > + TEST_ASSERT_VAL("threadpool wait failure", ret == 0); > + TEST_ASSERT_VAL("waited threadpool is not ready", threadpool_is_ready(pool)); > + > + return 0; > +} > > static int __test__threadpool(void *_args) > { > struct threadpool_test_args_t *args = _args; > struct threadpool_struct *pool; > - int ret; > + int ret, i; > + struct test_task task; > + > + task.task.fn = test_task_fn1; > + task.n_threads = args->pool_size; > + task.array = calloc(args->pool_size, sizeof(*task.array));
Need to check the return value.
> > ret = __threadpool__prepare(&pool, args->pool_size); > if (ret) > return ret; > > + ret = __threadpool__exec_wait(pool, &task.task); > + if (ret) > + return ret; > + > + for (i = 0; i < args->pool_size; i++) > + TEST_ASSERT_VAL("failed array check (1)", task.array[i] == i+1); > + > + task.task.fn = test_task_fn2; > + > + ret = __threadpool__exec_wait(pool, &task.task); > + if (ret) > + return ret; > + > + for (i = 0; i < args->pool_size; i++) > + TEST_ASSERT_VAL("failed array check (2)", task.array[i] == 2*i); > + > ret = __threadpool__teardown(pool); > if (ret) > return ret; > > + free(task.array);
All previous returns will leak it.
Thanks, Namhyung
| |