blob: 5838c1d14d05ad449df74489e0d288c0ef849a9f [file] [log] [blame]
Russ Coxece09792014-11-11 17:07:54 -05001// 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// The following code runs only on g0 stack.
7
8package runtime
9
10import "unsafe"
11
Russ Coxece09792014-11-11 17:07:54 -050012func lfstackpush(head *uint64, node *lfnode) {
Russ Coxece09792014-11-11 17:07:54 -050013 node.pushcnt++
Russ Cox5fce15a2014-11-14 12:55:23 -050014 new := lfstackPack(node, node.pushcnt)
Austin Clementsb76e8362014-11-19 11:30:58 -050015 if node1, _ := lfstackUnpack(new); node1 != node {
16 println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
Keith Randallb2a950b2014-12-27 20:58:00 -080017 throw("lfstackpush")
Austin Clementsb76e8362014-11-19 11:30:58 -050018 }
Russ Coxece09792014-11-11 17:07:54 -050019 for {
20 old := atomicload64(head)
Russ Cox0fcf54b2014-11-15 08:00:38 -050021 node.next = old
Russ Coxece09792014-11-11 17:07:54 -050022 if cas64(head, old, new) {
23 break
24 }
25 }
26}
27
28func lfstackpop(head *uint64) unsafe.Pointer {
29 for {
30 old := atomicload64(head)
31 if old == 0 {
32 return nil
33 }
Russ Cox5fce15a2014-11-14 12:55:23 -050034 node, _ := lfstackUnpack(old)
Russ Cox0fcf54b2014-11-15 08:00:38 -050035 next := atomicload64(&node.next)
36 if cas64(head, old, next) {
Russ Coxece09792014-11-11 17:07:54 -050037 return unsafe.Pointer(node)
38 }
39 }
40}