// 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.

// Lock-free stack.

package runtime

import (
	
	
)

// lfstack is the head of a lock-free stack.
//
// The zero value of lfstack is an empty list.
//
// This stack is intrusive. Nodes must embed lfnode as the first field.
//
// The stack does not keep GC-visible pointers to nodes, so the caller
// must ensure the nodes are allocated outside the Go heap.
type lfstack uint64

func ( *lfstack) ( *lfnode) {
	.pushcnt++
	 := lfstackPack(, .pushcnt)
	if  := lfstackUnpack();  !=  {
		print("runtime: lfstack.push invalid packing: node=", , " cnt=", hex(.pushcnt), " packed=", hex(), " -> node=", , "\n")
		throw("lfstack.push")
	}
	for {
		 := atomic.Load64((*uint64)())
		.next = 
		if atomic.Cas64((*uint64)(), , ) {
			break
		}
	}
}

func ( *lfstack) () unsafe.Pointer {
	for {
		 := atomic.Load64((*uint64)())
		if  == 0 {
			return nil
		}
		 := lfstackUnpack()
		 := atomic.Load64(&.next)
		if atomic.Cas64((*uint64)(), , ) {
			return unsafe.Pointer()
		}
	}
}

func ( *lfstack) () bool {
	return atomic.Load64((*uint64)()) == 0
}

// lfnodeValidate panics if node is not a valid address for use with
// lfstack.push. This only needs to be called when node is allocated.
func lfnodeValidate( *lfnode) {
	if , ,  := findObject(uintptr(unsafe.Pointer()), 0, 0);  != 0 {
		throw("lfstack node allocated from the heap")
	}
	if lfstackUnpack(lfstackPack(, ^uintptr(0))) !=  {
		printlock()
		println("runtime: bad lfnode address", hex(uintptr(unsafe.Pointer())))
		throw("bad lfnode address")
	}
}

func lfstackPack( *lfnode,  uintptr) uint64 {
	return uint64(taggedPointerPack(unsafe.Pointer(), ))
}

func lfstackUnpack( uint64) *lfnode {
	return (*lfnode)(taggedPointer().pointer())
}