# 2.3.3 O（n）调度器 - 调度时机

聊完了调度的具体逻辑与时间分配之后，我们再来简单聊一下调度时机，即调度这件事情在什么情况下会发生。O(n) 的调度主要发生在如下场景中：

1. 进程主动发起调度，搜索内核代码会发现大量的地方调用了 `schedule()` 方法
2. timer 发现当前进程已经耗尽了自己的时间，触发调度。代码如下：

   ```
   /* file: kernel/timer.c */
   void update_process_times(int user_tick) {
       struct task_struct *p = current;
       int cpu = smp_processor_id(), system = user_tick ^ 1;

       update_one_process(p, user_tick, system, cpu);
       if (p->pid) {
           /* 运行时间耗尽，设置调度标记 */
           if (--p->counter <= 0) {
               p->counter = 0;
               p->need_resched = 1;
           }
           if (p->nice > 0)
               kstat.per_cpu_nice[cpu] += user_tick;
           else
               kstat.per_cpu_user[cpu] += user_tick;
           kstat.per_cpu_system[cpu] += system;
       } else if (local_bh_count(cpu) || local_irq_count(cpu) > 1)
           kstat.per_cpu_system[cpu] += system;
   }
   ```

   在定时器中不会直接触发调度，而是设置任务的调度位： `p->need_resched = 1;`, 系统在下一轮调度中才会做对应的处理。
3. 用户修改进程优先级的时候，这一点很好理解。
4. 系统通过 `fork()` 创建新任务的时候，新任务的产生会导致系统产生调度需求。

还有很多其它的情况会引发调度，这里不再一一列举了。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://s3.shizhz.me/linux-sched/history/o-n-tick.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
