===================================================================
@@ -1,4 +1,4 @@
-14dc8052a09ad0a2226e64ab6b5af69c6923b830
+df6046971233854e5b7533140d4ead095ab69857
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
===================================================================
@@ -488,7 +488,6 @@ runtime_files = \
$(runtime_thread_files) \
runtime/yield.c \
$(rtems_task_variable_add_file) \
- lfstack.c \
malloc.c \
runtime1.c \
sigqueue.c \
===================================================================
@@ -6,6 +6,10 @@
package runtime
+import (
+ "unsafe"
+)
+
//var Fadd64 = fadd64
//var Fsub64 = fsub64
//var Fmul64 = fmul64
@@ -32,11 +36,13 @@ type LFNode struct {
Pushcnt uintptr
}
-func lfstackpush_go(head *uint64, node *LFNode)
-func lfstackpop_go(head *uint64) *LFNode
+func LFStackPush(head *uint64, node *LFNode) {
+ lfstackpush(head, (*lfnode)(unsafe.Pointer(node)))
+}
-var LFStackPush = lfstackpush_go
-var LFStackPop = lfstackpop_go
+func LFStackPop(head *uint64) *LFNode {
+ return (*LFNode)(unsafe.Pointer(lfstackpop(head)))
+}
type ParFor struct {
body func(*ParFor, uint32)
===================================================================
@@ -0,0 +1,50 @@
+// 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.
+// Initialize head to 0, compare with 0 to test for emptiness.
+// The stack does not keep pointers to nodes,
+// so they can be garbage collected if there are no other pointers to nodes.
+// The following code runs only in non-preemptible contexts.
+
+package runtime
+
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
+
+// Temporary for C code to call:
+//go:linkname lfstackpush runtime.lfstackpush
+//go:linkname lfstackpop runtime.lfstackpop
+
+func lfstackpush(head *uint64, node *lfnode) {
+ node.pushcnt++
+ new := lfstackPack(node, node.pushcnt)
+ if node1 := lfstackUnpack(new); node1 != node {
+ print("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+ throw("lfstackpush")
+ }
+ for {
+ old := atomic.Load64(head)
+ node.next = old
+ if atomic.Cas64(head, old, new) {
+ break
+ }
+ }
+}
+
+func lfstackpop(head *uint64) unsafe.Pointer {
+ for {
+ old := atomic.Load64(head)
+ if old == 0 {
+ return nil
+ }
+ node := lfstackUnpack(old)
+ next := atomic.Load64(&node.next)
+ if atomic.Cas64(head, old, next) {
+ return unsafe.Pointer(node)
+ }
+ }
+}
===================================================================
@@ -0,0 +1,19 @@
+// Copyright 2014 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.
+
+// +build 386 arm nacl armbe m68k mips mipsle mips64p32 mips64p32le mipso32 mipsn32 s390 sparc
+
+package runtime
+
+import "unsafe"
+
+// On 32-bit systems, the stored uint64 has a 32-bit pointer and 32-bit count.
+
+func lfstackPack(node *lfnode, cnt uintptr) uint64 {
+ return uint64(uintptr(unsafe.Pointer(node)))<<32 | uint64(cnt)
+}
+
+func lfstackUnpack(val uint64) *lfnode {
+ return (*lfnode)(unsafe.Pointer(uintptr(val >> 32)))
+}
===================================================================
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build ignore
-
-// +build amd64 arm64 mips64 mips64le ppc64 ppc64le s390x
+// +build amd64 arm64 mips64 mips64le ppc64 ppc64le s390x arm64be alpha mipsn64 sparc64
package runtime
@@ -41,8 +39,8 @@ func lfstackPack(node *lfnode, cnt uintp
}
func lfstackUnpack(val uint64) *lfnode {
- if GOARCH == "amd64" {
- // amd64 systems can place the stack above the VA hole, so we need to sign extend
+ if GOARCH == "amd64" || GOOS == "solaris" {
+ // amd64 or Solaris systems can place the stack above the VA hole, so we need to sign extend
// val before unpacking.
return (*lfnode)(unsafe.Pointer(uintptr(int64(val) >> cntBits << 3)))
}
===================================================================
@@ -1,95 +0,0 @@
-// 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
-#include "runtime.h"
-#include "arch.h"
-
-#if __SIZEOF_POINTER__ == 8
-// SPARC64 and Solaris on AMD64 uses all 64 bits of virtual addresses.
-// Use low-order three bits as ABA counter.
-// http://docs.oracle.com/cd/E19120-01/open.solaris/816-5138/6mba6ua5p/index.html
-# if defined(__sparc__) || (defined(__sun__) && defined(__amd64__))
-static inline uint64 lfPack(LFNode *node, uintptr cnt) {
- return ((uint64)(node)) | ((cnt)&7);
-}
-static inline LFNode* lfUnpack(uint64 val) {
- return (LFNode*)(val&~7);
-}
-# else
-# if defined(__aarch64__)
-// Depending on the kernel options, pointers on arm64 can have up to 48 significant
-// bits (see https://www.kernel.org/doc/Documentation/arm64/memory.txt).
-# define PTR_BITS 48
-# else
-// 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
-# endif
-# define CNT_BITS (64 - PTR_BITS + 3)
-static inline uint64 lfPack(LFNode *node, uintptr cnt) {
- return ((uint64)(node)<<(64-PTR_BITS)) | (cnt&(((1<<CNT_BITS)-1)));
-}
-static inline LFNode* lfUnpack(uint64 val) {
- return (LFNode*)((val >> CNT_BITS) << 3);
-}
-# endif
-#else
-static inline uint64 lfPack(LFNode *node, uintptr cnt) {
- return ((uint64)(uintptr)(node)<<32) | cnt;
-}
-static inline LFNode* lfUnpack(uint64 val) {
- return (LFNode*)(uintptr)(val >> 32);
-}
-#endif
-
-void
-runtime_lfstackpush(uint64 *head, LFNode *node)
-{
- uint64 old, new;
-
- if(node != lfUnpack(lfPack(node, 0))) {
- runtime_printf("p=%p\n", node);
- runtime_throw("runtime_lfstackpush: invalid pointer");
- }
-
- node->pushcnt++;
- new = lfPack(node, node->pushcnt);
- for(;;) {
- old = runtime_atomicload64(head);
- node->next = lfUnpack(old);
- 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 = lfUnpack(old);
- node2 = runtime_atomicloadp(&node->next);
- new = 0;
- if(node2 != nil)
- new = lfPack(node2, node2->pushcnt);
- if(runtime_cas64(head, old, new))
- return node;
- }
-}
-
-func lfstackpush_go(head *uint64, node *LFNode) {
- runtime_lfstackpush(head, node);
-}
-
-func lfstackpop_go(head *uint64) (node *LFNode) {
- node = runtime_lfstackpop(head);
-}
===================================================================
@@ -67,7 +67,7 @@ typedef struct FixAlloc FixAlloc;
typedef struct hchan Hchan;
typedef struct timer Timer;
typedef struct gcstats GCStats;
-typedef struct LFNode LFNode;
+typedef struct lfnode LFNode;
typedef struct ParFor ParFor;
typedef struct ParForThread ParForThread;
typedef struct cgoMal CgoMal;
@@ -178,13 +178,6 @@ enum {
};
#endif
-// Lock-free stack node.
-struct LFNode
-{
- LFNode *next;
- uintptr pushcnt;
-};
-
// Parallel for descriptor.
struct ParFor
{
@@ -461,7 +454,8 @@ bool runtime_notetsleepg(Note*, int64)
*/
void runtime_lfstackpush(uint64 *head, LFNode *node)
__asm__ (GOSYM_PREFIX "runtime.lfstackpush");
-LFNode* runtime_lfstackpop(uint64 *head);
+void* runtime_lfstackpop(uint64 *head)
+ __asm__ (GOSYM_PREFIX "runtime.lfstackpop");
/*
* Parallel for over [0, n).