本文介绍: sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射。

sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射

type sudog struct {
  // 指向的goroutine
	g *g

  // 指向前后sudog的指针
	next *sudog
	prev *sudog
  
  // 指向数据
	elem unsafe.Pointer // data element (may point to stack)

	// The following fields are never accessed concurrently.
	// For channels, waitlink is only accessed by g.
	// For semaphores, all fields (including the ones above)
	// are only accessed when holding a semaRoot lock.

  // 获取时间
	acquiretime int64
  // 释放时间
	releasetime int64
  // 作为队列元素的标识
	ticket      uint32

	// isSelect indicates g is participating in a select, so
	// g.selectDone must be CAS'd to win the wake-up race.
	isSelect bool

	// success indicates whether communication over channel c
	// succeeded. It is true if the goroutine was awoken because a
	// value was delivered over channel c, and false if awoken
	// because c was closed.
	success bool

	parent   *sudog // semaRoot binary tree
	waitlink *sudog // g.waiting list or semaRoot
	waittail *sudog // semaRoot
	c        *hchan // channel
}

acquireSudog()

func acquireSudog() *sudog {
  // 增加m的锁,防止垃圾回收在此期间被调用
	mp := acquirem()
	pp := mp.p.ptr()
  
 	// 如果本地缓存为空
	if len(pp.sudogcache) == 0 {
		lock(&sched.sudoglock)
    // 从中心缓存迁移至多一半本地缓存容量的缓存项到本地缓存
		for len(pp.sudogcache) < cap(pp.sudogcache)/2 && sched.sudogcache != nil {
			s := sched.sudogcache
			sched.sudogcache = s.next
			s.next = nil
			pp.sudogcache = append(pp.sudogcache, s)
		}
		unlock(&sched.sudoglock)

    // 若本地缓存仍为空,则新建缓存项
		if len(pp.sudogcache) == 0 {
			pp.sudogcache = append(pp.sudogcache, new(sudog))
		}
	}
  
  // 从本地缓存中取出最后一个缓存项返回
	n := len(pp.sudogcache)
	s := pp.sudogcache[n-1]
	pp.sudogcache[n-1] = nil
	pp.sudogcache = pp.sudogcache[:n-1]
	if s.elem != nil {
		throw("acquireSudog: found s.elem != nil in cache")
	}
  // 减少m的锁,允许垃圾回收调用
	releasem(mp)
	return s
}

releaseSudog()

func releaseSudog(s *sudog) {
  // 判断sudog各项数据、状态是否正确
	if s.elem != nil {
		throw("runtime: sudog with non-nil elem")
	}
	if s.isSelect {
		throw("runtime: sudog with non-false isSelect")
	}
	if s.next != nil {
		throw("runtime: sudog with non-nil next")
	}
	if s.prev != nil {
		throw("runtime: sudog with non-nil prev")
	}
	if s.waitlink != nil {
		throw("runtime: sudog with non-nil waitlink")
	}
	if s.c != nil {
		throw("runtime: sudog with non-nil c")
	}
	gp := getg()
	if gp.param != nil {
		throw("runtime: releaseSudog with non-nil gp.param")
	}
	mp := acquirem() // avoid rescheduling to another P
	pp := mp.p.ptr()
  // 如果本地缓存满了,就迁移至多一半容量缓存项到中心缓存
	if len(pp.sudogcache) == cap(pp.sudogcache) {
		// Transfer half of local cache to the central cache.
		var first, last *sudog
		for len(pp.sudogcache) > cap(pp.sudogcache)/2 {
			n := len(pp.sudogcache)
			p := pp.sudogcache[n-1]
			pp.sudogcache[n-1] = nil
			pp.sudogcache = pp.sudogcache[:n-1]
			if first == nil {
				first = p
			} else {
				last.next = p
			}
			last = p
		}
		lock(&sched.sudoglock)
    // 将迁移出来的本地缓存链表直接挂到中心缓存中
		last.next = sched.sudogcache
		sched.sudogcache = first
		unlock(&sched.sudoglock)
	}
  
  // 将释放的sudog添加到本地缓存
	pp.sudogcache = append(pp.sudogcache, s)
	releasem(mp)
}

原文地址:https://blog.csdn.net/iUcool/article/details/135995006

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_65811.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注