Messages in this thread | | | Date | Thu, 29 Aug 2013 22:08:13 +0800 | From | Libin <> | Subject | Re: [PATCH 00/14] Fix bug about invalid wake up problem |
| |
On 2013/8/29 21:57, Libin wrote: .... > 2)Test: > I have written a test module to trigger the problem by adding some > synchronization condition. I will post it in the form of an attachment soon. > > Test result as follows: > [103135.332683] wakeup_test: create two kernel threads - producer & consumer > [103135.332686] wakeup_test: module loaded successfully > [103135.332692] wakeup_test: kthread producer try to wake up the kthread consumer > [103165.299865] wakeup_test: kthread consumer have waited for 30s, indicating > trigger an invalid wakeup problem! > ....
/* * wakeup_test.c -- Linux kernel invalid wake up problem simulation test module * * Written By: Libin <huawei.libin@huawei.com> * * History * ------- */ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/kthread.h> #include <linux/sched.h> #include <linux/list.h> #include <linux/slab.h> #include <linux/completion.h> #include <linux/timer.h>
#define NAME "wakeup_test" #define WAIT_TIMEOUT HZ*30 static LIST_HEAD(product_list); struct product_struct{ int data; struct list_head list; }; static struct task_struct *producer, *consumer; static struct completion done;
static int producer_thread(void *unused) { struct product_struct *product; product = (struct product_struct *)kmalloc(sizeof (struct product_struct), GFP_KERNEL); product->data = 1;
list_add_tail(&product->list, &product_list);
wake_up_process(consumer); printk(KERN_INFO "%s: kthread producer try to wake up the kthread consumer\n", NAME); complete(&done); /* NOTE: added for problem trigger simulation */
while (!kthread_should_stop()){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); }
printk(KERN_INFO "%s: kthread producer exit\n", NAME); return 0; } static void simulate_preempted(void) { schedule(); }
static void wakeup_wait_timeout(unsigned long unused) { printk(KERN_ERR "%s: kthread consumer have waited for %ds, " "indicating trigger an invalid wakeup problem!\n", NAME, WAIT_TIMEOUT/HZ); } static int consumer_thread(void *unused) { struct timer_list wakeup_wait_timer; setup_timer(&wakeup_wait_timer, wakeup_wait_timeout, (unsigned long)NULL); wait_for_completion(&done); /* NOTE: added for problem trigger simulation */
mod_timer(&wakeup_wait_timer, jiffies + WAIT_TIMEOUT); set_current_state(TASK_INTERRUPTIBLE);
simulate_preempted(); /* NOTE: added for problem trigger simulation */ while (list_empty(&product_list)){ schedule(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING);
del_timer_sync(&wakeup_wait_timer); if (kthread_should_stop()){ goto out; }
if (!list_empty(&product_list)){ printk(KERN_INFO "%s: kthread consumer be woken up successfully, all right!\n", NAME); }
while (!kthread_should_stop()){ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); }
out: printk(KERN_INFO "%s: kthread consumer exit\n", NAME); return 0; }
static int __init wakeup_test_init(void) { producer = kthread_create(producer_thread, NULL, "producer"); consumer = kthread_create(consumer_thread, NULL, "consumer"); init_completion(&done); wake_up_process(producer); wake_up_process(consumer); printk(KERN_INFO "%s: create two kernel threads - producer & consumer\n", NAME); printk(KERN_INFO "%s: module loaded successfully\n", NAME); return 0; } static void __exit wakeup_test_exit(void) { kthread_stop(producer); kthread_stop(consumer); printk(KERN_INFO "%s: module unloaded successfully\n", NAME); } module_init(wakeup_test_init); module_exit(wakeup_test_exit); MODULE_LICENSE("GPL");
| |