

type g struct {
    stack       stack      // g自己的栈
    m            *m        // 隶属于哪个M
    sched        gobuf     // 保存了g的现场,goroutine切换时通过它来恢复
    atomicstatus uint32    // G的运行状态
    goid         int64
    schedlink    guintptr  // 下一个g, g链表
    preempt      bool      //抢占标记
    lockedm      muintptr  // 锁定的M,g中断恢复指定M执行
    gopc          uintptr  // 创建该goroutine的指令地址
    startpc       uintptr  // goroutine 函数的指令地址
}
| 状态 | 值 | 含义 | 
|---|---|---|
| _Gidle | 0 | 刚刚被分配,还没有进行初始化。 | 
| _Grunnable | 1 | 已经在运行队列中,还没有执行用户代码。 | 
| _Grunning | 2 | 不在运行队列里中,已经可以执行用户代码,此时已经分配了 M 和 P。 | 
| _Gsyscall | 3 | 正在执行系统调用,此时分配了 M。 | 
| _Gwaiting | 4 | 在运行时被阻止,没有执行用户代码,也不在运行队列中,此时它正在某处阻塞等待中。Groutine wait的原因有哪些。参见代码 | 
| _Gmoribund_unused | 5 | 尚未使用,但是在 gdb 中进行了硬编码。 | 
| _Gdead | 6 | 尚未使用,这个状态可能是刚退出或是刚被初始化,此时它并没有执行用户代码,有可能有也有可能没有分配堆栈。 | 
| _Genqueue_unused | 7 | 尚未使用。 | 
| _Gcopystack | 8 | 正在复制堆栈,并没有执行用户代码,也不在运行队列中。 | 
逻辑处理器,P关联了的本地可运行G的队列(也称为LRQ),最多可存放256个G。
type p struct {
    id          int32
    status      uint32     // P的状态
    link        puintptr   // 下一个P, P链表
    m           muintptr   // 拥有这个P的M
    mcache      *mcache  
    // P本地runnable状态的G队列,无锁访问
    runqhead uint32
    runqtail uint32
    runq     [256]guintptr
    
    runnext guintptr       // 一个比runq优先级更高的runnable G
    // 状态为dead的G链表,在获取G时会从这里面获取
    gFree struct {
        gList
        n int32
    }
    gcBgMarkWorker       guintptr // (atomic)
    gcw gcWork
}
| 状态 | 值 | 含义 | 
|---|---|---|
| _Pidle | 0 | 刚刚被分配,还没有进行进行初始化。 | 
| _Prunning | 1 | 当 M 与 P 绑定调用 acquirep 时,P 的状态会改变为 _Prunning。 | 
| _Psyscall | 2 | 正在执行系统调用。 | 
| _Pgcstop | 3 | 暂停运行,此时系统正在进行 GC,直至 GC 结束后才会转变到下一个状态阶段。 | 
| _Pdead | 4 | 废弃,不再使用。 | 
GMP调度流程大致如下: