diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-02-03 14:52:27 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-02-23 12:03:24 -0500 |
commit | 47cf29b9e721967aac95ebda9e50408219755852 (patch) | |
tree | 9f35fcc13e7411c277094b9740d94fab14323a8b | |
parent | bc8f83e2c0d585b201dfbb52e98f6f8741d324ea (diff) |
rcutorture: Abstract torture_create_kthread()
Creation of kthreads is not RCU-specific, so this commit abstracts
out torture_create_kthread(), saving a few tens of lines of code in
the process.
This change requires modifying VERBOSE_TOROUT_ERRSTRING() to take a
non-const string, so that _torture_create_kthread() can avoid an
open-coded substitute.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r-- | include/linux/torture.h | 8 | ||||
-rw-r--r-- | kernel/rcu/rcutorture.c | 98 | ||||
-rw-r--r-- | kernel/torture.c | 80 |
3 files changed, 60 insertions, 126 deletions
diff --git a/include/linux/torture.h b/include/linux/torture.h index 2ea11094daf6..430cc3008628 100644 --- a/include/linux/torture.h +++ b/include/linux/torture.h | |||
@@ -47,7 +47,7 @@ | |||
47 | #define VERBOSE_TOROUT_STRING(s) \ | 47 | #define VERBOSE_TOROUT_STRING(s) \ |
48 | do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0) | 48 | do { if (verbose) pr_alert("%s" TORTURE_FLAG " %s\n", torture_type, s); } while (0) |
49 | #define VERBOSE_TOROUT_ERRSTRING(s) \ | 49 | #define VERBOSE_TOROUT_ERRSTRING(s) \ |
50 | do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0) | 50 | do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0) |
51 | 51 | ||
52 | /* Definitions for a non-string torture-test module parameter. */ | 52 | /* Definitions for a non-string torture-test module parameter. */ |
53 | #define torture_parm(type, name, init, msg) \ | 53 | #define torture_parm(type, name, init, msg) \ |
@@ -89,5 +89,11 @@ bool torture_cleanup(void); | |||
89 | bool torture_must_stop(void); | 89 | bool torture_must_stop(void); |
90 | bool torture_must_stop_irq(void); | 90 | bool torture_must_stop_irq(void); |
91 | void torture_kthread_stopping(char *title); | 91 | void torture_kthread_stopping(char *title); |
92 | int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m, | ||
93 | char *f, struct task_struct **tp); | ||
94 | |||
95 | #define torture_create_kthread(n, arg, tp) \ | ||
96 | _torture_create_kthread(n, (arg), #n, "Creating " #n " task", \ | ||
97 | "Failed to create " #n, &(tp)) | ||
92 | 98 | ||
93 | #endif /* __LINUX_TORTURE_H */ | 99 | #endif /* __LINUX_TORTURE_H */ |
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 25e9b16fe7f0..a6f6c8418d87 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c | |||
@@ -1105,19 +1105,9 @@ static int rcu_torture_stall(void *args) | |||
1105 | /* Spawn CPU-stall kthread, if stall_cpu specified. */ | 1105 | /* Spawn CPU-stall kthread, if stall_cpu specified. */ |
1106 | static int __init rcu_torture_stall_init(void) | 1106 | static int __init rcu_torture_stall_init(void) |
1107 | { | 1107 | { |
1108 | int ret; | ||
1109 | |||
1110 | if (stall_cpu <= 0) | 1108 | if (stall_cpu <= 0) |
1111 | return 0; | 1109 | return 0; |
1112 | VERBOSE_TOROUT_STRING("Creating rcu_torture_stall task"); | 1110 | return torture_create_kthread(rcu_torture_stall, NULL, stall_task); |
1113 | stall_task = kthread_run(rcu_torture_stall, NULL, "rcu_torture_stall"); | ||
1114 | if (IS_ERR(stall_task)) { | ||
1115 | ret = PTR_ERR(stall_task); | ||
1116 | stall_task = NULL; | ||
1117 | return ret; | ||
1118 | } | ||
1119 | torture_shuffle_task_register(stall_task); | ||
1120 | return 0; | ||
1121 | } | 1111 | } |
1122 | 1112 | ||
1123 | /* Clean up after the CPU-stall kthread, if one was spawned. */ | 1113 | /* Clean up after the CPU-stall kthread, if one was spawned. */ |
@@ -1226,29 +1216,13 @@ static int rcu_torture_barrier_init(void) | |||
1226 | return -ENOMEM; | 1216 | return -ENOMEM; |
1227 | for (i = 0; i < n_barrier_cbs; i++) { | 1217 | for (i = 0; i < n_barrier_cbs; i++) { |
1228 | init_waitqueue_head(&barrier_cbs_wq[i]); | 1218 | init_waitqueue_head(&barrier_cbs_wq[i]); |
1229 | VERBOSE_TOROUT_STRING("Creating rcu_torture_barrier_cbs task"); | 1219 | ret = torture_create_kthread(rcu_torture_barrier_cbs, |
1230 | barrier_cbs_tasks[i] = kthread_run(rcu_torture_barrier_cbs, | 1220 | (void *)(long)i, |
1231 | (void *)(long)i, | 1221 | barrier_cbs_tasks[i]); |
1232 | "rcu_torture_barrier_cbs"); | 1222 | if (ret) |
1233 | if (IS_ERR(barrier_cbs_tasks[i])) { | ||
1234 | ret = PTR_ERR(barrier_cbs_tasks[i]); | ||
1235 | VERBOSE_TOROUT_ERRSTRING("Failed to create rcu_torture_barrier_cbs"); | ||
1236 | barrier_cbs_tasks[i] = NULL; | ||
1237 | return ret; | 1223 | return ret; |
1238 | } | ||
1239 | torture_shuffle_task_register(barrier_cbs_tasks[i]); | ||
1240 | } | 1224 | } |
1241 | VERBOSE_TOROUT_STRING("Creating rcu_torture_barrier task"); | 1225 | return torture_create_kthread(rcu_torture_barrier, NULL, barrier_task); |
1242 | barrier_task = kthread_run(rcu_torture_barrier, NULL, | ||
1243 | "rcu_torture_barrier"); | ||
1244 | if (IS_ERR(barrier_task)) { | ||
1245 | ret = PTR_ERR(barrier_task); | ||
1246 | VERBOSE_TOROUT_ERRSTRING("Failed to create rcu_torture_barrier"); | ||
1247 | barrier_task = NULL; | ||
1248 | return ret; | ||
1249 | } | ||
1250 | torture_shuffle_task_register(barrier_task); | ||
1251 | return 0; | ||
1252 | } | 1226 | } |
1253 | 1227 | ||
1254 | /* Clean up after RCU barrier testing. */ | 1228 | /* Clean up after RCU barrier testing. */ |
@@ -1516,17 +1490,10 @@ rcu_torture_init(void) | |||
1516 | 1490 | ||
1517 | /* Start up the kthreads. */ | 1491 | /* Start up the kthreads. */ |
1518 | 1492 | ||
1519 | VERBOSE_TOROUT_STRING("Creating rcu_torture_writer task"); | 1493 | firsterr = torture_create_kthread(rcu_torture_writer, NULL, |
1520 | writer_task = kthread_create(rcu_torture_writer, NULL, | 1494 | writer_task); |
1521 | "rcu_torture_writer"); | 1495 | if (firsterr) |
1522 | if (IS_ERR(writer_task)) { | ||
1523 | firsterr = PTR_ERR(writer_task); | ||
1524 | VERBOSE_TOROUT_ERRSTRING("Failed to create writer"); | ||
1525 | writer_task = NULL; | ||
1526 | goto unwind; | 1496 | goto unwind; |
1527 | } | ||
1528 | torture_shuffle_task_register(writer_task); | ||
1529 | wake_up_process(writer_task); | ||
1530 | fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), | 1497 | fakewriter_tasks = kzalloc(nfakewriters * sizeof(fakewriter_tasks[0]), |
1531 | GFP_KERNEL); | 1498 | GFP_KERNEL); |
1532 | if (fakewriter_tasks == NULL) { | 1499 | if (fakewriter_tasks == NULL) { |
@@ -1535,16 +1502,10 @@ rcu_torture_init(void) | |||
1535 | goto unwind; | 1502 | goto unwind; |
1536 | } | 1503 | } |
1537 | for (i = 0; i < nfakewriters; i++) { | 1504 | for (i = 0; i < nfakewriters; i++) { |
1538 | VERBOSE_TOROUT_STRING("Creating rcu_torture_fakewriter task"); | 1505 | firsterr = torture_create_kthread(rcu_torture_fakewriter, |
1539 | fakewriter_tasks[i] = kthread_run(rcu_torture_fakewriter, NULL, | 1506 | NULL, fakewriter_tasks[i]); |
1540 | "rcu_torture_fakewriter"); | 1507 | if (firsterr) |
1541 | if (IS_ERR(fakewriter_tasks[i])) { | ||
1542 | firsterr = PTR_ERR(fakewriter_tasks[i]); | ||
1543 | VERBOSE_TOROUT_ERRSTRING("Failed to create fakewriter"); | ||
1544 | fakewriter_tasks[i] = NULL; | ||
1545 | goto unwind; | 1508 | goto unwind; |
1546 | } | ||
1547 | torture_shuffle_task_register(fakewriter_tasks[i]); | ||
1548 | } | 1509 | } |
1549 | reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]), | 1510 | reader_tasks = kzalloc(nrealreaders * sizeof(reader_tasks[0]), |
1550 | GFP_KERNEL); | 1511 | GFP_KERNEL); |
@@ -1554,28 +1515,16 @@ rcu_torture_init(void) | |||
1554 | goto unwind; | 1515 | goto unwind; |
1555 | } | 1516 | } |
1556 | for (i = 0; i < nrealreaders; i++) { | 1517 | for (i = 0; i < nrealreaders; i++) { |
1557 | VERBOSE_TOROUT_STRING("Creating rcu_torture_reader task"); | 1518 | firsterr = torture_create_kthread(rcu_torture_reader, NULL, |
1558 | reader_tasks[i] = kthread_run(rcu_torture_reader, NULL, | 1519 | reader_tasks[i]); |
1559 | "rcu_torture_reader"); | 1520 | if (firsterr) |
1560 | if (IS_ERR(reader_tasks[i])) { | ||
1561 | firsterr = PTR_ERR(reader_tasks[i]); | ||
1562 | VERBOSE_TOROUT_ERRSTRING("Failed to create reader"); | ||
1563 | reader_tasks[i] = NULL; | ||
1564 | goto unwind; | 1521 | goto unwind; |
1565 | } | ||
1566 | torture_shuffle_task_register(reader_tasks[i]); | ||
1567 | } | 1522 | } |
1568 | if (stat_interval > 0) { | 1523 | if (stat_interval > 0) { |
1569 | VERBOSE_TOROUT_STRING("Creating rcu_torture_stats task"); | 1524 | firsterr = torture_create_kthread(rcu_torture_stats, NULL, |
1570 | stats_task = kthread_run(rcu_torture_stats, NULL, | 1525 | stats_task); |
1571 | "rcu_torture_stats"); | 1526 | if (firsterr) |
1572 | if (IS_ERR(stats_task)) { | ||
1573 | firsterr = PTR_ERR(stats_task); | ||
1574 | VERBOSE_TOROUT_ERRSTRING("Failed to create stats"); | ||
1575 | stats_task = NULL; | ||
1576 | goto unwind; | 1527 | goto unwind; |
1577 | } | ||
1578 | torture_shuffle_task_register(stats_task); | ||
1579 | } | 1528 | } |
1580 | if (test_no_idle_hz) { | 1529 | if (test_no_idle_hz) { |
1581 | firsterr = torture_shuffle_init(shuffle_interval * HZ); | 1530 | firsterr = torture_shuffle_init(shuffle_interval * HZ); |
@@ -1593,16 +1542,9 @@ rcu_torture_init(void) | |||
1593 | fqs_duration = 0; | 1542 | fqs_duration = 0; |
1594 | if (fqs_duration) { | 1543 | if (fqs_duration) { |
1595 | /* Create the fqs thread */ | 1544 | /* Create the fqs thread */ |
1596 | VERBOSE_TOROUT_STRING("Creating rcu_torture_fqs task"); | 1545 | torture_create_kthread(rcu_torture_fqs, NULL, fqs_task); |
1597 | fqs_task = kthread_run(rcu_torture_fqs, NULL, | 1546 | if (firsterr) |
1598 | "rcu_torture_fqs"); | ||
1599 | if (IS_ERR(fqs_task)) { | ||
1600 | firsterr = PTR_ERR(fqs_task); | ||
1601 | VERBOSE_TOROUT_ERRSTRING("Failed to create fqs"); | ||
1602 | fqs_task = NULL; | ||
1603 | goto unwind; | 1547 | goto unwind; |
1604 | } | ||
1605 | torture_shuffle_task_register(fqs_task); | ||
1606 | } | 1548 | } |
1607 | if (test_boost_interval < 1) | 1549 | if (test_boost_interval < 1) |
1608 | test_boost_interval = 1; | 1550 | test_boost_interval = 1; |
diff --git a/kernel/torture.c b/kernel/torture.c index 330576660cf4..439451821a7f 100644 --- a/kernel/torture.c +++ b/kernel/torture.c | |||
@@ -180,23 +180,16 @@ torture_onoff(void *arg) | |||
180 | */ | 180 | */ |
181 | int torture_onoff_init(long ooholdoff, long oointerval) | 181 | int torture_onoff_init(long ooholdoff, long oointerval) |
182 | { | 182 | { |
183 | #ifdef CONFIG_HOTPLUG_CPU | 183 | int ret = 0; |
184 | int ret; | ||
185 | 184 | ||
185 | #ifdef CONFIG_HOTPLUG_CPU | ||
186 | onoff_holdoff = ooholdoff; | 186 | onoff_holdoff = ooholdoff; |
187 | onoff_interval = oointerval; | 187 | onoff_interval = oointerval; |
188 | if (onoff_interval <= 0) | 188 | if (onoff_interval <= 0) |
189 | return 0; | 189 | return 0; |
190 | VERBOSE_TOROUT_STRING("Creating torture_onoff task"); | 190 | ret = torture_create_kthread(torture_onoff, NULL, onoff_task); |
191 | onoff_task = kthread_run(torture_onoff, NULL, "torture_onoff"); | ||
192 | if (IS_ERR(onoff_task)) { | ||
193 | ret = PTR_ERR(onoff_task); | ||
194 | onoff_task = NULL; | ||
195 | return ret; | ||
196 | } | ||
197 | torture_shuffle_task_register(onoff_task); | ||
198 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ | 191 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ |
199 | return 0; | 192 | return ret; |
200 | } | 193 | } |
201 | EXPORT_SYMBOL_GPL(torture_onoff_init); | 194 | EXPORT_SYMBOL_GPL(torture_onoff_init); |
202 | 195 | ||
@@ -379,8 +372,6 @@ static int torture_shuffle(void *arg) | |||
379 | */ | 372 | */ |
380 | int torture_shuffle_init(long shuffint) | 373 | int torture_shuffle_init(long shuffint) |
381 | { | 374 | { |
382 | int ret; | ||
383 | |||
384 | shuffle_interval = shuffint; | 375 | shuffle_interval = shuffint; |
385 | 376 | ||
386 | shuffle_idle_cpu = -1; | 377 | shuffle_idle_cpu = -1; |
@@ -391,17 +382,7 @@ int torture_shuffle_init(long shuffint) | |||
391 | } | 382 | } |
392 | 383 | ||
393 | /* Create the shuffler thread */ | 384 | /* Create the shuffler thread */ |
394 | VERBOSE_TOROUT_STRING("Creating torture_shuffle task"); | 385 | return torture_create_kthread(torture_shuffle, NULL, shuffler_task); |
395 | shuffler_task = kthread_run(torture_shuffle, NULL, "torture_shuffle"); | ||
396 | if (IS_ERR(shuffler_task)) { | ||
397 | ret = PTR_ERR(shuffler_task); | ||
398 | free_cpumask_var(shuffle_tmp_mask); | ||
399 | VERBOSE_TOROUT_ERRSTRING("Failed to create shuffler"); | ||
400 | shuffler_task = NULL; | ||
401 | return ret; | ||
402 | } | ||
403 | torture_shuffle_task_register(shuffler_task); | ||
404 | return 0; | ||
405 | } | 386 | } |
406 | EXPORT_SYMBOL_GPL(torture_shuffle_init); | 387 | EXPORT_SYMBOL_GPL(torture_shuffle_init); |
407 | 388 | ||
@@ -483,25 +464,16 @@ static int torture_shutdown(void *arg) | |||
483 | */ | 464 | */ |
484 | int torture_shutdown_init(int ssecs, void (*cleanup)(void)) | 465 | int torture_shutdown_init(int ssecs, void (*cleanup)(void)) |
485 | { | 466 | { |
486 | int ret; | 467 | int ret = 0; |
487 | 468 | ||
488 | shutdown_secs = ssecs; | 469 | shutdown_secs = ssecs; |
489 | torture_shutdown_hook = cleanup; | 470 | torture_shutdown_hook = cleanup; |
490 | if (shutdown_secs > 0) { | 471 | if (shutdown_secs > 0) { |
491 | VERBOSE_TOROUT_STRING("Creating torture_shutdown task"); | ||
492 | shutdown_time = jiffies + shutdown_secs * HZ; | 472 | shutdown_time = jiffies + shutdown_secs * HZ; |
493 | shutdown_task = kthread_create(torture_shutdown, NULL, | 473 | ret = torture_create_kthread(torture_shutdown, NULL, |
494 | "torture_shutdown"); | 474 | shutdown_task); |
495 | if (IS_ERR(shutdown_task)) { | ||
496 | ret = PTR_ERR(shutdown_task); | ||
497 | VERBOSE_TOROUT_ERRSTRING("Failed to create shutdown"); | ||
498 | shutdown_task = NULL; | ||
499 | return ret; | ||
500 | } | ||
501 | torture_shuffle_task_register(shutdown_task); | ||
502 | wake_up_process(shutdown_task); | ||
503 | } | 475 | } |
504 | return 0; | 476 | return ret; |
505 | } | 477 | } |
506 | EXPORT_SYMBOL_GPL(torture_shutdown_init); | 478 | EXPORT_SYMBOL_GPL(torture_shutdown_init); |
507 | 479 | ||
@@ -595,16 +567,8 @@ int torture_stutter_init(int s) | |||
595 | int ret; | 567 | int ret; |
596 | 568 | ||
597 | stutter = s; | 569 | stutter = s; |
598 | VERBOSE_TOROUT_STRING("Creating torture_stutter task"); | 570 | ret = torture_create_kthread(torture_stutter, NULL, stutter_task); |
599 | stutter_task = kthread_run(torture_stutter, NULL, "torture_stutter"); | 571 | return ret; |
600 | if (IS_ERR(stutter_task)) { | ||
601 | ret = PTR_ERR(stutter_task); | ||
602 | VERBOSE_TOROUT_ERRSTRING("Failed to create stutter"); | ||
603 | stutter_task = NULL; | ||
604 | return ret; | ||
605 | } | ||
606 | torture_shuffle_task_register(stutter_task); | ||
607 | return 0; | ||
608 | } | 572 | } |
609 | EXPORT_SYMBOL_GPL(torture_stutter_init); | 573 | EXPORT_SYMBOL_GPL(torture_stutter_init); |
610 | 574 | ||
@@ -714,3 +678,25 @@ void torture_kthread_stopping(char *title) | |||
714 | } | 678 | } |
715 | } | 679 | } |
716 | EXPORT_SYMBOL_GPL(torture_kthread_stopping); | 680 | EXPORT_SYMBOL_GPL(torture_kthread_stopping); |
681 | |||
682 | /* | ||
683 | * Create a generic torture kthread that is immediately runnable. If you | ||
684 | * need the kthread to be stopped so that you can do something to it before | ||
685 | * it starts, you will need to open-code your own. | ||
686 | */ | ||
687 | int _torture_create_kthread(int (*fn)(void *arg), void *arg, char *s, char *m, | ||
688 | char *f, struct task_struct **tp) | ||
689 | { | ||
690 | int ret = 0; | ||
691 | |||
692 | VERBOSE_TOROUT_STRING(m); | ||
693 | *tp = kthread_run(fn, arg, s); | ||
694 | if (IS_ERR(*tp)) { | ||
695 | ret = PTR_ERR(*tp); | ||
696 | VERBOSE_TOROUT_ERRSTRING(f); | ||
697 | *tp = NULL; | ||
698 | } | ||
699 | torture_shuffle_task_register(*tp); | ||
700 | return ret; | ||
701 | } | ||
702 | EXPORT_SYMBOL_GPL(_torture_create_kthread); | ||