/* * Taken from Linux Device Drivers, 3rd Edition. * Corbet, Rubini, and Kroah-Hartman. * * Modified by Paul E. McKenney (c) 2008 to test CPU-stall detection. */ #include #include #include #include #include #include MODULE_LICENSE("Dual BSD/GPL"); int stall_secs = 0; module_param(stall_secs, int, 0); MODULE_PARM_DESC(stall_secs, "Number of seconds to stall"); static struct task_struct *kstall_task; static int stall_thread(void *arg) { unsigned long stop_at; printk(KERN_ALERT "stall_thread %ld\n", (long)arg); do { stop_at = get_seconds(); printk(KERN_ALERT "stall_thread at %ld seconds\n", stop_at); stop_at += stall_secs; printk(KERN_ALERT "stall_thread wait until %ld seconds\n", stop_at); while ((long)(get_seconds() - stop_at) < 0) continue; printk(KERN_ALERT "stall_thread ended wait at %ld seconds\n", get_seconds()); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(10 * HZ); printk(KERN_ALERT "stall_thread %ld awakening\n", (long)arg); } while (!kthread_should_stop()); printk(KERN_ALERT "stall_thread %ld exiting\n", (long)arg); return 0; } static int stall_init(void) { int err; printk(KERN_ALERT "Hello, world! stall_secs = %d\n", stall_secs); kstall_task = kthread_run(stall_thread, (void *)(long)stall_secs, "stall_thread"); if (IS_ERR(kstall_task)) { err = PTR_ERR(kstall_task); kstall_task = NULL; return err; } return 0; } static void stall_exit(void) { if (kstall_task != NULL) { kthread_stop(kstall_task); } kstall_task = NULL; printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(stall_init); module_exit(stall_exit);