github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/runtime/lfstack.go (about) 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 }