Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Read-Copy Update module-based scalability-test facility
0004  *
0005  * Copyright (C) IBM Corporation, 2015
0006  *
0007  * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
0008  */
0009 
0010 #define pr_fmt(fmt) fmt
0011 
0012 #include <linux/types.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/mm.h>
0016 #include <linux/module.h>
0017 #include <linux/kthread.h>
0018 #include <linux/err.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/smp.h>
0021 #include <linux/rcupdate.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/sched.h>
0024 #include <uapi/linux/sched/types.h>
0025 #include <linux/atomic.h>
0026 #include <linux/bitops.h>
0027 #include <linux/completion.h>
0028 #include <linux/moduleparam.h>
0029 #include <linux/percpu.h>
0030 #include <linux/notifier.h>
0031 #include <linux/reboot.h>
0032 #include <linux/freezer.h>
0033 #include <linux/cpu.h>
0034 #include <linux/delay.h>
0035 #include <linux/stat.h>
0036 #include <linux/srcu.h>
0037 #include <linux/slab.h>
0038 #include <asm/byteorder.h>
0039 #include <linux/torture.h>
0040 #include <linux/vmalloc.h>
0041 #include <linux/rcupdate_trace.h>
0042 
0043 #include "rcu.h"
0044 
0045 MODULE_LICENSE("GPL");
0046 MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
0047 
0048 #define SCALE_FLAG "-scale:"
0049 #define SCALEOUT_STRING(s) \
0050     pr_alert("%s" SCALE_FLAG " %s\n", scale_type, s)
0051 #define VERBOSE_SCALEOUT_STRING(s) \
0052     do { if (verbose) pr_alert("%s" SCALE_FLAG " %s\n", scale_type, s); } while (0)
0053 #define SCALEOUT_ERRSTRING(s) \
0054     pr_alert("%s" SCALE_FLAG "!!! %s\n", scale_type, s)
0055 
0056 /*
0057  * The intended use cases for the nreaders and nwriters module parameters
0058  * are as follows:
0059  *
0060  * 1.   Specify only the nr_cpus kernel boot parameter.  This will
0061  *  set both nreaders and nwriters to the value specified by
0062  *  nr_cpus for a mixed reader/writer test.
0063  *
0064  * 2.   Specify the nr_cpus kernel boot parameter, but set
0065  *  rcuscale.nreaders to zero.  This will set nwriters to the
0066  *  value specified by nr_cpus for an update-only test.
0067  *
0068  * 3.   Specify the nr_cpus kernel boot parameter, but set
0069  *  rcuscale.nwriters to zero.  This will set nreaders to the
0070  *  value specified by nr_cpus for a read-only test.
0071  *
0072  * Various other use cases may of course be specified.
0073  *
0074  * Note that this test's readers are intended only as a test load for
0075  * the writers.  The reader scalability statistics will be overly
0076  * pessimistic due to the per-critical-section interrupt disabling,
0077  * test-end checks, and the pair of calls through pointers.
0078  */
0079 
0080 #ifdef MODULE
0081 # define RCUSCALE_SHUTDOWN 0
0082 #else
0083 # define RCUSCALE_SHUTDOWN 1
0084 #endif
0085 
0086 torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives");
0087 torture_param(int, gp_async_max, 1000, "Max # outstanding waits per reader");
0088 torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
0089 torture_param(int, holdoff, 10, "Holdoff time before test start (s)");
0090 torture_param(int, nreaders, -1, "Number of RCU reader threads");
0091 torture_param(int, nwriters, -1, "Number of RCU updater threads");
0092 torture_param(bool, shutdown, RCUSCALE_SHUTDOWN,
0093           "Shutdown at end of scalability tests.");
0094 torture_param(int, verbose, 1, "Enable verbose debugging printk()s");
0095 torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable");
0096 torture_param(int, kfree_rcu_test, 0, "Do we run a kfree_rcu() scale test?");
0097 torture_param(int, kfree_mult, 1, "Multiple of kfree_obj size to allocate.");
0098 
0099 static char *scale_type = "rcu";
0100 module_param(scale_type, charp, 0444);
0101 MODULE_PARM_DESC(scale_type, "Type of RCU to scalability-test (rcu, srcu, ...)");
0102 
0103 static int nrealreaders;
0104 static int nrealwriters;
0105 static struct task_struct **writer_tasks;
0106 static struct task_struct **reader_tasks;
0107 static struct task_struct *shutdown_task;
0108 
0109 static u64 **writer_durations;
0110 static int *writer_n_durations;
0111 static atomic_t n_rcu_scale_reader_started;
0112 static atomic_t n_rcu_scale_writer_started;
0113 static atomic_t n_rcu_scale_writer_finished;
0114 static wait_queue_head_t shutdown_wq;
0115 static u64 t_rcu_scale_writer_started;
0116 static u64 t_rcu_scale_writer_finished;
0117 static unsigned long b_rcu_gp_test_started;
0118 static unsigned long b_rcu_gp_test_finished;
0119 static DEFINE_PER_CPU(atomic_t, n_async_inflight);
0120 
0121 #define MAX_MEAS 10000
0122 #define MIN_MEAS 100
0123 
0124 /*
0125  * Operations vector for selecting different types of tests.
0126  */
0127 
0128 struct rcu_scale_ops {
0129     int ptype;
0130     void (*init)(void);
0131     void (*cleanup)(void);
0132     int (*readlock)(void);
0133     void (*readunlock)(int idx);
0134     unsigned long (*get_gp_seq)(void);
0135     unsigned long (*gp_diff)(unsigned long new, unsigned long old);
0136     unsigned long (*exp_completed)(void);
0137     void (*async)(struct rcu_head *head, rcu_callback_t func);
0138     void (*gp_barrier)(void);
0139     void (*sync)(void);
0140     void (*exp_sync)(void);
0141     const char *name;
0142 };
0143 
0144 static struct rcu_scale_ops *cur_ops;
0145 
0146 /*
0147  * Definitions for rcu scalability testing.
0148  */
0149 
0150 static int rcu_scale_read_lock(void) __acquires(RCU)
0151 {
0152     rcu_read_lock();
0153     return 0;
0154 }
0155 
0156 static void rcu_scale_read_unlock(int idx) __releases(RCU)
0157 {
0158     rcu_read_unlock();
0159 }
0160 
0161 static unsigned long __maybe_unused rcu_no_completed(void)
0162 {
0163     return 0;
0164 }
0165 
0166 static void rcu_sync_scale_init(void)
0167 {
0168 }
0169 
0170 static struct rcu_scale_ops rcu_ops = {
0171     .ptype      = RCU_FLAVOR,
0172     .init       = rcu_sync_scale_init,
0173     .readlock   = rcu_scale_read_lock,
0174     .readunlock = rcu_scale_read_unlock,
0175     .get_gp_seq = rcu_get_gp_seq,
0176     .gp_diff    = rcu_seq_diff,
0177     .exp_completed  = rcu_exp_batches_completed,
0178     .async      = call_rcu,
0179     .gp_barrier = rcu_barrier,
0180     .sync       = synchronize_rcu,
0181     .exp_sync   = synchronize_rcu_expedited,
0182     .name       = "rcu"
0183 };
0184 
0185 /*
0186  * Definitions for srcu scalability testing.
0187  */
0188 
0189 DEFINE_STATIC_SRCU(srcu_ctl_scale);
0190 static struct srcu_struct *srcu_ctlp = &srcu_ctl_scale;
0191 
0192 static int srcu_scale_read_lock(void) __acquires(srcu_ctlp)
0193 {
0194     return srcu_read_lock(srcu_ctlp);
0195 }
0196 
0197 static void srcu_scale_read_unlock(int idx) __releases(srcu_ctlp)
0198 {
0199     srcu_read_unlock(srcu_ctlp, idx);
0200 }
0201 
0202 static unsigned long srcu_scale_completed(void)
0203 {
0204     return srcu_batches_completed(srcu_ctlp);
0205 }
0206 
0207 static void srcu_call_rcu(struct rcu_head *head, rcu_callback_t func)
0208 {
0209     call_srcu(srcu_ctlp, head, func);
0210 }
0211 
0212 static void srcu_rcu_barrier(void)
0213 {
0214     srcu_barrier(srcu_ctlp);
0215 }
0216 
0217 static void srcu_scale_synchronize(void)
0218 {
0219     synchronize_srcu(srcu_ctlp);
0220 }
0221 
0222 static void srcu_scale_synchronize_expedited(void)
0223 {
0224     synchronize_srcu_expedited(srcu_ctlp);
0225 }
0226 
0227 static struct rcu_scale_ops srcu_ops = {
0228     .ptype      = SRCU_FLAVOR,
0229     .init       = rcu_sync_scale_init,
0230     .readlock   = srcu_scale_read_lock,
0231     .readunlock = srcu_scale_read_unlock,
0232     .get_gp_seq = srcu_scale_completed,
0233     .gp_diff    = rcu_seq_diff,
0234     .exp_completed  = srcu_scale_completed,
0235     .async      = srcu_call_rcu,
0236     .gp_barrier = srcu_rcu_barrier,
0237     .sync       = srcu_scale_synchronize,
0238     .exp_sync   = srcu_scale_synchronize_expedited,
0239     .name       = "srcu"
0240 };
0241 
0242 static struct srcu_struct srcud;
0243 
0244 static void srcu_sync_scale_init(void)
0245 {
0246     srcu_ctlp = &srcud;
0247     init_srcu_struct(srcu_ctlp);
0248 }
0249 
0250 static void srcu_sync_scale_cleanup(void)
0251 {
0252     cleanup_srcu_struct(srcu_ctlp);
0253 }
0254 
0255 static struct rcu_scale_ops srcud_ops = {
0256     .ptype      = SRCU_FLAVOR,
0257     .init       = srcu_sync_scale_init,
0258     .cleanup    = srcu_sync_scale_cleanup,
0259     .readlock   = srcu_scale_read_lock,
0260     .readunlock = srcu_scale_read_unlock,
0261     .get_gp_seq = srcu_scale_completed,
0262     .gp_diff    = rcu_seq_diff,
0263     .exp_completed  = srcu_scale_completed,
0264     .async      = srcu_call_rcu,
0265     .gp_barrier = srcu_rcu_barrier,
0266     .sync       = srcu_scale_synchronize,
0267     .exp_sync   = srcu_scale_synchronize_expedited,
0268     .name       = "srcud"
0269 };
0270 
0271 #ifdef CONFIG_TASKS_RCU
0272 
0273 /*
0274  * Definitions for RCU-tasks scalability testing.
0275  */
0276 
0277 static int tasks_scale_read_lock(void)
0278 {
0279     return 0;
0280 }
0281 
0282 static void tasks_scale_read_unlock(int idx)
0283 {
0284 }
0285 
0286 static struct rcu_scale_ops tasks_ops = {
0287     .ptype      = RCU_TASKS_FLAVOR,
0288     .init       = rcu_sync_scale_init,
0289     .readlock   = tasks_scale_read_lock,
0290     .readunlock = tasks_scale_read_unlock,
0291     .get_gp_seq = rcu_no_completed,
0292     .gp_diff    = rcu_seq_diff,
0293     .async      = call_rcu_tasks,
0294     .gp_barrier = rcu_barrier_tasks,
0295     .sync       = synchronize_rcu_tasks,
0296     .exp_sync   = synchronize_rcu_tasks,
0297     .name       = "tasks"
0298 };
0299 
0300 #define TASKS_OPS &tasks_ops,
0301 
0302 #else // #ifdef CONFIG_TASKS_RCU
0303 
0304 #define TASKS_OPS
0305 
0306 #endif // #else // #ifdef CONFIG_TASKS_RCU
0307 
0308 #ifdef CONFIG_TASKS_TRACE_RCU
0309 
0310 /*
0311  * Definitions for RCU-tasks-trace scalability testing.
0312  */
0313 
0314 static int tasks_trace_scale_read_lock(void)
0315 {
0316     rcu_read_lock_trace();
0317     return 0;
0318 }
0319 
0320 static void tasks_trace_scale_read_unlock(int idx)
0321 {
0322     rcu_read_unlock_trace();
0323 }
0324 
0325 static struct rcu_scale_ops tasks_tracing_ops = {
0326     .ptype      = RCU_TASKS_FLAVOR,
0327     .init       = rcu_sync_scale_init,
0328     .readlock   = tasks_trace_scale_read_lock,
0329     .readunlock = tasks_trace_scale_read_unlock,
0330     .get_gp_seq = rcu_no_completed,
0331     .gp_diff    = rcu_seq_diff,
0332     .async      = call_rcu_tasks_trace,
0333     .gp_barrier = rcu_barrier_tasks_trace,
0334     .sync       = synchronize_rcu_tasks_trace,
0335     .exp_sync   = synchronize_rcu_tasks_trace,
0336     .name       = "tasks-tracing"
0337 };
0338 
0339 #define TASKS_TRACING_OPS &tasks_tracing_ops,
0340 
0341 #else // #ifdef CONFIG_TASKS_TRACE_RCU
0342 
0343 #define TASKS_TRACING_OPS
0344 
0345 #endif // #else // #ifdef CONFIG_TASKS_TRACE_RCU
0346 
0347 static unsigned long rcuscale_seq_diff(unsigned long new, unsigned long old)
0348 {
0349     if (!cur_ops->gp_diff)
0350         return new - old;
0351     return cur_ops->gp_diff(new, old);
0352 }
0353 
0354 /*
0355  * If scalability tests complete, wait for shutdown to commence.
0356  */
0357 static void rcu_scale_wait_shutdown(void)
0358 {
0359     cond_resched_tasks_rcu_qs();
0360     if (atomic_read(&n_rcu_scale_writer_finished) < nrealwriters)
0361         return;
0362     while (!torture_must_stop())
0363         schedule_timeout_uninterruptible(1);
0364 }
0365 
0366 /*
0367  * RCU scalability reader kthread.  Repeatedly does empty RCU read-side
0368  * critical section, minimizing update-side interference.  However, the
0369  * point of this test is not to evaluate reader scalability, but instead
0370  * to serve as a test load for update-side scalability testing.
0371  */
0372 static int
0373 rcu_scale_reader(void *arg)
0374 {
0375     unsigned long flags;
0376     int idx;
0377     long me = (long)arg;
0378 
0379     VERBOSE_SCALEOUT_STRING("rcu_scale_reader task started");
0380     set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
0381     set_user_nice(current, MAX_NICE);
0382     atomic_inc(&n_rcu_scale_reader_started);
0383 
0384     do {
0385         local_irq_save(flags);
0386         idx = cur_ops->readlock();
0387         cur_ops->readunlock(idx);
0388         local_irq_restore(flags);
0389         rcu_scale_wait_shutdown();
0390     } while (!torture_must_stop());
0391     torture_kthread_stopping("rcu_scale_reader");
0392     return 0;
0393 }
0394 
0395 /*
0396  * Callback function for asynchronous grace periods from rcu_scale_writer().
0397  */
0398 static void rcu_scale_async_cb(struct rcu_head *rhp)
0399 {
0400     atomic_dec(this_cpu_ptr(&n_async_inflight));
0401     kfree(rhp);
0402 }
0403 
0404 /*
0405  * RCU scale writer kthread.  Repeatedly does a grace period.
0406  */
0407 static int
0408 rcu_scale_writer(void *arg)
0409 {
0410     int i = 0;
0411     int i_max;
0412     long me = (long)arg;
0413     struct rcu_head *rhp = NULL;
0414     bool started = false, done = false, alldone = false;
0415     u64 t;
0416     u64 *wdp;
0417     u64 *wdpp = writer_durations[me];
0418 
0419     VERBOSE_SCALEOUT_STRING("rcu_scale_writer task started");
0420     WARN_ON(!wdpp);
0421     set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
0422     current->flags |= PF_NO_SETAFFINITY;
0423     sched_set_fifo_low(current);
0424 
0425     if (holdoff)
0426         schedule_timeout_uninterruptible(holdoff * HZ);
0427 
0428     /*
0429      * Wait until rcu_end_inkernel_boot() is called for normal GP tests
0430      * so that RCU is not always expedited for normal GP tests.
0431      * The system_state test is approximate, but works well in practice.
0432      */
0433     while (!gp_exp && system_state != SYSTEM_RUNNING)
0434         schedule_timeout_uninterruptible(1);
0435 
0436     t = ktime_get_mono_fast_ns();
0437     if (atomic_inc_return(&n_rcu_scale_writer_started) >= nrealwriters) {
0438         t_rcu_scale_writer_started = t;
0439         if (gp_exp) {
0440             b_rcu_gp_test_started =
0441                 cur_ops->exp_completed() / 2;
0442         } else {
0443             b_rcu_gp_test_started = cur_ops->get_gp_seq();
0444         }
0445     }
0446 
0447     do {
0448         if (writer_holdoff)
0449             udelay(writer_holdoff);
0450         wdp = &wdpp[i];
0451         *wdp = ktime_get_mono_fast_ns();
0452         if (gp_async) {
0453 retry:
0454             if (!rhp)
0455                 rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
0456             if (rhp && atomic_read(this_cpu_ptr(&n_async_inflight)) < gp_async_max) {
0457                 atomic_inc(this_cpu_ptr(&n_async_inflight));
0458                 cur_ops->async(rhp, rcu_scale_async_cb);
0459                 rhp = NULL;
0460             } else if (!kthread_should_stop()) {
0461                 cur_ops->gp_barrier();
0462                 goto retry;
0463             } else {
0464                 kfree(rhp); /* Because we are stopping. */
0465             }
0466         } else if (gp_exp) {
0467             cur_ops->exp_sync();
0468         } else {
0469             cur_ops->sync();
0470         }
0471         t = ktime_get_mono_fast_ns();
0472         *wdp = t - *wdp;
0473         i_max = i;
0474         if (!started &&
0475             atomic_read(&n_rcu_scale_writer_started) >= nrealwriters)
0476             started = true;
0477         if (!done && i >= MIN_MEAS) {
0478             done = true;
0479             sched_set_normal(current, 0);
0480             pr_alert("%s%s rcu_scale_writer %ld has %d measurements\n",
0481                  scale_type, SCALE_FLAG, me, MIN_MEAS);
0482             if (atomic_inc_return(&n_rcu_scale_writer_finished) >=
0483                 nrealwriters) {
0484                 schedule_timeout_interruptible(10);
0485                 rcu_ftrace_dump(DUMP_ALL);
0486                 SCALEOUT_STRING("Test complete");
0487                 t_rcu_scale_writer_finished = t;
0488                 if (gp_exp) {
0489                     b_rcu_gp_test_finished =
0490                         cur_ops->exp_completed() / 2;
0491                 } else {
0492                     b_rcu_gp_test_finished =
0493                         cur_ops->get_gp_seq();
0494                 }
0495                 if (shutdown) {
0496                     smp_mb(); /* Assign before wake. */
0497                     wake_up(&shutdown_wq);
0498                 }
0499             }
0500         }
0501         if (done && !alldone &&
0502             atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters)
0503             alldone = true;
0504         if (started && !alldone && i < MAX_MEAS - 1)
0505             i++;
0506         rcu_scale_wait_shutdown();
0507     } while (!torture_must_stop());
0508     if (gp_async) {
0509         cur_ops->gp_barrier();
0510     }
0511     writer_n_durations[me] = i_max + 1;
0512     torture_kthread_stopping("rcu_scale_writer");
0513     return 0;
0514 }
0515 
0516 static void
0517 rcu_scale_print_module_parms(struct rcu_scale_ops *cur_ops, const char *tag)
0518 {
0519     pr_alert("%s" SCALE_FLAG
0520          "--- %s: nreaders=%d nwriters=%d verbose=%d shutdown=%d\n",
0521          scale_type, tag, nrealreaders, nrealwriters, verbose, shutdown);
0522 }
0523 
0524 static void
0525 rcu_scale_cleanup(void)
0526 {
0527     int i;
0528     int j;
0529     int ngps = 0;
0530     u64 *wdp;
0531     u64 *wdpp;
0532 
0533     /*
0534      * Would like warning at start, but everything is expedited
0535      * during the mid-boot phase, so have to wait till the end.
0536      */
0537     if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp)
0538         SCALEOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!");
0539     if (rcu_gp_is_normal() && gp_exp)
0540         SCALEOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!");
0541     if (gp_exp && gp_async)
0542         SCALEOUT_ERRSTRING("No expedited async GPs, so went with async!");
0543 
0544     if (torture_cleanup_begin())
0545         return;
0546     if (!cur_ops) {
0547         torture_cleanup_end();
0548         return;
0549     }
0550 
0551     if (reader_tasks) {
0552         for (i = 0; i < nrealreaders; i++)
0553             torture_stop_kthread(rcu_scale_reader,
0554                          reader_tasks[i]);
0555         kfree(reader_tasks);
0556     }
0557 
0558     if (writer_tasks) {
0559         for (i = 0; i < nrealwriters; i++) {
0560             torture_stop_kthread(rcu_scale_writer,
0561                          writer_tasks[i]);
0562             if (!writer_n_durations)
0563                 continue;
0564             j = writer_n_durations[i];
0565             pr_alert("%s%s writer %d gps: %d\n",
0566                  scale_type, SCALE_FLAG, i, j);
0567             ngps += j;
0568         }
0569         pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n",
0570              scale_type, SCALE_FLAG,
0571              t_rcu_scale_writer_started, t_rcu_scale_writer_finished,
0572              t_rcu_scale_writer_finished -
0573              t_rcu_scale_writer_started,
0574              ngps,
0575              rcuscale_seq_diff(b_rcu_gp_test_finished,
0576                        b_rcu_gp_test_started));
0577         for (i = 0; i < nrealwriters; i++) {
0578             if (!writer_durations)
0579                 break;
0580             if (!writer_n_durations)
0581                 continue;
0582             wdpp = writer_durations[i];
0583             if (!wdpp)
0584                 continue;
0585             for (j = 0; j < writer_n_durations[i]; j++) {
0586                 wdp = &wdpp[j];
0587                 pr_alert("%s%s %4d writer-duration: %5d %llu\n",
0588                     scale_type, SCALE_FLAG,
0589                     i, j, *wdp);
0590                 if (j % 100 == 0)
0591                     schedule_timeout_uninterruptible(1);
0592             }
0593             kfree(writer_durations[i]);
0594         }
0595         kfree(writer_tasks);
0596         kfree(writer_durations);
0597         kfree(writer_n_durations);
0598     }
0599 
0600     /* Do torture-type-specific cleanup operations.  */
0601     if (cur_ops->cleanup != NULL)
0602         cur_ops->cleanup();
0603 
0604     torture_cleanup_end();
0605 }
0606 
0607 /*
0608  * Return the number if non-negative.  If -1, the number of CPUs.
0609  * If less than -1, that much less than the number of CPUs, but
0610  * at least one.
0611  */
0612 static int compute_real(int n)
0613 {
0614     int nr;
0615 
0616     if (n >= 0) {
0617         nr = n;
0618     } else {
0619         nr = num_online_cpus() + 1 + n;
0620         if (nr <= 0)
0621             nr = 1;
0622     }
0623     return nr;
0624 }
0625 
0626 /*
0627  * RCU scalability shutdown kthread.  Just waits to be awakened, then shuts
0628  * down system.
0629  */
0630 static int
0631 rcu_scale_shutdown(void *arg)
0632 {
0633     wait_event(shutdown_wq,
0634            atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters);
0635     smp_mb(); /* Wake before output. */
0636     rcu_scale_cleanup();
0637     kernel_power_off();
0638     return -EINVAL;
0639 }
0640 
0641 /*
0642  * kfree_rcu() scalability tests: Start a kfree_rcu() loop on all CPUs for number
0643  * of iterations and measure total time and number of GP for all iterations to complete.
0644  */
0645 
0646 torture_param(int, kfree_nthreads, -1, "Number of threads running loops of kfree_rcu().");
0647 torture_param(int, kfree_alloc_num, 8000, "Number of allocations and frees done in an iteration.");
0648 torture_param(int, kfree_loops, 10, "Number of loops doing kfree_alloc_num allocations and frees.");
0649 torture_param(bool, kfree_rcu_test_double, false, "Do we run a kfree_rcu() double-argument scale test?");
0650 torture_param(bool, kfree_rcu_test_single, false, "Do we run a kfree_rcu() single-argument scale test?");
0651 
0652 static struct task_struct **kfree_reader_tasks;
0653 static int kfree_nrealthreads;
0654 static atomic_t n_kfree_scale_thread_started;
0655 static atomic_t n_kfree_scale_thread_ended;
0656 
0657 struct kfree_obj {
0658     char kfree_obj[8];
0659     struct rcu_head rh;
0660 };
0661 
0662 static int
0663 kfree_scale_thread(void *arg)
0664 {
0665     int i, loop = 0;
0666     long me = (long)arg;
0667     struct kfree_obj *alloc_ptr;
0668     u64 start_time, end_time;
0669     long long mem_begin, mem_during = 0;
0670     bool kfree_rcu_test_both;
0671     DEFINE_TORTURE_RANDOM(tr);
0672 
0673     VERBOSE_SCALEOUT_STRING("kfree_scale_thread task started");
0674     set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids));
0675     set_user_nice(current, MAX_NICE);
0676     kfree_rcu_test_both = (kfree_rcu_test_single == kfree_rcu_test_double);
0677 
0678     start_time = ktime_get_mono_fast_ns();
0679 
0680     if (atomic_inc_return(&n_kfree_scale_thread_started) >= kfree_nrealthreads) {
0681         if (gp_exp)
0682             b_rcu_gp_test_started = cur_ops->exp_completed() / 2;
0683         else
0684             b_rcu_gp_test_started = cur_ops->get_gp_seq();
0685     }
0686 
0687     do {
0688         if (!mem_during) {
0689             mem_during = mem_begin = si_mem_available();
0690         } else if (loop % (kfree_loops / 4) == 0) {
0691             mem_during = (mem_during + si_mem_available()) / 2;
0692         }
0693 
0694         for (i = 0; i < kfree_alloc_num; i++) {
0695             alloc_ptr = kmalloc(kfree_mult * sizeof(struct kfree_obj), GFP_KERNEL);
0696             if (!alloc_ptr)
0697                 return -ENOMEM;
0698 
0699             // By default kfree_rcu_test_single and kfree_rcu_test_double are
0700             // initialized to false. If both have the same value (false or true)
0701             // both are randomly tested, otherwise only the one with value true
0702             // is tested.
0703             if ((kfree_rcu_test_single && !kfree_rcu_test_double) ||
0704                     (kfree_rcu_test_both && torture_random(&tr) & 0x800))
0705                 kfree_rcu(alloc_ptr);
0706             else
0707                 kfree_rcu(alloc_ptr, rh);
0708         }
0709 
0710         cond_resched();
0711     } while (!torture_must_stop() && ++loop < kfree_loops);
0712 
0713     if (atomic_inc_return(&n_kfree_scale_thread_ended) >= kfree_nrealthreads) {
0714         end_time = ktime_get_mono_fast_ns();
0715 
0716         if (gp_exp)
0717             b_rcu_gp_test_finished = cur_ops->exp_completed() / 2;
0718         else
0719             b_rcu_gp_test_finished = cur_ops->get_gp_seq();
0720 
0721         pr_alert("Total time taken by all kfree'ers: %llu ns, loops: %d, batches: %ld, memory footprint: %lldMB\n",
0722                (unsigned long long)(end_time - start_time), kfree_loops,
0723                rcuscale_seq_diff(b_rcu_gp_test_finished, b_rcu_gp_test_started),
0724                (mem_begin - mem_during) >> (20 - PAGE_SHIFT));
0725 
0726         if (shutdown) {
0727             smp_mb(); /* Assign before wake. */
0728             wake_up(&shutdown_wq);
0729         }
0730     }
0731 
0732     torture_kthread_stopping("kfree_scale_thread");
0733     return 0;
0734 }
0735 
0736 static void
0737 kfree_scale_cleanup(void)
0738 {
0739     int i;
0740 
0741     if (torture_cleanup_begin())
0742         return;
0743 
0744     if (kfree_reader_tasks) {
0745         for (i = 0; i < kfree_nrealthreads; i++)
0746             torture_stop_kthread(kfree_scale_thread,
0747                          kfree_reader_tasks[i]);
0748         kfree(kfree_reader_tasks);
0749     }
0750 
0751     torture_cleanup_end();
0752 }
0753 
0754 /*
0755  * shutdown kthread.  Just waits to be awakened, then shuts down system.
0756  */
0757 static int
0758 kfree_scale_shutdown(void *arg)
0759 {
0760     wait_event(shutdown_wq,
0761            atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads);
0762 
0763     smp_mb(); /* Wake before output. */
0764 
0765     kfree_scale_cleanup();
0766     kernel_power_off();
0767     return -EINVAL;
0768 }
0769 
0770 static int __init
0771 kfree_scale_init(void)
0772 {
0773     long i;
0774     int firsterr = 0;
0775 
0776     kfree_nrealthreads = compute_real(kfree_nthreads);
0777     /* Start up the kthreads. */
0778     if (shutdown) {
0779         init_waitqueue_head(&shutdown_wq);
0780         firsterr = torture_create_kthread(kfree_scale_shutdown, NULL,
0781                           shutdown_task);
0782         if (torture_init_error(firsterr))
0783             goto unwind;
0784         schedule_timeout_uninterruptible(1);
0785     }
0786 
0787     pr_alert("kfree object size=%zu\n", kfree_mult * sizeof(struct kfree_obj));
0788 
0789     kfree_reader_tasks = kcalloc(kfree_nrealthreads, sizeof(kfree_reader_tasks[0]),
0790                    GFP_KERNEL);
0791     if (kfree_reader_tasks == NULL) {
0792         firsterr = -ENOMEM;
0793         goto unwind;
0794     }
0795 
0796     for (i = 0; i < kfree_nrealthreads; i++) {
0797         firsterr = torture_create_kthread(kfree_scale_thread, (void *)i,
0798                           kfree_reader_tasks[i]);
0799         if (torture_init_error(firsterr))
0800             goto unwind;
0801     }
0802 
0803     while (atomic_read(&n_kfree_scale_thread_started) < kfree_nrealthreads)
0804         schedule_timeout_uninterruptible(1);
0805 
0806     torture_init_end();
0807     return 0;
0808 
0809 unwind:
0810     torture_init_end();
0811     kfree_scale_cleanup();
0812     return firsterr;
0813 }
0814 
0815 static int __init
0816 rcu_scale_init(void)
0817 {
0818     long i;
0819     int firsterr = 0;
0820     static struct rcu_scale_ops *scale_ops[] = {
0821         &rcu_ops, &srcu_ops, &srcud_ops, TASKS_OPS TASKS_TRACING_OPS
0822     };
0823 
0824     if (!torture_init_begin(scale_type, verbose))
0825         return -EBUSY;
0826 
0827     /* Process args and announce that the scalability'er is on the job. */
0828     for (i = 0; i < ARRAY_SIZE(scale_ops); i++) {
0829         cur_ops = scale_ops[i];
0830         if (strcmp(scale_type, cur_ops->name) == 0)
0831             break;
0832     }
0833     if (i == ARRAY_SIZE(scale_ops)) {
0834         pr_alert("rcu-scale: invalid scale type: \"%s\"\n", scale_type);
0835         pr_alert("rcu-scale types:");
0836         for (i = 0; i < ARRAY_SIZE(scale_ops); i++)
0837             pr_cont(" %s", scale_ops[i]->name);
0838         pr_cont("\n");
0839         firsterr = -EINVAL;
0840         cur_ops = NULL;
0841         goto unwind;
0842     }
0843     if (cur_ops->init)
0844         cur_ops->init();
0845 
0846     if (kfree_rcu_test)
0847         return kfree_scale_init();
0848 
0849     nrealwriters = compute_real(nwriters);
0850     nrealreaders = compute_real(nreaders);
0851     atomic_set(&n_rcu_scale_reader_started, 0);
0852     atomic_set(&n_rcu_scale_writer_started, 0);
0853     atomic_set(&n_rcu_scale_writer_finished, 0);
0854     rcu_scale_print_module_parms(cur_ops, "Start of test");
0855 
0856     /* Start up the kthreads. */
0857 
0858     if (shutdown) {
0859         init_waitqueue_head(&shutdown_wq);
0860         firsterr = torture_create_kthread(rcu_scale_shutdown, NULL,
0861                           shutdown_task);
0862         if (torture_init_error(firsterr))
0863             goto unwind;
0864         schedule_timeout_uninterruptible(1);
0865     }
0866     reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]),
0867                    GFP_KERNEL);
0868     if (reader_tasks == NULL) {
0869         SCALEOUT_ERRSTRING("out of memory");
0870         firsterr = -ENOMEM;
0871         goto unwind;
0872     }
0873     for (i = 0; i < nrealreaders; i++) {
0874         firsterr = torture_create_kthread(rcu_scale_reader, (void *)i,
0875                           reader_tasks[i]);
0876         if (torture_init_error(firsterr))
0877             goto unwind;
0878     }
0879     while (atomic_read(&n_rcu_scale_reader_started) < nrealreaders)
0880         schedule_timeout_uninterruptible(1);
0881     writer_tasks = kcalloc(nrealwriters, sizeof(reader_tasks[0]),
0882                    GFP_KERNEL);
0883     writer_durations = kcalloc(nrealwriters, sizeof(*writer_durations),
0884                    GFP_KERNEL);
0885     writer_n_durations =
0886         kcalloc(nrealwriters, sizeof(*writer_n_durations),
0887             GFP_KERNEL);
0888     if (!writer_tasks || !writer_durations || !writer_n_durations) {
0889         SCALEOUT_ERRSTRING("out of memory");
0890         firsterr = -ENOMEM;
0891         goto unwind;
0892     }
0893     for (i = 0; i < nrealwriters; i++) {
0894         writer_durations[i] =
0895             kcalloc(MAX_MEAS, sizeof(*writer_durations[i]),
0896                 GFP_KERNEL);
0897         if (!writer_durations[i]) {
0898             firsterr = -ENOMEM;
0899             goto unwind;
0900         }
0901         firsterr = torture_create_kthread(rcu_scale_writer, (void *)i,
0902                           writer_tasks[i]);
0903         if (torture_init_error(firsterr))
0904             goto unwind;
0905     }
0906     torture_init_end();
0907     return 0;
0908 
0909 unwind:
0910     torture_init_end();
0911     rcu_scale_cleanup();
0912     if (shutdown) {
0913         WARN_ON(!IS_MODULE(CONFIG_RCU_SCALE_TEST));
0914         kernel_power_off();
0915     }
0916     return firsterr;
0917 }
0918 
0919 module_init(rcu_scale_init);
0920 module_exit(rcu_scale_cleanup);