Go1.25的源碼分析-src/runtime/runtime1.go(GMP)g

1. 主要組成部分

Go語言的GMP調度器基于四個核心數據結構:gmpschedt

1.1 主要常量解讀

1.1.1G 狀態常量

const (_Gidle = iota //剛分配尚未初始化的 G_Grunnable//已在運行隊列上,未執行用戶代碼;棧未被該 G 擁有_Grunning//正在執行用戶代碼;已分配 M 與 P;不在運行隊列上;棧由該 G 擁有_Gsyscall//正在執行系統調用;不執行用戶代碼;不在運行隊列上;已分配 M;棧由該 G 擁有_Gwaiting//在 runtime 內部阻塞(如通道、鎖、定時器等);不執行用戶代碼;不在運行隊列上;通常不擁有棧(特定通道路徑在鎖下可讀寫)_Gmoribund_unused//預留給調試器(gdb)_Gdead//當前未使用的 G(剛退出、在空閑鏈表、或初始化中);不執行用戶代碼;可能有或沒有棧;由處理其回收/復用的 M 暫時擁有_Genqueue_unused_Gcopystack//正在進行棧移動/拷貝;不執行用戶代碼;不在運行隊列上;棧由發起拷貝的一方擁有_Gpreempted//因 suspendG 搶占而自停,類似 _Gwaiting,但尚無人負責將其 ready;需要某個 suspendG 將狀態 CAS 為 _Gwaiting 并負責喚醒//GC 掃描期疊加位,用于標注 goroutine 棧掃描/自掃描期間的狀態,除了_Gscanrunning_Gscan          = 0x1000_Gscanrunnable  = _Gscan + _Grunnable_Gscanrunning   = _Gscan + _Grunning_Gscansyscall   = _Gscan + _Gsyscall_Gscanwaiting   = _Gscan + _Gwaiting_Gscanpreempted = _Gscan + _Gpreempted
)

1.1.2 P的狀態常量

const (// P status_Pidle = iota // 空閑:未用于運行用戶代碼或調度器,通常在空閑隊列_Prunning  // 運行中:被某個 M 持有,用于運行用戶代碼或調度器_Psyscall  // 系統調用關聯:不運行用戶代碼,與系統調用中的 M 有親和性,可被其他 M 竊取_Pgcstop   // GC 停止:STW 期間暫停,由發起 STW 的 M 持有_Pdead     // 已死亡:GOMAXPROCS 變小后不再使用,資源基本被剝離
)

1.2 重要數據結構

1.2.1 gobuf的結構體

// 源碼位置:go/src/runtime/runtime2.go
type gobuf struct {// sp, pc, g的偏移量是已知的(硬編碼在)libmach中//// ctxt在GC方面是不尋常的:它可能是堆分配的funcval,// 所以GC需要跟蹤它,但它需要從匯編中設置和清除,// 在那里很難有寫屏障。然而,ctxt實際上是一個保存的活動寄存器,// 我們只在真實寄存器和gobuf之間交換它。// 因此,我們在棧掃描期間將其視為根,這意味著保存和恢復它的匯編不需要寫屏障// 它仍然被類型化為指針,以便Go的任何其他寫入都獲得寫屏障sp   uintptr        // 棧指針pc   uintptr        // 程序計數器g    guintptr       // goroutine指針(繞過寫屏障)ctxt unsafe.Pointer // 上下文指針,通常指向funcvallr   uintptr        // 鏈接寄存器(用于某些架構)bp   uintptr        // 基指針(用于啟用幀指針的架構)//ret  uintptr     // 1.24.4被刪除 返回值 現在直接通過寄存器或 goroutine 的棧傳遞返回值
}

主要作用:

gobuf是運行時“協程上下文快照”的結構;調度、棧切換、cgo?邊界、棧擴容等一切需要“暫停-繼續”的地方,都會寫/讀它;真正的保存和跳轉由?gosave/gogo?這類匯編原語完成。

1.2.2 G的結構體

type g struct {// Stack parameters.// stack 描述實際棧內存區間: [stack.lo, stack.hi)。// stackguard0 是 Go 棧增長前序中比較的棧指針。//   通常為 stack.lo+StackGuard,但可設為 StackPreempt 以觸發搶占。// stackguard1 是 //go:systemstack 棧增長前序中比較的棧指針。//   在 g0 和 gsignal 棧上為 stack.lo+StackGuard;//   在其他 goroutine 棧上為 ~0,以觸發 morestackc 并導致崩潰。stack       stack   // 偏移量由 runtime/cgo 已知stackguard0 uintptr // 偏移量由 liblink 已知stackguard1 uintptr // 偏移量由 liblink 已知_panic    *_panic // 最內層 panic,偏移量由 liblink 已知_defer    *_defer // 最內層 deferm         *m      // 當前綁定的 M,偏移量由 arm liblink 已知sched     gobuf   // 調度上下文(保存寄存器、PC、SP 等)// 系統調用相關上下文(用于 GC 時保留)syscallsp uintptr // 若 status==Gsyscall,此處存 sched.spsyscallpc uintptr // 若 status==Gsyscall,此處存 sched.pcsyscallbp uintptr // 若 status==Gsyscall,此處存 sched.bp 用于回溯stktopsp  uintptr // 回溯時期望的棧頂 SP// param 是通用指針參數字段,用于在特定場景傳遞值:// 1. channel 操作喚醒阻塞 goroutine 時,指向該次阻塞的 sudog;// 2. gcAssistAlloc1 通知調用者完成 GC 周期(因棧可能已搬遷);// 3. debugCallWrap 傳參給新 goroutine(運行時禁止閉包分配);// 4. panic 恢復返回到某幀時,指向 savedOpenDeferState。param        unsafe.Pointeratomicstatus atomic.Uint32 // 原子狀態stackLock    uint32        // sigprof/scang 鎖;TODO: 合并到 atomicstatusgoid         uint64        // goroutine 唯一 IDschedlink    guintptr      // 全局可運行隊列鏈接waitsince    int64         // 估計阻塞開始時間waitreason   waitReason    // 若 status==Gwaiting,記錄原因// 搶占控制preempt       bool // 搶占信號(等價于 stackguard0 = stackpreempt)preemptStop   bool // 搶占時轉入 _Gpreempted,否則僅去調度preemptShrink bool // 在同步安全點收縮棧// asyncSafePoint 表示 g 在異步安全點停下,此時棧上可能無精確指針信息asyncSafePoint bool// paniconfault 在意外故障地址時 panic 而非直接 crashpaniconfault bool// gcscandone 表示棧掃描已完成,受 status 的 _Gscan 位保護gcscandone bool// throwsplit 禁止在此 g 上進行棧分裂throwsplit bool// activeStackChans 表示未加鎖 channel 引用此棧,收縮時需加鎖保護activeStackChans bool// parkingOnChan 表示即將 park 在 chansend/chanrecv 上,標記棧收縮不安全點parkingOnChan atomic.Bool// inMarkAssist 表示是否在執行 mark assist(執行跟蹤使用)inMarkAssist boolcoroexit     bool // coroswitch_m 的參數// raceignore 忽略競態檢測事件raceignore    int8  // 忽略競態檢測事件nocgocallback bool  // 禁止從 C 回調到 Gotracking      bool  // 是否跟蹤此 G 的調度延遲統計trackingSeq   uint8 // 決定是否跟蹤的序列號trackingStamp int64 // 開始跟蹤的時間戳runnableTime  int64 // 可運行時間累計(運行時清零),僅在跟蹤時使用lockedm         muintptr      // LockThread 時鎖定的 MfipsIndicator   uint8         // FIPS 模式指示syncSafePoint   bool          // 是否停在同步安全點runningCleanups atomic.Bool   // 是否正在運行清理函數sig             uint32        // 信號編號writebuf       byte        // 信號處理寫緩沖區sigcode0        uintptr       // 信號處理相關寄存器sigcode1        uintptrsigpc           uintptrparentGoid uint64          // 創建此 goroutine 的父 goidgopc       uintptr         // 創建此 goroutine 的 go 語句的 PCancestors  *ancestorInfo // debug.tracebackancestors 模式下的祖先鏈startpc    uintptr         // goroutine 函數入口 PCracectx    uintptr         // 競態檢測上下文// waiting 指向當前 g 等待的 sudog 鏈表(elem 有效)waiting *sudogcgoCtxtuintptr      // cgo 回溯上下文labels  unsafe.Pointer // 性能分析器標簽timer   *timer         // time.Sleep 緩存的定時器sleepWhen int64        // 睡眠到期時間selectDone atomic.Uint32 // 是否參與 select 及是否贏得喚醒競賽// goroutineProfiled 表示當前 goroutine 棧在 profile 中的狀態goroutineProfiled goroutineProfileStateHoldercoroarg *coro             // 協程切換參數bubble  *synctestBubble   // 同步測試氣泡// Per-G 追蹤狀態trace gTraceState// GC 相關狀態// gcAssistBytes 為 GC 輔助信用額度(字節數)://   >0 表示有可用額度;//   <0 表示需完成掃描工作。// 通過 assist ratio 轉換為掃描工作債務。gcAssistBytes int64// valgrindStackID 在 valgrind build tag 下用于跟蹤棧內存,否則未使用valgrindStackID uintptr
}
G的狀態轉換圖

1.2.3 M的結構體

type m struct {g0    *g// g0: 持有調度堆棧的goroutinemorebuf    gobuf// morebuf: 傳遞給morestack的gobuf參數divmod    uint32// divmod: ARM平臺的除法/模運算分母(已知liblink,詳見cmd/internal/obj/arm/obj5.go)// 調試器未知的字段procid uint64 // 供調試器使用,但偏移量未硬編碼gsignal *g // 信號處理專用的goroutinegoSigStack gsignalStack // Go分配的信號處理堆棧sigmask sigset // 保存的信號掩碼存儲tls [tlsSlots]uintptr // 線程局部存儲(用于x86外部寄存器)mstartfn func() // M啟動函數curg *g // 當前運行的goroutinecaughtsig guintptr // 在致命信號期間運行的goroutinep puintptr // 附加的P(用于執行Go代碼,未執行Go代碼時為nil)nextp puintptr // 下一個Poldp puintptr // 執行系統調用前附加的Pid int64 // M的唯一IDmallocing int32 // 是否在分配內存throwing throwType // 當前拋出類型preemptoff string // 若非空,強制保持curg在此M上運行locks int32 // 保持鎖定的次數dying int32 // 死亡狀態標志profilehz int32 // 性能分析頻率spinning bool // M處于空閑狀態并主動尋找工作blocked bool // M被note阻塞newSigstack bool // minit在C線程中調用了sigaltstackprintlock int8 // 打印鎖incgo bool // 是否在執行cgo調用isextra bool // 是否為備用MisExtraInC bool // 是否為在C代碼中運行的備用MisExtraInSig bool // 是否為在信號處理中運行的備用MfreeWait atomic.Uint32 // 是否可以安全釋放g0并刪除M(freeMRef/freeMStack/freeMWait之一)needextram bool // 是否需要備用Mg0StackAccurate bool // g0堆棧是否具有準確邊界traceback uint8 // 回溯類型allpSnapshot []*p // 附加P時的allp快照(findRunnable釋放P后使用,否則為nil)ncgocall uint64 // 總cgo調用次數ncgo int32 // 當前進行的cgo調用次數cgoCallersUse atomic.Uint32 // 若非零,cgoCallers臨時可用cgoCallers *cgoCallers // cgo調用崩潰時的回溯信息park note // 用于阻塞M的notealllink *m // 在allm鏈表中的鏈接schedlink muintptr // 調度鏈表鏈接lockedg guintptr // 鎖定的goroutinecreatestack [32]uintptr // 創建此線程的堆棧(用于StackRecord.Stack0,必須對齊)lockedExt uint32 // 外部LockOSThread狀態追蹤lockedInt uint32 // 內部lockOSThread狀態追蹤mWaitList mWaitList // 運行時鎖等待者列表mLockProfile mLockProfile // 與runtime.lock爭用相關的字段profStackuintptr // 用于內存/阻塞/互斥鎖堆棧追蹤// wait*字段用于從gopark傳遞參數到park_m(因為低級NOSPLIT函數沒有堆棧)waitunlockf func(*g, unsafe.Pointer) bool // 解鎖函數waitlock unsafe.Pointer // 等待的鎖waitTraceSkip int // 跟蹤跳過次數waitTraceBlockReason traceBlockReason // 跟蹤阻塞原因syscalltick uint32 // 系統調用計數freelink *m // 在sched.freem鏈表中的鏈接trace mTraceState // 跟蹤狀態// 這些字段太大,不能放在低級NOSPLIT函數的堆棧中libcall libcall // 系統調用參數libcallpc uintptr // 用于CPU性能分析libcallsp uintptr // 調用堆棧指針libcallg guintptr // 當前goroutinewinsyscall winlibcall // Windows平臺的系統調用參數vdsoSP uintptr // VDSO調用中的堆棧指針(未調用時為0)vdsoPC uintptr // VDSO調用中的程序計數器// preemptGen: 記錄已完成的搶占信號次數(用于檢測搶占失敗)preemptGen atomic.Uint32// 該M是否有待處理的搶占信號signalPending atomic.Uint32// pcvalue查找緩存pcvalueCache pcvalueCachedlogPerM // 每M的日志記錄mOS // 操作系統相關字段chacha8 chacha8rand.State // ChaCha8隨機數生成器狀態cheaprand uint64 // 快速隨機數生成器// 該M持有的最多10把鎖(由鎖排序代碼維護)locksHeldLen int // 持有鎖數量locksHeld [10]heldLockInfo // 持有鎖信息數組
}
M的內存大小
const mRedZoneSize = (16 << 3) * asanenabledBit // redZoneSize(2048)type mPadded struct {m// Size the runtime.m structure so it fits in the 2048-byte size class, and// not in the next-smallest (1792-byte) size class. That leaves the 11 low// bits of muintptr values available for flags, as required by// lock_spinbit.go._ [(1 - goarch.IsWasm) * (2048 - mallocHeaderSize - mRedZoneSize - unsafe.Sizeof(m{}))]byte
}

mRedZoneSize是在啟用Ascan時,作為棧溢出檢測的區域,大小為128字節。也用于棧擴展部分,當stackstackguard0進入red zone,會觸發gorwStack擴展棧。

mPadded?的設計目的是?通過填充字段?確保?m?結構體大小為 2048 字節,從而在?muintptr?中?保留低 11 位用于標志位。該設計在非 Wasm 平臺生效,Wasm 平臺因內存模型差異跳過填充。核心優化點在于?標志位復用?和?內存對齊,避免額外內存分配,提升并發性能。

1.2.3 P的結構體

type p struct {id          int32 // 進程IDstatus      uint32 // 狀態(如 pidle/prunning/...)link        puintptr // 鏈表指針schedtick   uint32 // 每次調度調用時遞增的計數器syscalltick uint32 // 每次系統調用時遞增的計數器sysmontick  sysmontick // sysmon 上次觀察到的計數器m           muintptr // 關聯的 M(空閑時為 nil)mcache      *mcache // 本地 M 的緩存pcache      pageCache // 頁緩存raceprocctx uintptr // 競態檢測上下文deferpool    []*_defer // 可用 defer 結構體池(見 panic.go)deferpoolbuf [32]*_defer // defer 結構體緩沖區// 緩存的 goroutine ID,減少對 runtime·sched.goidgen 的訪問goidcache    uint64 // goroutine ID 緩存起始值goidcacheend uint64 // 緩存的 goroutine ID 終止值// 可運行的 goroutine 隊列(無鎖訪問)runqhead uint32 // 隊列頭部索引runqtail uint32 // 隊列尾部索引runq     [256]guintptr // 隊列數組// runnext 存儲當前 G 準備運行的下一個 G(若時間片未用盡)。// 它繼承當前時間片的剩余時間。若一組 goroutine 處于通信和等待模式中,// 此字段可將該組作為一個單元調度,避免將 goroutine 添加到隊列尾部導致的調度延遲。// 注意:其他 P 可以原子地將此字段置為零,但只有當前 P 可以原子地設置為有效 G。runnext guintptr// 可用的 G(狀態 == Gdead)gFree gList // 可回收的 G 列表sudogcache []*sudog // sudog 緩存sudogbuf   [128]*sudog // sudog 緩沖區// 從堆中緩存的 mspan 對象mspancache struct {// 顯式長度字段,避免在分配路徑中使用寫屏障時的復雜性len int // 當前緩存長度buf [128]*mspan // 緩存數組}// 緩存的單個 pinner 對象,減少重復創建 pinner 的分配開銷pinnerCache *pinnertrace pTraceState // 跟蹤狀態palloc persistentAlloc // 每個 P 的持久化分配器// 每個 P 的 GC 狀態gcAssistTime         int64 // GC 輔助分配所花費的時間(納秒)gcFractionalMarkTime int64 // 分數標記工作者所花費的時間(納秒,原子更新)// limiterEvent 跟蹤 GC CPU 限制器的事件limiterEvent limiterEvent// gcMarkWorkerMode 指示下一個標記工作者應運行的模式// 用于與通過 gcController.findRunnableGCWorker 選擇的工作者 goroutine 通信// 調度其他 goroutine 時,此字段必須設置為 gcMarkWorkerNotWorkergcMarkWorkerMode gcMarkWorkerMode// gcMarkWorkerStartTime 是最近標記工作者的啟動時間(納秒)gcMarkWorkerStartTime int64// gcw 是此 P 的 GC 工作緩沖區緩存// 緩沖區由寫屏障填充,由突變器輔助消耗,在特定 GC 狀態轉換時釋放gcw gcWork// wbBuf 是此 P 的 GC 寫屏障緩沖區// TODO: 考慮將其緩存在運行的 G 中wbBuf wbBufrunSafePointFn uint32 // 若為 1,調度器在下一個安全點運行 sched.safePointFn// statsSeq 是指示此 P 是否正在寫入統計信息的計數器// 偶數表示未寫入,奇數表示正在寫入statsSeq atomic.Uint32// 定時器堆timers timers// 清理塊cleanups       *cleanupBlockcleanupsQueued uint64 // 此 P 隊列的清理塊數量(單調遞增)// maxStackScanDelta 累積活動 goroutine 的棧空間占用(即可能需要掃描的棧大小)// 當達到 maxStackScanSlack 或 -maxStackScanSlack 時,刷新到 gcController.maxStackScanmaxStackScanDelta int64// GC 時間統計// 與 maxStackScan 不同,該字段累積 GC 時實際觀察到的棧使用量(hi - sp)// 而非瞬時的總棧大小(hi - lo)scannedStackSize uint64 // 此 P 掃描的 goroutine 棧大小scannedStacks    uint64 // 此 P 掃描的 goroutine 數量// preempt 標記此 P 需盡快進入調度器(無論當前 G 在運行什么)preempt bool// gcStopTime 是此 P 最近進入 _Pgcstop 的時間戳(納秒)gcStopTime int64
}

1.2.4 schedt結構體

type schedt struct {// goidgen 是全局唯一的 goroutine ID 生成器// lastpoll 記錄上次網絡輪詢的時間(若當前正在輪詢則為 0)// pollUntil 記錄當前輪詢的睡眠截止時間// pollingNet 表示是否有 P 正在執行非阻塞的網絡輪詢goidgen    atomic.Uint64lastpoll   atomic.Int64 // 上次網絡輪詢時間pollUntil  atomic.Int64 // 當前輪詢的睡眠截止時間pollingNet atomic.Int32 // 1 表示有 P 正在執行非阻塞輪詢// lock 是全局調度器的互斥鎖lock mutex// 增加 nmidle、nmidlelocked、nmsys 或 nmfreed 時,必須調用 checkdead()// midle 是等待工作的空閑 M 鏈表// nmidle 是空閑 M 的數量// nmidlelocked 是被鎖定的空閑 M 數量// mnext 是已創建的 M 總數和下一個 M 的 ID// maxmcount 是允許的最大 M 數量(超過則終止)// nmsys 是系統 M 的數量(不計入死鎖檢測)// nmfreed 是累計釋放的 M 數量midle        muintptr // 空閑 M 鏈表nmidle       int32    // 空閑 M 數量nmidlelocked int32    // 被鎖定的空閑 M 數量mnext        int64    // 已創建的 M 數量和下一個 M IDmaxmcount    int32    // 最大允許的 M 數量nmsys        int32    // 系統 M 數量nmfreed      int64    // 累計釋放的 M 數量// ngsys 是系統 goroutine 的數量ngsys atomic.Int32// pidle 是空閑 P 鏈表// npidle 是空閑 P 數量(原子更新)// nmspinning 是自旋的 M 數量(參考 proc.go 中的“Worker thread parking/unparking”注釋)// needspinning 是是否需要自旋的標志(參考 proc.go 中的“Delicate dance”注釋,布爾值,修改時需持有 sched.lock)pidle        puintptr // 空閑 P 鏈表npidle       atomic.Int32nmspinning   atomic.Int32needspinning atomic.Uint32// 全局可運行隊列runq gQueue// disable 控制調度器的禁用(通過 schedEnableUser 控制)// disable.user 表示是否禁用用戶 goroutine 的調度// disable.runnable 是待運行的 G 隊列disable struct {user     boolrunnable gQueue // 待運行的 G 隊列}// gFree 是全局死亡 G 的緩存gFree struct {lock    mutexstack   gList // 帶棧的 G 列表noStack gList // 無棧的 G 列表}// sudoglock 保護 sudogcache 的互斥鎖// sudogcache 是全局 sudog 緩存sudoglock  mutexsudogcache *sudog// deferlock 保護 deferpool 的互斥鎖// deferpool 是全局 defer 結構體緩存deferlock mutexdeferpool *_defer// freem 是 m.exited 被設置后等待釋放的 M 鏈表(通過 m.freelink 連接)freem *m// gcwaiting 表示 GC 是否在等待運行// stopwait 和 stopnote 用于 stop-the-world 等待// sysmonwait 表示 sysmon 是否在等待// sysmonnote 是 sysmon 的等待信號gcwaiting  atomic.Bool // GC 等待運行標志stopwait   int32stopnote   notesysmonwait atomic.Boolsysmonnote note// safePointFn 是在下一個 GC 安全點需要調用的函數(若 p.runSafePointFn 被設置)// safePointWait 是等待計數// safePointNote 是安全點的等待信號safePointFn   func(*p)safePointWait int32safePointNote note// profilehz 是 CPU 采樣率profilehz int32// procresizetime 是上次調整 gomaxprocs 的時間(納秒)// totaltime 是從 procresizetime 開始的累計運行時間procresizetime int64 // 上次調整 gomaxprocs 的時間totaltime      int64 // 累計運行時間// customGOMAXPROCS 表示 GOMAXPROCS 是否被手動設置(環境變量或 runtime.GOMAXPROCS)customGOMAXPROCS bool// sysmonlock 是保護 sysmon 與運行時交互的互斥鎖// 持有該鎖可阻斷 sysmon 對運行時的操作sysmonlock mutex// timeToRun 是調度延遲分布(定義為 G 在 _Grunnable 狀態到 _Grunning 狀態的總時間)timeToRun timeHistogram// idleTime 是所有 P 的空閑時間總和(每次 GC 周期重置)idleTime atomic.Int64// totalMutexWaitTime 是 goroutine 在 _Gwaiting 狀態等待 runtime 內部鎖的總時間totalMutexWaitTime atomic.Int64// stwStoppingTimeGC/Other 是 stop-the-world 停止延遲分布(定義為 stopTheWorldWithSema 到所有 P 停止的時間)// stwStoppingTimeGC 覆蓋所有 GC 相關的 STW,stwStoppingTimeOther 覆蓋其他 STWstwStoppingTimeGC    timeHistogramstwStoppingTimeOther timeHistogram// stwTotalTimeGC/Other 是 stop-the-world 總延遲分布(定義為 stopTheWorldWithSema 到 startTheWorldWithSema 的總時間)// stwTotalTimeGC 覆蓋所有 GC 相關的 STW,stwTotalTimeOther 覆蓋其他 STWstwTotalTimeGC    timeHistogramstwTotalTimeOther timeHistogram// totalRuntimeLockWaitTime(加上每個 M 的 lockWaitTime)是 goroutine 在 _Grunnable 狀態且持有 M 但等待 runtime 內部鎖的總時間// 該字段存儲已退出 M 的累計時間totalRuntimeLockWaitTime atomic.Int64
}

剩余結構體作用

type libcall struct {fn uintptrn uintptr // 參數個數args uintptr // 參數列表r1 uintptr // 返回值1r2 uintptr // 返回值2err uintptr // 錯誤號
}// Stack 描述了 Go 運行時的執行棧。
// 棧的邊界恰好是 [lo, hi),
// 兩端沒有任何隱式的數據結構。
type stack struct {lo uintptrhi uintptr
}// heldLockInfo 提供已持有的鎖及該鎖等級的信息
type heldLockInfo struct {lockAddr uintptrrank lockRank
}

其中libcall在匯編/系統層面,runtime 會構造一個 libcall,把要調用的函數地址、參數列表打包到它的各字段里,然后由通用的調用入口(如 asm/syscall 實現)讀取這些字段并真正發起調用,返回值和 errno 也寫回到這里。

每個 G 對象里有一個 stack 字段,用 lo、hi 精確標識它的棧內存區域(lo ≤ sp < hi)。GC、棧擴展/收縮、調度等子系統都依賴這兩個邊界來判斷棧是否需要 grow/shrink,以及掃描活躍幀時的地址合法性

Go 運行時為了在調試模式下檢測可能的死鎖或鎖順序反轉,會給每把鎖分配一個 rank。每當 G 獲取一把鎖,就往它的 heldLocks 列表里插入一個 heldLockInfo。釋放時再刪掉。這樣就能在運行時斷言“只允許按 rank 升序獲取鎖”,及時報告不安全的鎖順序。

參考文獻

https://juejin.cn/post/7519334402688368667#heading-11

https://zhuanlan.zhihu.com/p/67852800

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96354.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96354.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96354.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用jwt+redis實現單點登錄

首先理一下登錄流程 前端登錄—>賬號密碼驗證—>成功返回token—>后續請求攜帶token---->用戶異地登錄---->本地用戶token不能用&#xff0c;不能再訪問需要攜帶token的網頁 jwt工具類 package com.nageoffer.shortlink.admin.util;import cn.hutool.core.util.…

Trae配置rules與MCP

這個文章不錯&#xff0c;不過如果只是看&#xff0c;還感受不到作者的震撼&#xff0c;所以我自己實操了一下&#xff0c;深受震動&#xff0c;也希望看到這篇文章的人也自己實操一下。 與Cursor結對編程的四個月&#xff0c;我大徹大悟了&#xff01; 學到了什么 無論是熟悉…

對抗攻擊與防御:如何保護視覺模型安全?

對抗攻擊與防御:如何保護視覺模型安全? 前言 一、對抗攻擊的基本原理 二、對抗攻擊的主要類型 2.1 白盒攻擊 2.2 黑盒攻擊 三、對抗攻擊的常見形式 3.1 定向攻擊 3.2 非定向攻擊 四、對抗防御的核心思路 五、常見的對抗防御方法 5.1 對抗訓練 5.2 輸入預處理 5.3 防御蒸餾 六…

區塊鏈開發:Solidity 智能合約安全審計要點

本文聚焦區塊鏈開發中 Solidity 智能合約的安全審計要點。首先概述智能合約安全審計的重要性&#xff0c;接著詳細介紹常見的安全漏洞&#xff0c;如重入攻擊、整數溢出與下溢等&#xff0c;以及對應的審計方法。還闡述了審計的具體流程&#xff0c;包括自動化工具檢測、手動代…

C++ 新手第一個練手小游戲:井字棋

1. 引言 介于身邊有特別多沒有學習過編程&#xff0c;或者有一定C語言、python或是Java基礎的但是沒有接觸過C的新手朋友&#xff0c;我想可以通過一個很簡單的小項目作為挑戰&#xff0c;幫助大家入門C。 今天&#xff0c;我們將挑戰一個對新手來說稍微復雜一點&#xff0c;…

透射TEM 新手入門:快速掌握核心技能

目錄 簡介? 一、TEM 基本知識 1. 核心原理&#xff08;理解圖像本質&#xff09;? 2. 關鍵結構與成像模式&#xff08;對應圖像類型&#xff09;? 二、TEM 數據處理 1. 預處理&#xff08;通用步驟&#xff09;? 2. 衍射花樣&#xff08;SAED&#xff09;處理&#x…

day075-MySQL數據庫服務安裝部署與基礎服務管理命令

文章目錄0. 老男孩思想-老男孩名言警句1. 數據庫服務安裝部署1.1 下載安裝包1.2 系統環境準備1.2.1 關閉防火墻1.2.2 關閉selinux1.2.3 安裝依賴軟件1.2.4 卸載沖突軟件1.3 安裝程序1.3.1 上傳軟件包1.3.2 配置環境變量1.3.3 創建數據庫存儲數據目錄1.3.4 創建數據庫程序管理用…

Qt二維碼生成器項目開發教程 - 從零開始構建專業級QR碼生成工具

Qt二維碼生成器項目開發教程 - 從零開始構建專業級QR碼生成工具 項目概述 本項目是一個基于Qt框架開發的專業級二維碼生成器&#xff0c;集成了開源的qrencode庫&#xff0c;提供完整的QR碼生成、預覽、保存和分享功能。項目采用C語言開發&#xff0c;使用Qt的信號槽機制實現…

LLaVA-3D,Video-3D LLM,VG-LLM,SPAR論文解讀

目錄 一、LLaVA-3D 1、概述 2、方法 3、訓練過程 4、實驗 二、Video-3D LLM 1、概述 2、方法 3、訓練過程 4、實驗 三、SPAR 1、概述 2、方法 4、實驗 四、VG-LLM 1、概述 2、方法 3、方法 4、實驗 一、LLaVA-3D 1、概述 空間關系不足&#xff1a;傳…

Spring兩個核心IoCDI(二)

DI&#xff08;依賴注入&#xff09;就是從IoC容器中獲取對象并賦值給某個屬性&#xff0c;這就是依賴注入的過程。 關于依賴注入有3種方式&#xff1a; 1、屬性注入 2、構造方法注入 3、setter注入 目錄 1、屬性注入 2、 構造方法注入 3、Setter方法注入 4、3種注入方式優…

廣東省省考備考(第八十三天8.21)——言語、判斷推理(強化訓練)

言語理解與表達 錯題解析 文段開篇介紹足夠的執法權限對于基層治理高效運行的重要性&#xff0c;接著從兩方面進行論證&#xff0c;介紹權限不足和權限過度下放對基層治理的負面影響&#xff0c;最后通過“因此”進行總結&#xff0c;強調一方面要完善執法目錄動態調整機制和制…

字符串與算法題詳解:最長回文子串、IP 地址轉換、字符串排序、蛇形矩陣與字符串加密

字符串與算法題詳解&#xff1a;最長回文子串、IP 地址轉換、字符串排序、蛇形矩陣與字符串加密 前言 在編程題訓練中&#xff0c;字符串相關的題目非常常見。本文將結合幾個典型的例題&#xff0c;詳細解析它們的解題思路和實現方式&#xff0c;幫助初學者循序漸進地掌握常用技…

從協同設計到綠色制造:工業云渲染的價值閉環

在智能制造、建筑工程、能源電力、船舶海工等工業場景中&#xff0c;3D可視化已從傳統的桌面端逐步向Web端遷移&#xff0c;Web 3D憑借其跨平臺、輕量化、實時交互等特性&#xff0c;已成為企業構建數字孿生、實現遠程協作、推動云端交付的重要工具。這場技術變革不僅改變了工業…

算法第五十一天:圖論part02(第十一章)

1.島嶼數量 99. 島嶼數量 &#x1f31f; 思路總結 — DFS 版 1?? 問題本質 給定一個二維矩陣 grid&#xff0c;1 表示陸地&#xff0c;0 表示水 統計島嶼數量&#xff0c;每個島嶼由上下左右相鄰的陸地組成 本質是 在二維網格中找連通塊 的問題。 2?? 核心思路 遍歷矩陣…

杰里708n tws api 簡介

/** 通過搜索碼搜索tws設備*/int tws_api_search_sibling_by_code();/**打開可發現, 可連接&#xff0c;可被手機和tws搜索到*/int tws_api_wait_pair_by_code(u16 code, const char *name, int timeout_ms);int tws_api_wait_pair_by_ble(u16 code, const char *name, int tim…

高調光比 LED 恒流驅動芯片方案詳解AP5165B:36V/1A

AP5165B 是深圳市世微半導體有限公司推出的一款高性能、連續電流模式的降壓型&#xff08;Buck&#xff09;LED 恒流驅動芯片。該芯片適用于輸入電壓高于 LED 電壓的應用場景&#xff0c;可驅動單顆或多顆串聯的 LED&#xff0c;輸出電流最高可達 1A&#xff0c;廣泛用于非隔離…

【從零構建企業級線程池管理系統:Python并發編程實戰指南】

從零構建企業級線程池管理系統&#xff1a;Python并發編程實戰指南 技術博客 | 深入探索Python并發編程、Web開發與現代軟件架構設計的完整實踐 &#x1f680; 項目背景 在當今高并發的互聯網時代&#xff0c;線程池作為并發編程的核心組件&#xff0c;其管理和監控能力直接影…

飛牛系統總是死機,安裝個工具查看一下日志

崩潰轉儲 (kernel crash dump)如果你懷疑是內核 panic&#xff0c;可以開啟 kdump 或 kernel crash dump。 安裝&#xff1a;sudo apt install kdump-tools # Debian/Ubuntu sudo systemctl enable kdump 下次死機時&#xff0c;系統會把內存 dump 到 /var/crash 里。sudo syst…

2025年AI Agent技術深度解析:原理、應用與未來趨勢

一、引言隨著人工智能技術的飛速發展&#xff0c;AI Agent&#xff08;智能體&#xff09;作為人工智能領域的重要分支&#xff0c;正逐漸成為推動各行業智能化轉型的關鍵力量。AI Agent具備自主感知、決策和執行能力&#xff0c;能夠在復雜環境中完成特定任務&#xff0c;為人…

linux內核 - 內存分配機制介紹

在linux內核中&#xff0c;下面這張圖說明了系統中存在一個可以滿足各種內存請求的分配機制。根據你需要內存的用途&#xff0c;你可以選擇最接近你目標的分配方式。最底層、最基礎的分配器是 頁分配器&#xff08;page allocator&#xff09;&#xff0c;它以頁為單位分配內存…