Linux Kernel调度管理之进程唤醒
2017-03-11 23:34
316 查看
进程唤醒:
/* * Notes on Program-Order guarantees on SMP systems. * * MIGRATION * * The basic program-order guarantee on SMP systems is that when a task [t] * migrates, all its activity on its old cpu [c0] happens-before any subsequent * execution on its new cpu [c1]. * * For migration (of runnable tasks) this is provided by the following means: * * A) UNLOCK of the rq(c0)->lock scheduling out task t * B) migration for t is required to synchronize *both* rq(c0)->lock and * rq(c1)->lock (if not at the same time, then in that order). * C) LOCK of the rq(c1)->lock scheduling in task * * Transitivity guarantees that B happens after A and C after B. * Note: we only require RCpc transitivity. * Note: the cpu doing B need not be c0 or c1 * * Example: * * CPU0 CPU1 CPU2 * * LOCK rq(0)->lock * sched-out X * sched-in Y * UNLOCK rq(0)->lock * * LOCK rq(0)->lock // orders against CPU0 * dequeue X * UNLOCK rq(0)->lock * * LOCK rq(1)->lock * enqueue X * UNLOCK rq(1)->lock * * LOCK rq(1)->lock // orders against CPU2 * sched-out Z * sched-in X * UNLOCK rq(1)->lock * * * BLOCKING -- aka. SLEEP + WAKEUP * * For blocking we (obviously) need to provide the same guarantee as for * migration. However the means are completely different as there is no lock * chain to provide order. Instead we do: * * 1) smp_store_release(X->on_cpu, 0) * 2) smp_cond_load_acquire(!X->on_cpu) * * Example: * * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule) * * LOCK rq(0)->lock LOCK X->pi_lock * dequeue X * sched-out X * smp_store_release(X->on_cpu, 0); * * smp_cond_load_acquire(&X->on_cpu, !VAL); * X->state = WAKING * set_task_cpu(X,2) * * LOCK rq(2)->lock * enqueue X * X->state = RUNNING * UNLOCK rq(2)->lock * * LOCK rq(2)->lock // orders against CPU1 * sched-out Z * sched-in X * UNLOCK rq(2)->lock * * UNLOCK X->pi_lock * UNLOCK rq(0)->lock * * * However; for wakeups there is a second guarantee we must provide, namely we * must observe the state that lead to our wakeup. That is, not only must our * task observe its own prior state, it must also observe the stores prior to * its wakeup. * * This means that any means of doing remote wakeups must order the CPU doing * the wakeup against the CPU the task is going to end up running on. This, * however, is already required for the regular Program-Order guarantee above, * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire). * */ /** * try_to_wake_up - wake up a thread * @p: the thread to be awakened * @state: the mask of task states that can be woken * @wake_flags: wake modifier flags (WF_*) * * Put it on the run-queue if it's not already there. The "current" * thread is always on the run-queue (except when the actual * re-schedule is in progress), and as such you're allowed to do * the simpler "current->state = TASK_RUNNING" to mark yourself * runnable without the overhead of this. * * Return: %true if @p was woken up, %false if it was already running. * or @state didn't match @p's state. */ static int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) { unsigned long flags; int cpu, success = 0; /* * If we are going to wake up a thread waiting for CONDITION we * need to ensure that CONDITION=1 done by the caller can not be * reordered with p->state check below. This pairs with mb() in * set_current_state() the waiting thread does. */ smp_mb__before_spinlock(); raw_spin_lock_irqsave(&p->pi_lock, flags); if (!(p->state & state)) goto out; trace_sched_waking(p); success = 1; /* we're going to change ->state */ cpu = task_cpu(p); /* * Ensure we load p->on_rq _after_ p->state, otherwise it would * be possible to, falsely, observe p->on_rq == 0 and get stuck * in smp_cond_load_acquire() below. * * sched_ttwu_pending() try_to_wake_up() * [S] p->on_rq = 1; [L] P->state * UNLOCK rq->lock -----. * \ * +--- RMB * schedule() / * LOCK rq->lock -----' * UNLOCK rq->lock * * [task p] * [S] p->state = UNINTERRUPTIBLE [L] p->on_rq * * Pairs with the UNLOCK+LOCK on rq->lock from the * last wakeup of our task and the schedule that got our task * current. */ smp_rmb(); if (p->on_rq && ttwu_remote(p, wake_flags)) goto stat; #ifdef CONFIG_SMP /* * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be * possible to, falsely, observe p->on_cpu == 0. * * One must be running (->on_cpu == 1) in order to remove oneself * from the runqueue. * * [S] ->on_cpu = 1; [L] ->on_rq * UNLOCK rq->lock * RMB * LOCK rq->lock * [S] ->on_rq = 0; [L] ->on_cpu * * Pairs with the full barrier implied in the UNLOCK+LOCK on rq->lock * from the consecutive calls to schedule(); the first switching to our * task, the second putting it to sleep. */ smp_rmb(); /* * If the owning (remote) cpu is still in the middle of schedule() with * this task as prev, wait until its done referencing the task. * * Pairs with the smp_store_release() in finish_lock_switch(). * * This ensures that tasks getting woken will be fully ordered against * their previous state and preserve Program Order. */ smp_cond_load_acquire(&p->on_cpu, !VAL); p->sched_contributes_to_load = !!task_contributes_to_load(p); p->state = TASK_WAKING; 选核处理 cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags); if (task_cpu(p) != cpu) { wake_flags |= WF_MIGRATED; set_task_cpu(p, cpu); } #endif /* CONFIG_SMP */ ttwu_queue(p, cpu, wake_flags); stat: ttwu_stat(p, cpu, wake_flags); out: raw_spin_unlock_irqrestore(&p->pi_lock, flags); return success; }
相关文章推荐
- Linux Kernel调度管理之唤醒进程并设定唤醒标识
- Linux Kernel调度管理之唤醒指定进程
- Linux CFS调度器之唤醒抢占--Linux进程的管理与调度(三十)
- Linux唤醒抢占----Linux进程的管理与调度(二十三)
- Linux Kernel调度管理之idle进程框架
- Linux Kernel 2.6进程调度的分析(转)
- Linux 技巧:让进程在后台可靠运行的几种方法 用 cron 和 at 调度作业 使用 screen 管理你的远程会话
- 睡眠和唤醒 -- 进程管理
- 调度技术和进程管理整合
- 作业二:进程PCB管理与调度程序
- Linux 进程管理剖析(创建、管理、调度和销毁)
- Linux 进程管理剖析: 创建、管理、调度和销毁进程
- Linux进程调度切换和虚拟空间管理深入分析
- 【进程管理】强制性调度
- 《深入理解linux内核架构》第二章 进程管理和调度
- Linux Kernel(四) 进程调度
- Linux 进程管理剖析—— 创建、管理、调度和销毁
- Linux kernel 进程的睡眠和唤醒
- 基于三级反馈队列调度算法的UNIX进程管理程序模拟
- 进程管理笔记-进程的阻塞、唤醒、挂起、激活