]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - kernel/rcu/rcuperf.c
Merge branch 'for-v5.6' of git://git.kernel.org:/pub/scm/linux/kernel/git/jmorris...
[mirror_ubuntu-jammy-kernel.git] / kernel / rcu / rcuperf.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Read-Copy Update module-based performance-test facility
4 *
5 * Copyright (C) IBM Corporation, 2015
6 *
7 * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
8 */
9
10 #define pr_fmt(fmt) fmt
11
12 #include <linux/types.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/kthread.h>
17 #include <linux/err.h>
18 #include <linux/spinlock.h>
19 #include <linux/smp.h>
20 #include <linux/rcupdate.h>
21 #include <linux/interrupt.h>
22 #include <linux/sched.h>
23 #include <uapi/linux/sched/types.h>
24 #include <linux/atomic.h>
25 #include <linux/bitops.h>
26 #include <linux/completion.h>
27 #include <linux/moduleparam.h>
28 #include <linux/percpu.h>
29 #include <linux/notifier.h>
30 #include <linux/reboot.h>
31 #include <linux/freezer.h>
32 #include <linux/cpu.h>
33 #include <linux/delay.h>
34 #include <linux/stat.h>
35 #include <linux/srcu.h>
36 #include <linux/slab.h>
37 #include <asm/byteorder.h>
38 #include <linux/torture.h>
39 #include <linux/vmalloc.h>
40
41 #include "rcu.h"
42
43 MODULE_LICENSE("GPL");
44 MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
45
46 #define PERF_FLAG "-perf:"
47 #define PERFOUT_STRING(s) \
48 pr_alert("%s" PERF_FLAG " %s\n", perf_type, s)
49 #define VERBOSE_PERFOUT_STRING(s) \
50 do { if (verbose) pr_alert("%s" PERF_FLAG " %s\n", perf_type, s); } while (0)
51 #define VERBOSE_PERFOUT_ERRSTRING(s) \
52 do { if (verbose) pr_alert("%s" PERF_FLAG "!!! %s\n", perf_type, s); } while (0)
53
54 /*
55 * The intended use cases for the nreaders and nwriters module parameters
56 * are as follows:
57 *
58 * 1. Specify only the nr_cpus kernel boot parameter. This will
59 * set both nreaders and nwriters to the value specified by
60 * nr_cpus for a mixed reader/writer test.
61 *
62 * 2. Specify the nr_cpus kernel boot parameter, but set
63 * rcuperf.nreaders to zero. This will set nwriters to the
64 * value specified by nr_cpus for an update-only test.
65 *
66 * 3. Specify the nr_cpus kernel boot parameter, but set
67 * rcuperf.nwriters to zero. This will set nreaders to the
68 * value specified by nr_cpus for a read-only test.
69 *
70 * Various other use cases may of course be specified.
71 */
72
73 #ifdef MODULE
74 # define RCUPERF_SHUTDOWN 0
75 #else
76 # define RCUPERF_SHUTDOWN 1
77 #endif
78
79 torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives");
80 torture_param(int, gp_async_max, 1000, "Max # outstanding waits per reader");
81 torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
82 torture_param(int, holdoff, 10, "Holdoff time before test start (s)");
83 torture_param(int, nreaders, -1, "Number of RCU reader threads");
84 torture_param(int, nwriters, -1, "Number of RCU updater threads");
85 torture_param(bool, shutdown, RCUPERF_SHUTDOWN,
86 "Shutdown at end of performance tests.");
87 torture_param(int, verbose, 1, "Enable verbose debugging printk()s");
88 torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable");
89 torture_param(int, kfree_rcu_test, 0, "Do we run a kfree_rcu() perf test?");
90
91 static char *perf_type = "rcu";
92 module_param(perf_type, charp, 0444);
93 MODULE_PARM_DESC(perf_type, "Type of RCU to performance-test (rcu, srcu, ...)");
94
95 static int nrealreaders;
96 static int nrealwriters;
97 static struct task_struct **writer_tasks;
98 static struct task_struct **reader_tasks;
99 static struct task_struct *shutdown_task;
100
101 static u64 **writer_durations;
102 static int *writer_n_durations;
103 static atomic_t n_rcu_perf_reader_started;
104 static atomic_t n_rcu_perf_writer_started;
105 static atomic_t n_rcu_perf_writer_finished;
106 static wait_queue_head_t shutdown_wq;
107 static u64 t_rcu_perf_writer_started;
108 static u64 t_rcu_perf_writer_finished;
109 static unsigned long b_rcu_gp_test_started;
110 static unsigned long b_rcu_gp_test_finished;
111 static DEFINE_PER_CPU(atomic_t, n_async_inflight);
112
113 #define MAX_MEAS 10000
114 #define MIN_MEAS 100
115
116 /*
117 * Operations vector for selecting different types of tests.
118 */
119
120 struct rcu_perf_ops {
121 int ptype;
122 void (*init)(void);
123 void (*cleanup)(void);
124 int (*readlock)(void);
125 void (*readunlock)(int idx);
126 unsigned long (*get_gp_seq)(void);
127 unsigned long (*gp_diff)(unsigned long new, unsigned long old);
128 unsigned long (*exp_completed)(void);
129 void (*async)(struct rcu_head *head, rcu_callback_t func);
130 void (*gp_barrier)(void);
131 void (*sync)(void);
132 void (*exp_sync)(void);
133 const char *name;
134 };
135
136 static struct rcu_perf_ops *cur_ops;
137
138 /*
139 * Definitions for rcu perf testing.
140 */
141
142 static int rcu_perf_read_lock(void) __acquires(RCU)
143 {
144 rcu_read_lock();
145 return 0;
146 }
147
148 static void rcu_perf_read_unlock(int idx) __releases(RCU)
149 {
150 rcu_read_unlock();
151 }
152
153 static unsigned long __maybe_unused rcu_no_completed(void)
154 {
155 return 0;
156 }
157
158 static void rcu_sync_perf_init(void)
159 {
160 }
161
162 static struct rcu_perf_ops rcu_ops = {
163 .ptype = RCU_FLAVOR,
164 .init = rcu_sync_perf_init,
165 .readlock = rcu_perf_read_lock,
166 .readunlock = rcu_perf_read_unlock,
167 .get_gp_seq = rcu_get_gp_seq,
168 .gp_diff = rcu_seq_diff,
169 .exp_completed = rcu_exp_batches_completed,
170 .async = call_rcu,
171 .gp_barrier = rcu_barrier,
172 .sync = synchronize_rcu,
173 .exp_sync = synchronize_rcu_expedited,
174 .name = "rcu"
175 };
176
177 /*
178 * Definitions for srcu perf testing.
179 */
180
181 DEFINE_STATIC_SRCU(srcu_ctl_perf);
182 static struct srcu_struct *srcu_ctlp = &srcu_ctl_perf;
183
184 static int srcu_perf_read_lock(void) __acquires(srcu_ctlp)
185 {
186 return srcu_read_lock(srcu_ctlp);
187 }
188
189 static void srcu_perf_read_unlock(int idx) __releases(srcu_ctlp)
190 {
191 srcu_read_unlock(srcu_ctlp, idx);
192 }
193
194 static unsigned long srcu_perf_completed(void)
195 {
196 return srcu_batches_completed(srcu_ctlp);
197 }
198
199 static void srcu_call_rcu(struct rcu_head *head, rcu_callback_t func)
200 {
201 call_srcu(srcu_ctlp, head, func);
202 }
203
204 static void srcu_rcu_barrier(void)
205 {
206 srcu_barrier(srcu_ctlp);
207 }
208
209 static void srcu_perf_synchronize(void)
210 {
211 synchronize_srcu(srcu_ctlp);
212 }
213
214 static void srcu_perf_synchronize_expedited(void)
215 {
216 synchronize_srcu_expedited(srcu_ctlp);
217 }
218
219 static struct rcu_perf_ops srcu_ops = {
220 .ptype = SRCU_FLAVOR,
221 .init = rcu_sync_perf_init,
222 .readlock = srcu_perf_read_lock,
223 .readunlock = srcu_perf_read_unlock,
224 .get_gp_seq = srcu_perf_completed,
225 .gp_diff = rcu_seq_diff,
226 .exp_completed = srcu_perf_completed,
227 .async = srcu_call_rcu,
228 .gp_barrier = srcu_rcu_barrier,
229 .sync = srcu_perf_synchronize,
230 .exp_sync = srcu_perf_synchronize_expedited,
231 .name = "srcu"
232 };
233
234 static struct srcu_struct srcud;
235
236 static void srcu_sync_perf_init(void)
237 {
238 srcu_ctlp = &srcud;
239 init_srcu_struct(srcu_ctlp);
240 }
241
242 static void srcu_sync_perf_cleanup(void)
243 {
244 cleanup_srcu_struct(srcu_ctlp);
245 }
246
247 static struct rcu_perf_ops srcud_ops = {
248 .ptype = SRCU_FLAVOR,
249 .init = srcu_sync_perf_init,
250 .cleanup = srcu_sync_perf_cleanup,
251 .readlock = srcu_perf_read_lock,
252 .readunlock = srcu_perf_read_unlock,
253 .get_gp_seq = srcu_perf_completed,
254 .gp_diff = rcu_seq_diff,
255 .exp_completed = srcu_perf_completed,
256 .async = srcu_call_rcu,
257 .gp_barrier = srcu_rcu_barrier,
258 .sync = srcu_perf_synchronize,
259 .exp_sync = srcu_perf_synchronize_expedited,
260 .name = "srcud"
261 };
262
263 /*
264 * Definitions for RCU-tasks perf testing.
265 */
266
267 static int tasks_perf_read_lock(void)
268 {
269 return 0;
270 }
271
272 static void tasks_perf_read_unlock(int idx)
273 {
274 }
275
276 static struct rcu_perf_ops tasks_ops = {
277 .ptype = RCU_TASKS_FLAVOR,
278 .init = rcu_sync_perf_init,
279 .readlock = tasks_perf_read_lock,
280 .readunlock = tasks_perf_read_unlock,
281 .get_gp_seq = rcu_no_completed,
282 .gp_diff = rcu_seq_diff,
283 .async = call_rcu_tasks,
284 .gp_barrier = rcu_barrier_tasks,
285 .sync = synchronize_rcu_tasks,
286 .exp_sync = synchronize_rcu_tasks,
287 .name = "tasks"
288 };
289
290 static unsigned long rcuperf_seq_diff(unsigned long new, unsigned long old)
291 {
292 if (!cur_ops->gp_diff)
293 return new - old;
294 return cur_ops->gp_diff(new, old);
295 }
296
297 /*
298 * If performance tests complete, wait for shutdown to commence.
299 */
300 static void rcu_perf_wait_shutdown(void)
301 {
302 cond_resched_tasks_rcu_qs();
303 if (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters)
304 return;
305 while (!torture_must_stop())
306 schedule_timeout_uninterruptible(1);
307 }
308
309 /*
310 * RCU perf reader kthread. Repeatedly does empty RCU read-side
311 * critical section, minimizing update-side interference.
312 */
313 static int
314 rcu_perf_reader(void *arg)
315 {
316 unsigned long flags;
317 int idx;
318 long me = (long)arg;
319
320 VERBOSE_PERFOUT_STRING("rcu_perf_reader task started");
321 set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
322 set_user_nice(current, MAX_NICE);
323 atomic_inc(&n_rcu_perf_reader_started);
324
325 do {
326 local_irq_save(flags);
327 idx = cur_ops->readlock();
328 cur_ops->readunlock(idx);
329 local_irq_restore(flags);
330 rcu_perf_wait_shutdown();
331 } while (!torture_must_stop());
332 torture_kthread_stopping("rcu_perf_reader");
333 return 0;
334 }
335
336 /*
337 * Callback function for asynchronous grace periods from rcu_perf_writer().
338 */
339 static void rcu_perf_async_cb(struct rcu_head *rhp)
340 {
341 atomic_dec(this_cpu_ptr(&n_async_inflight));
342 kfree(rhp);
343 }
344
345 /*
346 * RCU perf writer kthread. Repeatedly does a grace period.
347 */
348 static int
349 rcu_perf_writer(void *arg)
350 {
351 int i = 0;
352 int i_max;
353 long me = (long)arg;
354 struct rcu_head *rhp = NULL;
355 struct sched_param sp;
356 bool started = false, done = false, alldone = false;
357 u64 t;
358 u64 *wdp;
359 u64 *wdpp = writer_durations[me];
360
361 VERBOSE_PERFOUT_STRING("rcu_perf_writer task started");
362 WARN_ON(!wdpp);
363 set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
364 sp.sched_priority = 1;
365 sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
366
367 if (holdoff)
368 schedule_timeout_uninterruptible(holdoff * HZ);
369
370 /*
371 * Wait until rcu_end_inkernel_boot() is called for normal GP tests
372 * so that RCU is not always expedited for normal GP tests.
373 * The system_state test is approximate, but works well in practice.
374 */
375 while (!gp_exp && system_state != SYSTEM_RUNNING)
376 schedule_timeout_uninterruptible(1);
377
378 t = ktime_get_mono_fast_ns();
379 if (atomic_inc_return(&n_rcu_perf_writer_started) >= nrealwriters) {
380 t_rcu_perf_writer_started = t;
381 if (gp_exp) {
382 b_rcu_gp_test_started =
383 cur_ops->exp_completed() / 2;
384 } else {
385 b_rcu_gp_test_started = cur_ops->get_gp_seq();
386 }
387 }
388
389 do {
390 if (writer_holdoff)
391 udelay(writer_holdoff);
392 wdp = &wdpp[i];
393 *wdp = ktime_get_mono_fast_ns();
394 if (gp_async) {
395 retry:
396 if (!rhp)
397 rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
398 if (rhp && atomic_read(this_cpu_ptr(&n_async_inflight)) < gp_async_max) {
399 atomic_inc(this_cpu_ptr(&n_async_inflight));
400 cur_ops->async(rhp, rcu_perf_async_cb);
401 rhp = NULL;
402 } else if (!kthread_should_stop()) {
403 cur_ops->gp_barrier();
404 goto retry;
405 } else {
406 kfree(rhp); /* Because we are stopping. */
407 }
408 } else if (gp_exp) {
409 cur_ops->exp_sync();
410 } else {
411 cur_ops->sync();
412 }
413 t = ktime_get_mono_fast_ns();
414 *wdp = t - *wdp;
415 i_max = i;
416 if (!started &&
417 atomic_read(&n_rcu_perf_writer_started) >= nrealwriters)
418 started = true;
419 if (!done && i >= MIN_MEAS) {
420 done = true;
421 sp.sched_priority = 0;
422 sched_setscheduler_nocheck(current,
423 SCHED_NORMAL, &sp);
424 pr_alert("%s%s rcu_perf_writer %ld has %d measurements\n",
425 perf_type, PERF_FLAG, me, MIN_MEAS);
426 if (atomic_inc_return(&n_rcu_perf_writer_finished) >=
427 nrealwriters) {
428 schedule_timeout_interruptible(10);
429 rcu_ftrace_dump(DUMP_ALL);
430 PERFOUT_STRING("Test complete");
431 t_rcu_perf_writer_finished = t;
432 if (gp_exp) {
433 b_rcu_gp_test_finished =
434 cur_ops->exp_completed() / 2;
435 } else {
436 b_rcu_gp_test_finished =
437 cur_ops->get_gp_seq();
438 }
439 if (shutdown) {
440 smp_mb(); /* Assign before wake. */
441 wake_up(&shutdown_wq);
442 }
443 }
444 }
445 if (done && !alldone &&
446 atomic_read(&n_rcu_perf_writer_finished) >= nrealwriters)
447 alldone = true;
448 if (started && !alldone && i < MAX_MEAS - 1)
449 i++;
450 rcu_perf_wait_shutdown();
451 } while (!torture_must_stop());
452 if (gp_async) {
453 cur_ops->gp_barrier();
454 }
455 writer_n_durations[me] = i_max;
456 torture_kthread_stopping("rcu_perf_writer");
457 return 0;
458 }
459
460 static void
461 rcu_perf_print_module_parms(struct rcu_perf_ops *cur_ops, const char *tag)
462 {
463 pr_alert("%s" PERF_FLAG
464 "--- %s: nreaders=%d nwriters=%d verbose=%d shutdown=%d\n",
465 perf_type, tag, nrealreaders, nrealwriters, verbose, shutdown);
466 }
467
468 static void
469 rcu_perf_cleanup(void)
470 {
471 int i;
472 int j;
473 int ngps = 0;
474 u64 *wdp;
475 u64 *wdpp;
476
477 /*
478 * Would like warning at start, but everything is expedited
479 * during the mid-boot phase, so have to wait till the end.
480 */
481 if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp)
482 VERBOSE_PERFOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!");
483 if (rcu_gp_is_normal() && gp_exp)
484 VERBOSE_PERFOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!");
485 if (gp_exp && gp_async)
486 VERBOSE_PERFOUT_ERRSTRING("No expedited async GPs, so went with async!");
487
488 if (torture_cleanup_begin())
489 return;
490 if (!cur_ops) {
491 torture_cleanup_end();
492 return;
493 }
494
495 if (reader_tasks) {
496 for (i = 0; i < nrealreaders; i++)
497 torture_stop_kthread(rcu_perf_reader,
498 reader_tasks[i]);
499 kfree(reader_tasks);
500 }
501
502 if (writer_tasks) {
503 for (i = 0; i < nrealwriters; i++) {
504 torture_stop_kthread(rcu_perf_writer,
505 writer_tasks[i]);
506 if (!writer_n_durations)
507 continue;
508 j = writer_n_durations[i];
509 pr_alert("%s%s writer %d gps: %d\n",
510 perf_type, PERF_FLAG, i, j);
511 ngps += j;
512 }
513 pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n",
514 perf_type, PERF_FLAG,
515 t_rcu_perf_writer_started, t_rcu_perf_writer_finished,
516 t_rcu_perf_writer_finished -
517 t_rcu_perf_writer_started,
518 ngps,
519 rcuperf_seq_diff(b_rcu_gp_test_finished,
520 b_rcu_gp_test_started));
521 for (i = 0; i < nrealwriters; i++) {
522 if (!writer_durations)
523 break;
524 if (!writer_n_durations)
525 continue;
526 wdpp = writer_durations[i];
527 if (!wdpp)
528 continue;
529 for (j = 0; j <= writer_n_durations[i]; j++) {
530 wdp = &wdpp[j];
531 pr_alert("%s%s %4d writer-duration: %5d %llu\n",
532 perf_type, PERF_FLAG,
533 i, j, *wdp);
534 if (j % 100 == 0)
535 schedule_timeout_uninterruptible(1);
536 }
537 kfree(writer_durations[i]);
538 }
539 kfree(writer_tasks);
540 kfree(writer_durations);
541 kfree(writer_n_durations);
542 }
543
544 /* Do torture-type-specific cleanup operations. */
545 if (cur_ops->cleanup != NULL)
546 cur_ops->cleanup();
547
548 torture_cleanup_end();
549 }
550
551 /*
552 * Return the number if non-negative. If -1, the number of CPUs.
553 * If less than -1, that much less than the number of CPUs, but
554 * at least one.
555 */
556 static int compute_real(int n)
557 {
558 int nr;
559
560 if (n >= 0) {
561 nr = n;
562 } else {
563 nr = num_online_cpus() + 1 + n;
564 if (nr <= 0)
565 nr = 1;
566 }
567 return nr;
568 }
569
570 /*
571 * RCU perf shutdown kthread. Just waits to be awakened, then shuts
572 * down system.
573 */
574 static int
575 rcu_perf_shutdown(void *arg)
576 {
577 do {
578 wait_event(shutdown_wq,
579 atomic_read(&n_rcu_perf_writer_finished) >=
580 nrealwriters);
581 } while (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters);
582 smp_mb(); /* Wake before output. */
583 rcu_perf_cleanup();
584 kernel_power_off();
585 return -EINVAL;
586 }
587
588 /*
589 * kfree_rcu() performance tests: Start a kfree_rcu() loop on all CPUs for number
590 * of iterations and measure total time and number of GP for all iterations to complete.
591 */
592
593 torture_param(int, kfree_nthreads, -1, "Number of threads running loops of kfree_rcu().");
594 torture_param(int, kfree_alloc_num, 8000, "Number of allocations and frees done in an iteration.");
595 torture_param(int, kfree_loops, 10, "Number of loops doing kfree_alloc_num allocations and frees.");
596
597 static struct task_struct **kfree_reader_tasks;
598 static int kfree_nrealthreads;
599 static atomic_t n_kfree_perf_thread_started;
600 static atomic_t n_kfree_perf_thread_ended;
601
602 struct kfree_obj {
603 char kfree_obj[8];
604 struct rcu_head rh;
605 };
606
607 static int
608 kfree_perf_thread(void *arg)
609 {
610 int i, loop = 0;
611 long me = (long)arg;
612 struct kfree_obj *alloc_ptr;
613 u64 start_time, end_time;
614
615 VERBOSE_PERFOUT_STRING("kfree_perf_thread task started");
616 set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
617 set_user_nice(current, MAX_NICE);
618
619 start_time = ktime_get_mono_fast_ns();
620
621 if (atomic_inc_return(&n_kfree_perf_thread_started) >= kfree_nrealthreads) {
622 if (gp_exp)
623 b_rcu_gp_test_started = cur_ops->exp_completed() / 2;
624 else
625 b_rcu_gp_test_started = cur_ops->get_gp_seq();
626 }
627
628 do {
629 for (i = 0; i < kfree_alloc_num; i++) {
630 alloc_ptr = kmalloc(sizeof(struct kfree_obj), GFP_KERNEL);
631 if (!alloc_ptr)
632 return -ENOMEM;
633
634 kfree_rcu(alloc_ptr, rh);
635 }
636
637 cond_resched();
638 } while (!torture_must_stop() && ++loop < kfree_loops);
639
640 if (atomic_inc_return(&n_kfree_perf_thread_ended) >= kfree_nrealthreads) {
641 end_time = ktime_get_mono_fast_ns();
642
643 if (gp_exp)
644 b_rcu_gp_test_finished = cur_ops->exp_completed() / 2;
645 else
646 b_rcu_gp_test_finished = cur_ops->get_gp_seq();
647
648 pr_alert("Total time taken by all kfree'ers: %llu ns, loops: %d, batches: %ld\n",
649 (unsigned long long)(end_time - start_time), kfree_loops,
650 rcuperf_seq_diff(b_rcu_gp_test_finished, b_rcu_gp_test_started));
651 if (shutdown) {
652 smp_mb(); /* Assign before wake. */
653 wake_up(&shutdown_wq);
654 }
655 }
656
657 torture_kthread_stopping("kfree_perf_thread");
658 return 0;
659 }
660
661 static void
662 kfree_perf_cleanup(void)
663 {
664 int i;
665
666 if (torture_cleanup_begin())
667 return;
668
669 if (kfree_reader_tasks) {
670 for (i = 0; i < kfree_nrealthreads; i++)
671 torture_stop_kthread(kfree_perf_thread,
672 kfree_reader_tasks[i]);
673 kfree(kfree_reader_tasks);
674 }
675
676 torture_cleanup_end();
677 }
678
679 /*
680 * shutdown kthread. Just waits to be awakened, then shuts down system.
681 */
682 static int
683 kfree_perf_shutdown(void *arg)
684 {
685 do {
686 wait_event(shutdown_wq,
687 atomic_read(&n_kfree_perf_thread_ended) >=
688 kfree_nrealthreads);
689 } while (atomic_read(&n_kfree_perf_thread_ended) < kfree_nrealthreads);
690
691 smp_mb(); /* Wake before output. */
692
693 kfree_perf_cleanup();
694 kernel_power_off();
695 return -EINVAL;
696 }
697
698 static int __init
699 kfree_perf_init(void)
700 {
701 long i;
702 int firsterr = 0;
703
704 kfree_nrealthreads = compute_real(kfree_nthreads);
705 /* Start up the kthreads. */
706 if (shutdown) {
707 init_waitqueue_head(&shutdown_wq);
708 firsterr = torture_create_kthread(kfree_perf_shutdown, NULL,
709 shutdown_task);
710 if (firsterr)
711 goto unwind;
712 schedule_timeout_uninterruptible(1);
713 }
714
715 kfree_reader_tasks = kcalloc(kfree_nrealthreads, sizeof(kfree_reader_tasks[0]),
716 GFP_KERNEL);
717 if (kfree_reader_tasks == NULL) {
718 firsterr = -ENOMEM;
719 goto unwind;
720 }
721
722 for (i = 0; i < kfree_nrealthreads; i++) {
723 firsterr = torture_create_kthread(kfree_perf_thread, (void *)i,
724 kfree_reader_tasks[i]);
725 if (firsterr)
726 goto unwind;
727 }
728
729 while (atomic_read(&n_kfree_perf_thread_started) < kfree_nrealthreads)
730 schedule_timeout_uninterruptible(1);
731
732 torture_init_end();
733 return 0;
734
735 unwind:
736 torture_init_end();
737 kfree_perf_cleanup();
738 return firsterr;
739 }
740
741 static int __init
742 rcu_perf_init(void)
743 {
744 long i;
745 int firsterr = 0;
746 static struct rcu_perf_ops *perf_ops[] = {
747 &rcu_ops, &srcu_ops, &srcud_ops, &tasks_ops,
748 };
749
750 if (!torture_init_begin(perf_type, verbose))
751 return -EBUSY;
752
753 /* Process args and tell the world that the perf'er is on the job. */
754 for (i = 0; i < ARRAY_SIZE(perf_ops); i++) {
755 cur_ops = perf_ops[i];
756 if (strcmp(perf_type, cur_ops->name) == 0)
757 break;
758 }
759 if (i == ARRAY_SIZE(perf_ops)) {
760 pr_alert("rcu-perf: invalid perf type: \"%s\"\n", perf_type);
761 pr_alert("rcu-perf types:");
762 for (i = 0; i < ARRAY_SIZE(perf_ops); i++)
763 pr_cont(" %s", perf_ops[i]->name);
764 pr_cont("\n");
765 WARN_ON(!IS_MODULE(CONFIG_RCU_PERF_TEST));
766 firsterr = -EINVAL;
767 cur_ops = NULL;
768 goto unwind;
769 }
770 if (cur_ops->init)
771 cur_ops->init();
772
773 if (kfree_rcu_test)
774 return kfree_perf_init();
775
776 nrealwriters = compute_real(nwriters);
777 nrealreaders = compute_real(nreaders);
778 atomic_set(&n_rcu_perf_reader_started, 0);
779 atomic_set(&n_rcu_perf_writer_started, 0);
780 atomic_set(&n_rcu_perf_writer_finished, 0);
781 rcu_perf_print_module_parms(cur_ops, "Start of test");
782
783 /* Start up the kthreads. */
784
785 if (shutdown) {
786 init_waitqueue_head(&shutdown_wq);
787 firsterr = torture_create_kthread(rcu_perf_shutdown, NULL,
788 shutdown_task);
789 if (firsterr)
790 goto unwind;
791 schedule_timeout_uninterruptible(1);
792 }
793 reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]),
794 GFP_KERNEL);
795 if (reader_tasks == NULL) {
796 VERBOSE_PERFOUT_ERRSTRING("out of memory");
797 firsterr = -ENOMEM;
798 goto unwind;
799 }
800 for (i = 0; i < nrealreaders; i++) {
801 firsterr = torture_create_kthread(rcu_perf_reader, (void *)i,
802 reader_tasks[i]);
803 if (firsterr)
804 goto unwind;
805 }
806 while (atomic_read(&n_rcu_perf_reader_started) < nrealreaders)
807 schedule_timeout_uninterruptible(1);
808 writer_tasks = kcalloc(nrealwriters, sizeof(reader_tasks[0]),
809 GFP_KERNEL);
810 writer_durations = kcalloc(nrealwriters, sizeof(*writer_durations),
811 GFP_KERNEL);
812 writer_n_durations =
813 kcalloc(nrealwriters, sizeof(*writer_n_durations),
814 GFP_KERNEL);
815 if (!writer_tasks || !writer_durations || !writer_n_durations) {
816 VERBOSE_PERFOUT_ERRSTRING("out of memory");
817 firsterr = -ENOMEM;
818 goto unwind;
819 }
820 for (i = 0; i < nrealwriters; i++) {
821 writer_durations[i] =
822 kcalloc(MAX_MEAS, sizeof(*writer_durations[i]),
823 GFP_KERNEL);
824 if (!writer_durations[i]) {
825 firsterr = -ENOMEM;
826 goto unwind;
827 }
828 firsterr = torture_create_kthread(rcu_perf_writer, (void *)i,
829 writer_tasks[i]);
830 if (firsterr)
831 goto unwind;
832 }
833 torture_init_end();
834 return 0;
835
836 unwind:
837 torture_init_end();
838 rcu_perf_cleanup();
839 return firsterr;
840 }
841
842 module_init(rcu_perf_init);
843 module_exit(rcu_perf_cleanup);