Chinaunix首页 | 论坛 | 博客
  • 博客访问: 170207
  • 博文数量: 60
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 638
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-26 10:59
个人简介

喜欢coding,因为那是一件伟大的事情,是将无生命的IC赋予灵魂的过程,让我拥有了和上帝一样的成就感。(w1c2g3@163.com)

文章分类

全部博文(60)

文章存档

2017年(7)

2016年(41)

2015年(1)

2014年(4)

2013年(7)

我的朋友

分类: LINUX

2013-09-21 20:51:04

Four method use it in kernel:


1. wake_up ->  
wait_event(wq, condition) / wait_event_interruptible

2. wake_up ->  
prepare_to_wait
schedule_timeout
finish_wait

3. wake_up ->  
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
set_current_state(TASK_RUNNING);

4. wake_up ->    
poll_wait

---------------------------------------------------------------------------------------------------------------

1.       wait_event(wq, condition)


    a.
        DEFINE_WAIT(__wait); // b
        for (;;) {
            prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);  // c
            if (condition)
                break;
            schedule();
        }
        finish_wait(&wq, &__wait);       // d

    b. 
        wait_queue_t __wait = {
            .private = current,
            .func            = autoremove_wake_function,
            .task_list       = LIST_HEAD_INIT(__wait.task_list),
        }

    c.
        wait->flags &= ~WQ_FLAG_EXCLUSIVE;
        spin_lock_irqsave(&q->lock, flags);
        if (list_empty(&wait->task_list))
        __add_wait_queue(q, wait); -> list_add(&new->task_list, &head->task_list);
        set_current_state(TASK_UNINTERRUPTIBLE);
        spin_unlock_irqrestore(&q->lock, flags);

    d. 
        __set_current_state(TASK_RUNNING);
        if (!list_empty_careful(&wait->task_list)) {
            spin_lock_irqsave(&q->lock, flags);
            list_del_init(&wait->task_list);
            spin_unlock_irqrestore(&q->lock, flags);
        }

2.      same as 1


3.      

        DECLARE_WAITQUEUE(wait, current); // a
        add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait); // b
        set_current_state(TASK_INTERRUPTIBLE);
        schedule();
        remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait); // c
        set_current_state(TASK_RUNNING);

    a.
wait_queue_t wait = {
.private = current,
.func            = default_wake_function,
.task_list       = { NULL, NULL }
}


    b.
wait->flags &= ~WQ_FLAG_EXCLUSIVE;
spin_lock_irqsave(&q->lock, flags);
__add_wait_queue(q, wait); -> list_add(&new->task_list, &head->task_list);
spin_unlock_irqrestore(&q->lock, flags);


    c.
spin_lock_irqsave(&q->lock, flags);
__remove_wait_queue(q, wait); -> list_del(&old->task_list);
spin_unlock_irqrestore(&q->lock, flags);

    the different is wait_queue_t.func:
    1.       autoremove_wake_function -> default_wake_function
    2.       default_wake_function

    wait_queue_t.func call sequence:
    wake_up -> __wake_up -> __wake_up_common -> wait_queue_t.func -> default_wake_function -> try_to_wake_up -> schudelu to workqueue task

4.       poll_wait

    It diferent from others, because the sleep at select system call.

    1. user call select system call:
struct poll_wqueues table;
poll_initwait -> poll_table._qproc = __pollwait
wait = &table.pt;
(*f_op->poll)(file, wait); // 2
poll_schedule_timeout -> to schedule

    2. driver call poll_wait:
poll_wait -> p->_qproc -> __pollwait
wait_queue_t.func = pollwake
add_wait_queue

    3. driver wake_up:
wake_up -> wait_queue_t.func -> pollwake -> __pollwake -> default_wake_function
阅读(1637) | 评论(0) | 转发(0) |
0

上一篇:可变参数宏

下一篇:Linux spinlock

给主人留下些什么吧!~~