Linux学习-等待队列
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则在条件满足时被唤醒。
Linux学习等待队 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
