返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

4.6.3 释放

发布于 2024-10-12 19:16:06 字数 1765 浏览 0 评论 0 收藏 0

将 dead G 放回复用链表时,会尝试释放栈内存。

如栈没有扩容,保留。

另,copystack、shrinkstack,以及垃圾回收也会释放。

// proc.go

// Put on gfree list.

func gfput(_p_ *p, gp *g) {
    stksize := gp.stack.hi - gp.stack.lo
    if stksize != _FixedStack {
        // non-standard stack size - free it.
        stackfree(gp.stack)
        
        gp.stack.lo = 0
        gp.stack.hi = 0
        gp.stackguard0 = 0
    }
}

释放同样区分大小块。

// stack.go

// stackfree frees an n byte stack allocation at stk.

func stackfree(stk stack) {
    
    v := unsafe.Pointer(stk.lo)
    n := stk.hi - stk.lo
    
    if n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
   
        // 计算等级。
        order := uint8(0)
        n2 := n
        for n2 > _FixedStack {
            order++
            n2 >>= 1
        }
        
        if stackNoCache != 0 || gp.m.p == 0 || gp.m.preemptoff != "" {
            stackpoolfree(x, order)
        } else {
            c := gp.m.p.ptr().mcache
            
            // 如果该等级缓存太多(总尺寸超出),则归还部分给全局。
            if c.stackcache[order].size >= _StackCacheSize {
                stackcacherelease(c, order)
            }
            
            // 添加到等级链表。
            x.ptr().next = c.stackcache[order].list
            c.stackcache[order].list = x
            c.stackcache[order].size += n
        }
    } else {
        
        // 大块,归还给 heap,或存入全局缓存。
        
        s := spanOfUnchecked(uintptr(v))
        if gcphase == _GCoff {                                // sweeping!
            mheap_.freeManual(s, &memstats.stacks_inuse)
        } else {
            log2npage := stacklog2(s.npages)
            stackLarge.free[log2npage].insert(s)
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文