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 <[email protected]>
 *
 * 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");

Reply via email to