diff options
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r-- | kernel/rcutorture.c | 73 |
1 files changed, 56 insertions, 17 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 697c0a0229d4..9bb52177af02 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
@@ -327,6 +327,11 @@ rcu_torture_cb(struct rcu_head *p) | |||
327 | cur_ops->deferred_free(rp); | 327 | cur_ops->deferred_free(rp); |
328 | } | 328 | } |
329 | 329 | ||
330 | static int rcu_no_completed(void) | ||
331 | { | ||
332 | return 0; | ||
333 | } | ||
334 | |||
330 | static void rcu_torture_deferred_free(struct rcu_torture *p) | 335 | static void rcu_torture_deferred_free(struct rcu_torture *p) |
331 | { | 336 | { |
332 | call_rcu(&p->rtort_rcu, rcu_torture_cb); | 337 | call_rcu(&p->rtort_rcu, rcu_torture_cb); |
@@ -388,6 +393,21 @@ static struct rcu_torture_ops rcu_sync_ops = { | |||
388 | .name = "rcu_sync" | 393 | .name = "rcu_sync" |
389 | }; | 394 | }; |
390 | 395 | ||
396 | static struct rcu_torture_ops rcu_expedited_ops = { | ||
397 | .init = rcu_sync_torture_init, | ||
398 | .cleanup = NULL, | ||
399 | .readlock = rcu_torture_read_lock, | ||
400 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ | ||
401 | .readunlock = rcu_torture_read_unlock, | ||
402 | .completed = rcu_no_completed, | ||
403 | .deferred_free = rcu_sync_torture_deferred_free, | ||
404 | .sync = synchronize_rcu_expedited, | ||
405 | .cb_barrier = NULL, | ||
406 | .stats = NULL, | ||
407 | .irq_capable = 1, | ||
408 | .name = "rcu_expedited" | ||
409 | }; | ||
410 | |||
391 | /* | 411 | /* |
392 | * Definitions for rcu_bh torture testing. | 412 | * Definitions for rcu_bh torture testing. |
393 | */ | 413 | */ |
@@ -547,6 +567,25 @@ static struct rcu_torture_ops srcu_ops = { | |||
547 | .name = "srcu" | 567 | .name = "srcu" |
548 | }; | 568 | }; |
549 | 569 | ||
570 | static void srcu_torture_synchronize_expedited(void) | ||
571 | { | ||
572 | synchronize_srcu_expedited(&srcu_ctl); | ||
573 | } | ||
574 | |||
575 | static struct rcu_torture_ops srcu_expedited_ops = { | ||
576 | .init = srcu_torture_init, | ||
577 | .cleanup = srcu_torture_cleanup, | ||
578 | .readlock = srcu_torture_read_lock, | ||
579 | .read_delay = srcu_read_delay, | ||
580 | .readunlock = srcu_torture_read_unlock, | ||
581 | .completed = srcu_torture_completed, | ||
582 | .deferred_free = rcu_sync_torture_deferred_free, | ||
583 | .sync = srcu_torture_synchronize_expedited, | ||
584 | .cb_barrier = NULL, | ||
585 | .stats = srcu_torture_stats, | ||
586 | .name = "srcu_expedited" | ||
587 | }; | ||
588 | |||
550 | /* | 589 | /* |
551 | * Definitions for sched torture testing. | 590 | * Definitions for sched torture testing. |
552 | */ | 591 | */ |
@@ -562,11 +601,6 @@ static void sched_torture_read_unlock(int idx) | |||
562 | preempt_enable(); | 601 | preempt_enable(); |
563 | } | 602 | } |
564 | 603 | ||
565 | static int sched_torture_completed(void) | ||
566 | { | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static void rcu_sched_torture_deferred_free(struct rcu_torture *p) | 604 | static void rcu_sched_torture_deferred_free(struct rcu_torture *p) |
571 | { | 605 | { |
572 | call_rcu_sched(&p->rtort_rcu, rcu_torture_cb); | 606 | call_rcu_sched(&p->rtort_rcu, rcu_torture_cb); |
@@ -583,7 +617,7 @@ static struct rcu_torture_ops sched_ops = { | |||
583 | .readlock = sched_torture_read_lock, | 617 | .readlock = sched_torture_read_lock, |
584 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ | 618 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ |
585 | .readunlock = sched_torture_read_unlock, | 619 | .readunlock = sched_torture_read_unlock, |
586 | .completed = sched_torture_completed, | 620 | .completed = rcu_no_completed, |
587 | .deferred_free = rcu_sched_torture_deferred_free, | 621 | .deferred_free = rcu_sched_torture_deferred_free, |
588 | .sync = sched_torture_synchronize, | 622 | .sync = sched_torture_synchronize, |
589 | .cb_barrier = rcu_barrier_sched, | 623 | .cb_barrier = rcu_barrier_sched, |
@@ -592,13 +626,13 @@ static struct rcu_torture_ops sched_ops = { | |||
592 | .name = "sched" | 626 | .name = "sched" |
593 | }; | 627 | }; |
594 | 628 | ||
595 | static struct rcu_torture_ops sched_ops_sync = { | 629 | static struct rcu_torture_ops sched_sync_ops = { |
596 | .init = rcu_sync_torture_init, | 630 | .init = rcu_sync_torture_init, |
597 | .cleanup = NULL, | 631 | .cleanup = NULL, |
598 | .readlock = sched_torture_read_lock, | 632 | .readlock = sched_torture_read_lock, |
599 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ | 633 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ |
600 | .readunlock = sched_torture_read_unlock, | 634 | .readunlock = sched_torture_read_unlock, |
601 | .completed = sched_torture_completed, | 635 | .completed = rcu_no_completed, |
602 | .deferred_free = rcu_sync_torture_deferred_free, | 636 | .deferred_free = rcu_sync_torture_deferred_free, |
603 | .sync = sched_torture_synchronize, | 637 | .sync = sched_torture_synchronize, |
604 | .cb_barrier = NULL, | 638 | .cb_barrier = NULL, |
@@ -612,7 +646,7 @@ static struct rcu_torture_ops sched_expedited_ops = { | |||
612 | .readlock = sched_torture_read_lock, | 646 | .readlock = sched_torture_read_lock, |
613 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ | 647 | .read_delay = rcu_read_delay, /* just reuse rcu's version. */ |
614 | .readunlock = sched_torture_read_unlock, | 648 | .readunlock = sched_torture_read_unlock, |
615 | .completed = sched_torture_completed, | 649 | .completed = rcu_no_completed, |
616 | .deferred_free = rcu_sync_torture_deferred_free, | 650 | .deferred_free = rcu_sync_torture_deferred_free, |
617 | .sync = synchronize_sched_expedited, | 651 | .sync = synchronize_sched_expedited, |
618 | .cb_barrier = NULL, | 652 | .cb_barrier = NULL, |
@@ -729,13 +763,13 @@ static void rcu_torture_timer(unsigned long unused) | |||
729 | /* Should not happen, but... */ | 763 | /* Should not happen, but... */ |
730 | pipe_count = RCU_TORTURE_PIPE_LEN; | 764 | pipe_count = RCU_TORTURE_PIPE_LEN; |
731 | } | 765 | } |
732 | ++__get_cpu_var(rcu_torture_count)[pipe_count]; | 766 | __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]); |
733 | completed = cur_ops->completed() - completed; | 767 | completed = cur_ops->completed() - completed; |
734 | if (completed > RCU_TORTURE_PIPE_LEN) { | 768 | if (completed > RCU_TORTURE_PIPE_LEN) { |
735 | /* Should not happen, but... */ | 769 | /* Should not happen, but... */ |
736 | completed = RCU_TORTURE_PIPE_LEN; | 770 | completed = RCU_TORTURE_PIPE_LEN; |
737 | } | 771 | } |
738 | ++__get_cpu_var(rcu_torture_batch)[completed]; | 772 | __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]); |
739 | preempt_enable(); | 773 | preempt_enable(); |
740 | cur_ops->readunlock(idx); | 774 | cur_ops->readunlock(idx); |
741 | } | 775 | } |
@@ -784,13 +818,13 @@ rcu_torture_reader(void *arg) | |||
784 | /* Should not happen, but... */ | 818 | /* Should not happen, but... */ |
785 | pipe_count = RCU_TORTURE_PIPE_LEN; | 819 | pipe_count = RCU_TORTURE_PIPE_LEN; |
786 | } | 820 | } |
787 | ++__get_cpu_var(rcu_torture_count)[pipe_count]; | 821 | __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]); |
788 | completed = cur_ops->completed() - completed; | 822 | completed = cur_ops->completed() - completed; |
789 | if (completed > RCU_TORTURE_PIPE_LEN) { | 823 | if (completed > RCU_TORTURE_PIPE_LEN) { |
790 | /* Should not happen, but... */ | 824 | /* Should not happen, but... */ |
791 | completed = RCU_TORTURE_PIPE_LEN; | 825 | completed = RCU_TORTURE_PIPE_LEN; |
792 | } | 826 | } |
793 | ++__get_cpu_var(rcu_torture_batch)[completed]; | 827 | __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]); |
794 | preempt_enable(); | 828 | preempt_enable(); |
795 | cur_ops->readunlock(idx); | 829 | cur_ops->readunlock(idx); |
796 | schedule(); | 830 | schedule(); |
@@ -1097,9 +1131,10 @@ rcu_torture_init(void) | |||
1097 | int cpu; | 1131 | int cpu; |
1098 | int firsterr = 0; | 1132 | int firsterr = 0; |
1099 | static struct rcu_torture_ops *torture_ops[] = | 1133 | static struct rcu_torture_ops *torture_ops[] = |
1100 | { &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, | 1134 | { &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops, |
1101 | &sched_expedited_ops, | 1135 | &rcu_bh_ops, &rcu_bh_sync_ops, |
1102 | &srcu_ops, &sched_ops, &sched_ops_sync, }; | 1136 | &srcu_ops, &srcu_expedited_ops, |
1137 | &sched_ops, &sched_sync_ops, &sched_expedited_ops, }; | ||
1103 | 1138 | ||
1104 | mutex_lock(&fullstop_mutex); | 1139 | mutex_lock(&fullstop_mutex); |
1105 | 1140 | ||
@@ -1110,8 +1145,12 @@ rcu_torture_init(void) | |||
1110 | break; | 1145 | break; |
1111 | } | 1146 | } |
1112 | if (i == ARRAY_SIZE(torture_ops)) { | 1147 | if (i == ARRAY_SIZE(torture_ops)) { |
1113 | printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n", | 1148 | printk(KERN_ALERT "rcu-torture: invalid torture type: \"%s\"\n", |
1114 | torture_type); | 1149 | torture_type); |
1150 | printk(KERN_ALERT "rcu-torture types:"); | ||
1151 | for (i = 0; i < ARRAY_SIZE(torture_ops); i++) | ||
1152 | printk(KERN_ALERT " %s", torture_ops[i]->name); | ||
1153 | printk(KERN_ALERT "\n"); | ||
1115 | mutex_unlock(&fullstop_mutex); | 1154 | mutex_unlock(&fullstop_mutex); |
1116 | return -EINVAL; | 1155 | return -EINVAL; |
1117 | } | 1156 | } |