github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/runtime/slqueue.go (about)

     1  package runtime
     2  
     3  type slqueue struct {
     4  	m    mutex
     5  	head sguintptr
     6  	tail sguintptr
     7  	size uint64
     8  }
     9  
    10  //go:nosplit
    11  //go:nowritebarrier
    12  func slqget(q *slqueue, locked bool) (*sudog, *sudog, int) {
    13  	if !locked {
    14  		MarkNoFutex()
    15  		lock(&q.m)
    16  		MarkFutex()
    17  	}
    18  	head, tail, size := q.head, q.tail, q.size
    19  	q.head, q.tail, q.size = 0, 0, 0
    20  	if !locked {
    21  		unlock(&q.m)
    22  	}
    23  	if size == 1 && head != tail {
    24  		throw("slqueue: head != tail for size 1.")
    25  	}
    26  	return head.ptr(), tail.ptr(), int(size)
    27  }
    28  
    29  //go:nosplit
    30  //go:nowritebarrier
    31  func slqput(q *slqueue, elem *sudog) {
    32  	var tail *sudog = elem
    33  	var size uint64 = 1
    34  	for tail.schednext != 0 {
    35  		// Just going through the list to find the tail
    36  		size++
    37  		tail = tail.schednext.ptr()
    38  	}
    39  	if tail == nil {
    40  		throw("slqueue tail is nil...")
    41  	}
    42  	MarkNoFutex()
    43  	lock(&q.m)
    44  	MarkFutex()
    45  	if q.tail == 0 {
    46  		if q.head != 0 || q.size != 0 {
    47  			throw("Malformed slqueue: the head is not nil, but tail is")
    48  		}
    49  		q.head.set(elem)
    50  	} else {
    51  		q.tail.ptr().schednext.set(elem)
    52  	}
    53  	q.tail.set(tail)
    54  	q.size += size
    55  	unlock(&q.m)
    56  }