const _WorkbufSize … const workbufAlloc … func init() { … } type gcWork … func (w *gcWork) init() { … } // put enqueues a pointer for the garbage collector to trace. // obj must point to the beginning of a heap object or an oblet. // //go:nowritebarrierrec func (w *gcWork) put(obj uintptr) { … } // putFast does a put and reports whether it can be done quickly // otherwise it returns false and the caller needs to call put. // //go:nowritebarrierrec func (w *gcWork) putFast(obj uintptr) bool { … } // putBatch performs a put on every pointer in obj. See put for // constraints on these pointers. // //go:nowritebarrierrec func (w *gcWork) putBatch(obj []uintptr) { … } // tryGet dequeues a pointer for the garbage collector to trace. // // If there are no pointers remaining in this gcWork or in the global // queue, tryGet returns 0. Note that there may still be pointers in // other gcWork instances or other caches. // //go:nowritebarrierrec func (w *gcWork) tryGet() uintptr { … } // tryGetFast dequeues a pointer for the garbage collector to trace // if one is readily available. Otherwise it returns 0 and // the caller is expected to call tryGet(). // //go:nowritebarrierrec func (w *gcWork) tryGetFast() uintptr { … } // dispose returns any cached pointers to the global queue. // The buffers are being put on the full queue so that the // write barriers will not simply reacquire them before the // GC can inspect them. This helps reduce the mutator's // ability to hide pointers during the concurrent mark phase. // //go:nowritebarrierrec func (w *gcWork) dispose() { … } // balance moves some work that's cached in this gcWork back on the // global queue. // //go:nowritebarrierrec func (w *gcWork) balance() { … } // empty reports whether w has no mark work available. // //go:nowritebarrierrec func (w *gcWork) empty() bool { … } type workbufhdr … type workbuf … func (b *workbuf) checknonempty() { … } func (b *workbuf) checkempty() { … } // getempty pops an empty work buffer off the work.empty list, // allocating new buffers if none are available. // //go:nowritebarrier func getempty() *workbuf { … } // putempty puts a workbuf onto the work.empty list. // Upon entry this goroutine owns b. The lfstack.push relinquishes ownership. // //go:nowritebarrier func putempty(b *workbuf) { … } // putfull puts the workbuf on the work.full list for the GC. // putfull accepts partially full buffers so the GC can avoid competing // with the mutators for ownership of partially full buffers. // //go:nowritebarrier func putfull(b *workbuf) { … } // trygetfull tries to get a full or partially empty workbuffer. // If one is not immediately available return nil. // //go:nowritebarrier func trygetfull() *workbuf { … } //go:nowritebarrier func handoff(b *workbuf) *workbuf { … } // prepareFreeWorkbufs moves busy workbuf spans to free list so they // can be freed to the heap. This must only be called when all // workbufs are on the empty list. func prepareFreeWorkbufs() { … } // freeSomeWbufs frees some workbufs back to the heap and returns // true if it should be called again to free more. func freeSomeWbufs(preemptible bool) bool { … }