微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux学习-等待队列

Linux学习-等待队列

时间:12-01 来源:互联网 点击:

spin_lock_init(&q->

lockdep_set_class(&q->

INIT_LIST_HEAD(&q->

wait->

spin_lock_irqsave(&q->

if (list_empty(&wait->

spin_unlock_irqrestore(&q->

set_mb(current->

list_add(&new->task_list, &head->

wait->

spin_lock_irqsave(&q->

mod_timer(&second_devp->

atomic_inc(&second_devp->

init_timer(&second_devp->

second_devp->

second_devp->

add_timer(&second_devp->

atomic_set(&second_devp->

del_timer(&second_devp->

counter = atomic_read(&second_devp->

dd_wait_queue(q, wait);

spin_unlock_irqrestore(&q->lock, flags);

}

void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)

{

unsigned long flags;

/*修改当前进程的状态为TASK_RUNNING,因此可以被执行*/

__set_current_state(TASK_RUNNING);

/*

* We can check for list emptiness outside the lock

* IFF:

* - we use the "careful" check that verifies both

* the next and prev pointers, so that there cannot

* be any half-pending updates in progress on other

* CPUs that we havent seen yet (and that might

* still change the stack area.

* and

* - all other users take the lock (ie we can only

* have _one_ other CPU that looks at or modifies

* the list).

*/

/*删除链表,实质上就是释放*/

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);

}

}

asmlinkage void __sched schedule(void)

{

struct task_struct *prev, *next;

unsigned long *switch_count;

struct rq *rq;

int cpu;

need_resched:

preempt_disable();

cpu = smp_processor_id();

rq = cpu_rq(cpu);

rcu_note_context_switch(cpu);

prev = rq->curr;

release_kernel_lock(prev);

need_resched_nonpreemptible:

schedule_debug(prev);

if (sched_feat(HRTICK))

hrtick_clear(rq);

raw_spin_lock_irq(&rq->lock);

switch_count = &prev->nivcsw;

if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {

if (unlikely(signal_pending_state(prev->state, prev))) {

prev->state = TASK_RUNNING;

} else {

/*

* If a worker is going to sleep, notify and

* ask workqueue whether it wants to wake up a

* task to maintain concurrency. If so, wake

* up the task.

*/

if (prev->flags & PF_WQ_WORKER) {

struct task_struct *to_wakeup;

to_wakeup = wq_worker_sleeping(prev, cpu);

if (to_wakeup)

try_to_wake_up_local(to_wakeup);

}

deactivate_task(rq, prev, DEQUEUE_SLEEP);

}

switch_count = &prev->nvcsw;

}

pre_schedule(rq, prev);

if (unlikely(!rq->nr_running))

idle_balance(cpu, rq);

put_prev_task(rq, prev);

next = pick_next_task(rq);

clear_tsk_need_resched(prev);

rq->skip_clock_update = 0;

if (likely(prev != next)) {

sched_info_switch(prev, next);

perf_event_task_sched_out(prev, next);

rq->nr_switches++;

rq->curr = next;

++*switch_count;

context_switch(rq, prev, next); /* unlocks the rq */

/*

* The context switch have flipped the stack from under us

* and restored the local variables which were saved when

* this task called schedule() in the past. prev == current

* is still correct, but it can be moved to another cpu/rq.

*/

cpu = smp_processor_id();

rq = cpu_rq(cpu);

} else

raw_spin_unlock_irq(&rq->lock);

post_schedule(rq);

if (unlikely(reacquire_kernel_lock(prev)))

goto need_resched_nonpreemptible;

preempt_enable_no_resched();

if (need_resched())

goto need_resched;

}

根据上面的各个函数,宏定义可知,在wait_event函数中完成了大部分的事情,其中包括等待队列节点的定义,添加,当前进程运行状态的改变,等待条件的满足,跳出等待,函数介绍之前需要完成的任务是修改当前进程的状态为TASK_RUNNING,删除链表,释放一些空间。

其他的函数wait_event_interruptible以及wait_event_killable具有相似的操作,只是对前期修改进程状态存在差别。wait_event_interruptible则不一定只能在条件满足时唤醒,也可以被信号唤醒,而wait_event则在条件满足时被唤醒。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top