mirror of
https://github.com/golang/go
synced 2024-10-04 20:21:22 -06:00
fb63e4fefb
The current cas64 definition hard-codes the x86 behavior of updating *old with the new value when the cas fails. This is inconsistent with cas32 and casp. Make it consistent. This means that the cas64 uses will be epsilon less efficient than they might be, because they have to do an unnecessary memory load on x86. But so be it. Code clarity and consistency is more important. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/10909045
66 lines
1.4 KiB
C
66 lines
1.4 KiB
C
// 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.
|
|
|
|
#include "runtime.h"
|
|
#include "arch_GOARCH.h"
|
|
|
|
#ifdef _64BIT
|
|
// Amd64 uses 48-bit virtual addresses, 47-th bit is used as kernel/user flag.
|
|
// So we use 17msb of pointers as ABA counter.
|
|
# define PTR_BITS 47
|
|
#else
|
|
# define PTR_BITS 32
|
|
#endif
|
|
#define PTR_MASK ((1ull<<PTR_BITS)-1)
|
|
#define CNT_MASK (0ull-1)
|
|
|
|
void
|
|
runtime·lfstackpush(uint64 *head, LFNode *node)
|
|
{
|
|
uint64 old, new;
|
|
|
|
if((uintptr)node != ((uintptr)node&PTR_MASK)) {
|
|
runtime·printf("p=%p\n", node);
|
|
runtime·throw("runtime·lfstackpush: invalid pointer");
|
|
}
|
|
|
|
node->pushcnt++;
|
|
new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS);
|
|
for(;;) {
|
|
old = runtime·atomicload64(head);
|
|
node->next = (LFNode*)(uintptr)(old&PTR_MASK);
|
|
if(runtime·cas64(head, old, new))
|
|
break;
|
|
}
|
|
}
|
|
|
|
LFNode*
|
|
runtime·lfstackpop(uint64 *head)
|
|
{
|
|
LFNode *node, *node2;
|
|
uint64 old, new;
|
|
|
|
for(;;) {
|
|
old = runtime·atomicload64(head);
|
|
if(old == 0)
|
|
return nil;
|
|
node = (LFNode*)(uintptr)(old&PTR_MASK);
|
|
node2 = runtime·atomicloadp(&node->next);
|
|
new = 0;
|
|
if(node2 != nil)
|
|
new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<<PTR_BITS);
|
|
if(runtime·cas64(head, old, new))
|
|
return node;
|
|
}
|
|
}
|
|
|
|
void
|
|
runtime·lfstackpop2(uint64 *head, LFNode *node)
|
|
{
|
|
node = runtime·lfstackpop(head);
|
|
FLUSH(&node);
|
|
}
|