diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2008-12-31 23:05:57 +1030 | 
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-12-31 23:05:57 +1030 | 
| commit | 2ca1a615835d9f4990f42102ab1f2ef434e7e89c (patch) | |
| tree | 726cf3d5f29a6c66c44e4bd68e7ebed2fd83d059 /kernel/rcutorture.c | |
| parent | e12f0102ac81d660c9f801d0a0e10ccf4537a9de (diff) | |
| parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) | |
| download | olio-linux-3.10-2ca1a615835d9f4990f42102ab1f2ef434e7e89c.tar.xz olio-linux-3.10-2ca1a615835d9f4990f42102ab1f2ef434e7e89c.zip  | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
	arch/x86/kernel/io_apic.c
Diffstat (limited to 'kernel/rcutorture.c')
| -rw-r--r-- | kernel/rcutorture.c | 66 | 
1 files changed, 56 insertions, 10 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 85cb90588a5..b3106552210 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -39,6 +39,7 @@  #include <linux/moduleparam.h>  #include <linux/percpu.h>  #include <linux/notifier.h> +#include <linux/reboot.h>  #include <linux/freezer.h>  #include <linux/cpu.h>  #include <linux/delay.h> @@ -108,7 +109,6 @@ struct rcu_torture {  	int rtort_mbtest;  }; -static int fullstop = 0;	/* stop generating callbacks at test end. */  static LIST_HEAD(rcu_torture_freelist);  static struct rcu_torture *rcu_torture_current = NULL;  static long rcu_torture_current_version = 0; @@ -136,6 +136,30 @@ static int stutter_pause_test = 0;  #endif  int rcutorture_runnable = RCUTORTURE_RUNNABLE_INIT; +#define FULLSTOP_SIGNALED 1	/* Bail due to signal. */ +#define FULLSTOP_CLEANUP  2	/* Orderly shutdown. */ +static int fullstop;		/* stop generating callbacks at test end. */ +DEFINE_MUTEX(fullstop_mutex);	/* protect fullstop transitions and */ +				/*  spawning of kthreads. */ + +/* + * Detect and respond to a signal-based shutdown. + */ +static int +rcutorture_shutdown_notify(struct notifier_block *unused1, +			   unsigned long unused2, void *unused3) +{ +	if (fullstop) +		return NOTIFY_DONE; +	if (signal_pending(current)) { +		mutex_lock(&fullstop_mutex); +		if (!ACCESS_ONCE(fullstop)) +			fullstop = FULLSTOP_SIGNALED; +		mutex_unlock(&fullstop_mutex); +	} +	return NOTIFY_DONE; +} +  /*   * Allocate an element from the rcu_tortures pool.   */ @@ -199,11 +223,12 @@ rcu_random(struct rcu_random_state *rrsp)  static void  rcu_stutter_wait(void)  { -	while (stutter_pause_test || !rcutorture_runnable) +	while ((stutter_pause_test || !rcutorture_runnable) && !fullstop) {  		if (rcutorture_runnable)  			schedule_timeout_interruptible(1);  		else  			schedule_timeout_interruptible(round_jiffies_relative(HZ)); +	}  }  /* @@ -599,7 +624,7 @@ rcu_torture_writer(void *arg)  		rcu_stutter_wait();  	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); -	while (!kthread_should_stop()) +	while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED)  		schedule_timeout_uninterruptible(1);  	return 0;  } @@ -624,7 +649,7 @@ rcu_torture_fakewriter(void *arg)  	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_fakewriter task stopping"); -	while (!kthread_should_stop()) +	while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED)  		schedule_timeout_uninterruptible(1);  	return 0;  } @@ -734,7 +759,7 @@ rcu_torture_reader(void *arg)  	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");  	if (irqreader && cur_ops->irqcapable)  		del_timer_sync(&t); -	while (!kthread_should_stop()) +	while (!kthread_should_stop() && fullstop != FULLSTOP_SIGNALED)  		schedule_timeout_uninterruptible(1);  	return 0;  } @@ -831,7 +856,7 @@ rcu_torture_stats(void *arg)  	do {  		schedule_timeout_interruptible(stat_interval * HZ);  		rcu_torture_stats_print(); -	} while (!kthread_should_stop()); +	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_stats task stopping");  	return 0;  } @@ -899,7 +924,7 @@ rcu_torture_shuffle(void *arg)  	do {  		schedule_timeout_interruptible(shuffle_interval * HZ);  		rcu_torture_shuffle_tasks(); -	} while (!kthread_should_stop()); +	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");  	return 0;  } @@ -914,10 +939,10 @@ rcu_torture_stutter(void *arg)  	do {  		schedule_timeout_interruptible(stutter * HZ);  		stutter_pause_test = 1; -		if (!kthread_should_stop()) +		if (!kthread_should_stop() && !fullstop)  			schedule_timeout_interruptible(stutter * HZ);  		stutter_pause_test = 0; -	} while (!kthread_should_stop()); +	} while (!kthread_should_stop() && !fullstop);  	VERBOSE_PRINTK_STRING("rcu_torture_stutter task stopping");  	return 0;  } @@ -934,12 +959,27 @@ rcu_torture_print_module_parms(char *tag)  		stutter, irqreader);  } +static struct notifier_block rcutorture_nb = { +	.notifier_call = rcutorture_shutdown_notify, +}; +  static void  rcu_torture_cleanup(void)  {  	int i; -	fullstop = 1; +	mutex_lock(&fullstop_mutex); +	if (!fullstop) { +		/* If being signaled, let it happen, then exit. */ +		mutex_unlock(&fullstop_mutex); +		schedule_timeout_interruptible(10 * HZ); +		if (cur_ops->cb_barrier != NULL) +			cur_ops->cb_barrier(); +		return; +	} +	fullstop = FULLSTOP_CLEANUP; +	mutex_unlock(&fullstop_mutex); +	unregister_reboot_notifier(&rcutorture_nb);  	if (stutter_task) {  		VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");  		kthread_stop(stutter_task); @@ -1015,6 +1055,8 @@ rcu_torture_init(void)  		{ &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops,  		  &srcu_ops, &sched_ops, &sched_ops_sync, }; +	mutex_lock(&fullstop_mutex); +  	/* Process args and tell the world that the torturer is on the job. */  	for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {  		cur_ops = torture_ops[i]; @@ -1024,6 +1066,7 @@ rcu_torture_init(void)  	if (i == ARRAY_SIZE(torture_ops)) {  		printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n",  		       torture_type); +		mutex_unlock(&fullstop_mutex);  		return (-EINVAL);  	}  	if (cur_ops->init) @@ -1146,9 +1189,12 @@ rcu_torture_init(void)  			goto unwind;  		}  	} +	register_reboot_notifier(&rcutorture_nb); +	mutex_unlock(&fullstop_mutex);  	return 0;  unwind: +	mutex_unlock(&fullstop_mutex);  	rcu_torture_cleanup();  	return firsterr;  }  |