Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1599288
  • 博文数量: 204
  • 博客积分: 2215
  • 博客等级: 大尉
  • 技术积分: 4427
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-06 08:03
个人简介

气质,源于心灵的自信!

文章存档

2018年(1)

2017年(1)

2016年(1)

2015年(18)

2014年(20)

2013年(30)

2012年(119)

2011年(14)

分类: Android平台

2013-03-15 17:56:55

//用记事本分析的等待队列机制
static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);//定义一个等待队列头

/*定义队列头分析*/
/**************************************************************************************/
struct list_head {
    struct list_head *next, *prev;
};

struct __wait_queue_head {
    spinlock_t lock;
    struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;

/*初始化自旋锁和链表头*/
#define DECLARE_WAIT_QUEUE_HEAD(name) \
    wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)

#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                \
    .lock        = __SPIN_LOCK_UNLOCKED(name.lock),        \
    .task_list    = { &(name).task_list, &(name).task_list } }
/**************************************************************************************/

//hub驱动示例
wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) || kthread_should_stop());

//跟踪调用链
#define wait_event_freezable(wq, condition)    wait_event_interruptible(wq, condition)

//跟踪调用链
#define wait_event_interruptible(wq, condition)                \
({                                    \
    int __ret = 0;                            \
    if (!(condition))                        \//先判断下调节,看是否满足
        __wait_event_interruptible(wq, condition, __ret);    \
    __ret;                                \
})

//继续跟踪调用链
#define __wait_event_interruptible(wq, condition, ret)            \
do {                                    \
    DEFINE_WAIT(__wait);                        \//定义一个等待队列项
                                    \
    for (;;) {                            \
        prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);    \
        if (condition)                        \//再次判断条件是否满足
            break;                        \
        if (!signal_pending(current)) {                \//判断是否有信号要处理?
            schedule();                    \//调度,睡眠
            continue;                    \//唤醒后从该处继续执行?
        }                            \
        ret = -ERESTARTSYS;                    \
        break;                            \
    }                                \
    finish_wait(&wq, &__wait);                    \
} while (0)

//分析DEFINE_WAIT()
typedef struct __wait_queue wait_queue_t;

struct __wait_queue {
    unsigned int flags;
#define WQ_FLAG_EXCLUSIVE    0x01
    void *private;
    wait_queue_func_t func;
    struct list_head task_list;
};

#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function)

#define DEFINE_WAIT_FUNC(name, function)                \
    wait_queue_t name = {                        \//赋值为当前进程的描述符
        .private    = current,                \//唤醒时执行函数
        .func        = function,                \
        .task_list    = LIST_HEAD_INIT((name).task_list),    \//用于链接到等待队列头
    }


void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
{
    unsigned long flags;

    wait->flags &= ~WQ_FLAG_EXCLUSIVE;//把互斥标志清为0
    spin_lock_irqsave(&q->lock, flags);
    if (list_empty(&wait->task_list))
        __add_wait_queue(q, wait);//加入到等待队列
    set_current_state(state);//设置当前进程的状态
    spin_unlock_irqrestore(&q->lock, flags);
}

static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
{
    list_add(&new->task_list, &head->task_list);
}

/*唤醒的处理,以hub唤醒为例*/
static void kick_khubd(struct usb_hub *hub)
{
    unsigned long    flags;

    spin_lock_irqsave(&hub_event_lock, flags);
    if (!hub->disconnected && list_empty(&hub->event_list)) {
        list_add_tail(&hub->event_list, &hub_event_list);//把等待的条件置为真

        /* Suppress autosuspend until khubd runs */
        usb_autopm_get_interface_no_resume(
                to_usb_interface(hub->intfdev));
        wake_up(&khubd_wait);//唤醒等待的进程
    }
    spin_unlock_irqrestore(&hub_event_lock, flags);
}

#define wake_up(x)    __wake_up(x, TASK_NORMAL, 1, NULL)

void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, void *key)
{
    unsigned long flags;

    spin_lock_irqsave(&q->lock, flags);
    __wake_up_common(q, mode, nr_exclusive, 0, key);
    spin_unlock_irqrestore(&q->lock, flags);
}

//唤醒nr_exclusive个排他性进程
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int wake_flags, void *key)
{
    wait_queue_t *curr, *next;

    list_for_each_entry_safe(curr, next, &q->task_list, task_list) {//取出队列的每一个等待项
        unsigned flags = curr->flags;

        //针对普通的先执行function函数,唤醒所有的非互斥等待节点和nr_exclusive个互斥节点
        if (curr->func(curr, mode, wake_flags, key) &&(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
            break;
    }
}

/*导致上面注册*/
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
    int ret = default_wake_function(wait, mode, sync, key);

    if (ret)
        list_del_init(&wait->task_list);//从等待队列中删除
    return ret;
}

int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags, void *key)
{
    return try_to_wake_up(curr->private, mode, wake_flags);//唤醒等待的进程
}

//从睡眠的地方继续调度
void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
{
    unsigned long flags;

    __set_current_state(TASK_RUNNING);//设置该进程的状态为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);
    }
}


//有两个函数分别是增加互斥和不互斥的节点
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
{
    unsigned long flags;

    wait->flags &= ~WQ_FLAG_EXCLUSIVE;
    spin_lock_irqsave(&q->lock, flags);
    __add_wait_queue(q, wait);
    spin_unlock_irqrestore(&q->lock, flags);
}
EXPORT_SYMBOL(add_wait_queue);

void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
{
    unsigned long flags;

    wait->flags |= WQ_FLAG_EXCLUSIVE;
    spin_lock_irqsave(&q->lock, flags);
    __add_wait_queue_tail(q, wait);
    spin_unlock_irqrestore(&q->lock, flags);
}

//因为completion机制是基于等待队列的,所以在此一并分析
struct completion {
    unsigned int done;
    wait_queue_head_t wait;
};

init_completion(&us->scanning_done);
static inline void init_completion(struct completion *x)
{
    x->done = 0;
    init_waitqueue_head(&x->wait);
}

#define init_waitqueue_head(q)                \
    do {                        \
        static struct lock_class_key __key;    \
                            \
        __init_waitqueue_head((q), &__key);    \
    } while (0)

//使用completion
wait_for_completion(&us->scanning_done);

void __sched wait_for_completion(struct completion *x)
{
    wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE, 0);
}

static long __sched wait_for_common(struct completion *x, long timeout, int state, int iowait)
{
    might_sleep();

    spin_lock_irq(&x->wait.lock);
    timeout = do_wait_for_common(x, timeout, state, iowait);
    spin_unlock_irq(&x->wait.lock);
    return timeout;
}

static inline long __sched do_wait_for_common(struct completion *x, long timeout, int state, int iowait)
{
    if (!x->done) {//判断done是否为0
        DECLARE_WAITQUEUE(wait, current);

        __add_wait_queue_tail_exclusive(&x->wait, &wait);
        do {
            if (signal_pending_state(state, current)) {
                timeout = -ERESTARTSYS;
                break;
            }
            __set_current_state(state);//设置当前进程的状态
            spin_unlock_irq(&x->wait.lock);
            if (iowait)
                timeout = io_schedule_timeout(timeout);
            else
                timeout = schedule_timeout(timeout);//调度,进入睡眠
            spin_lock_irq(&x->wait.lock);
        } while (!x->done && timeout);//看条件是否满足或者超时?
        __remove_wait_queue(&x->wait, &wait);//从等待节点从队列中移除
        if (!x->done)//如果不是done引起的唤醒,则返回超时时间
            return timeout;
    }
    x->done--;//重新置为0
    return timeout ?: 1;
}

#define __WAITQUEUE_INITIALIZER(name, tsk) {                \
    .private    = tsk,                        \
    .func        = default_wake_function,            \
    .task_list    = { NULL, NULL } }

#define DECLARE_WAITQUEUE(name, tsk)                    \
    wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)

//加入队列尾部
static inline void __add_wait_queue_tail_exclusive(wait_queue_head_t *q,
                          wait_queue_t *wait)
{
    wait->flags |= WQ_FLAG_EXCLUSIVE;
    __add_wait_queue_tail(q, wait);
}

complete(&us->scanning_done);

void complete(struct completion *x)
{
    unsigned long flags;

    spin_lock_irqsave(&x->wait.lock, flags);
    x->done++;//done++
    __wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL);//唤醒等待队列
    spin_unlock_irqrestore(&x->wait.lock, flags);
}

static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int wake_flags, void *key)
{
    wait_queue_t *curr, *next;

    list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
        unsigned flags = curr->flags;

        if (curr->func(curr, mode, wake_flags, key) &&
                (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
            break;
    }
}

int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
              void *key)
{
    return try_to_wake_up(curr->private, mode, wake_flags);
}
阅读(4034) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~