| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| // The following code runs only on g0 stack. |
| // lfPtrBits and lfCountMask are defined in lfstack_*.go. |
| lfPtrMask = 1<<lfPtrBits - 1 |
| func lfstackpush(head *uint64, node *lfnode) { |
| unode := uintptr(unsafe.Pointer(node)) |
| if unode&^lfPtrMask != 0 { |
| gothrow("lfstackpush: invalid pointer") |
| new := uint64(unode) | (uint64(node.pushcnt)&lfCountMask)<<lfPtrBits |
| old := atomicload64(head) |
| node.next = (*lfnode)(unsafe.Pointer(uintptr(old & lfPtrMask))) |
| if cas64(head, old, new) { |
| func lfstackpop(head *uint64) unsafe.Pointer { |
| old := atomicload64(head) |
| node := (*lfnode)(unsafe.Pointer(uintptr(old & lfPtrMask))) |
| node2 := (*lfnode)(atomicloadp(unsafe.Pointer(&node.next))) |
| new = uint64(uintptr(unsafe.Pointer(node2))) | uint64(node2.pushcnt&lfCountMask)<<lfPtrBits |
| if cas64(head, old, new) { |
| return unsafe.Pointer(node) |