Home | History | Annotate | Download | only in runtime
      1 // Copyright 2012 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Lock-free stack.
      6 // Initialize head to 0, compare with 0 to test for emptiness.
      7 // The stack does not keep pointers to nodes,
      8 // so they can be garbage collected if there are no other pointers to nodes.
      9 // The following code runs only in non-preemptible contexts.
     10 
     11 package runtime
     12 
     13 import (
     14 	"runtime/internal/atomic"
     15 	"unsafe"
     16 )
     17 
     18 func lfstackpush(head *uint64, node *lfnode) {
     19 	node.pushcnt++
     20 	new := lfstackPack(node, node.pushcnt)
     21 	if node1 := lfstackUnpack(new); node1 != node {
     22 		print("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
     23 		throw("lfstackpush")
     24 	}
     25 	for {
     26 		old := atomic.Load64(head)
     27 		node.next = old
     28 		if atomic.Cas64(head, old, new) {
     29 			break
     30 		}
     31 	}
     32 }
     33 
     34 func lfstackpop(head *uint64) unsafe.Pointer {
     35 	for {
     36 		old := atomic.Load64(head)
     37 		if old == 0 {
     38 			return nil
     39 		}
     40 		node := lfstackUnpack(old)
     41 		next := atomic.Load64(&node.next)
     42 		if atomic.Cas64(head, old, next) {
     43 			return unsafe.Pointer(node)
     44 		}
     45 	}
     46 }
     47