7.2 Code: Context switching

7.3 Code: Scheduling

  graph TD
    subgraph "scheduler() 执行流程"
        S1["遍历进程表"] --> S2["找到 RUNNABLE 进程"]
        S2 --> S3["`**swtch(&c->context, &p->context)**
        切换到进程`"]
        S3 -.->|"立即切换"| P1
        S4["`**从 swtch 返回**
        c->proc = 0`"] --> S1
    end
    
    subgraph "进程执行与切换"
        P1["⚙️ 进程执行"] --> P2{"何时需要切换?"}
        
        P2 -->|"主动让出CPU"| Y1["yield()"]
        P2 -->|"进程退出"| E1["exit()"] 
        P2 -->|"等待资源"| SL1["sleep()"]
        
        Y1 --> Y2["p->state = RUNNABLE"]
        E1 --> E2["p->state = ZOMBIE"] 
        SL1 --> SL2["p->state = SLEEPING"]
        
        Y2 --> SCHED1["`**sched()**`"]
        E2 --> SCHED2["`**sched()**`"]
        SL2 --> SCHED3["`**sched()**`"]
        
        SCHED1 --> SWTCH1["`**swtch() 切换回scheduler**`"]
        SCHED2 --> SWTCH2["`**swtch() 切换回scheduler**`"]
        SCHED3 --> SWTCH3["`**swtch() 切换回scheduler**`"]
        
        SWTCH1 -.->|"立即切换"| S4
        SWTCH2 -.->|"立即切换"| S4
        SWTCH3 -.->|"立即切换"| S4
        
        %% 只有yield和sleep在被重新选中时才返回
        SCHED1_RETURN["`**sched() 返回**`"] --> Y3["yield() 继续执行<br/>release(&p->lock)"]
        SCHED3_RETURN["`**sched() 返回**`"] --> SL3["sleep() 继续执行<br/>清理工作"]
        
        Y3 --> P1
        SL3 --> P1
    end
    
    %% 关键连接:从scheduler的swtch返回到进程的sched
    S3 -.->|"当scheduler选中此进程"| SCHED1_RETURN
    S3 -.->|"当wakeup()后选中此进程"| SCHED3_RETURN
    
    classDef scheduler fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
    classDef process fill:#f1f8e9,stroke:#388e3c,stroke-width:2px
    classDef sched fill:#fff3e0,stroke:#f57c00,stroke-width:2px
    classDef exit fill:#ffebee,stroke:#d32f2f,stroke-width:2px
    classDef dead fill:#424242,stroke:#000,stroke-width:2px,color:#fff
    
    class S1,S2,S3,S4 scheduler
    class P1,P2,Y1,Y2,Y3,SL1,SL2,SL3 process
    class SCHED1,SCHED2,SCHED3,SCHED1_RETURN,SCHED3_RETURN,SWTCH1,SWTCH2,SWTCH3 sched
    class E1,E2 exit
    class DEAD dead