mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 19:03:59 +08:00
runtime: copy lfstack code from Go 1.7 runtime
Note that lfstack_64bit.go was modified for Solaris support in a different, and better, way than the superseded lfstack.goc code. Reviewed-on: https://go-review.googlesource.com/31673 From-SVN: r241427
This commit is contained in:
parent
16b61424dd
commit
e597e0533d
@ -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 \
|
||||
|
@ -252,8 +252,8 @@ am__objects_5 = go-append.lo go-assert.lo go-breakpoint.lo \
|
||||
env_posix.lo heapdump.lo mcache.lo mcentral.lo \
|
||||
$(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo msize.lo \
|
||||
panic.lo parfor.lo print.lo proc.lo runtime.lo signal_unix.lo \
|
||||
thread.lo $(am__objects_2) yield.lo $(am__objects_3) \
|
||||
lfstack.lo malloc.lo runtime1.lo sigqueue.lo $(am__objects_4)
|
||||
thread.lo $(am__objects_2) yield.lo $(am__objects_3) malloc.lo \
|
||||
runtime1.lo sigqueue.lo $(am__objects_4)
|
||||
am_libgo_llgo_la_OBJECTS = $(am__objects_5)
|
||||
libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
|
||||
libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
@ -884,7 +884,6 @@ runtime_files = \
|
||||
$(runtime_thread_files) \
|
||||
runtime/yield.c \
|
||||
$(rtems_task_variable_add_file) \
|
||||
lfstack.c \
|
||||
malloc.c \
|
||||
runtime1.c \
|
||||
sigqueue.c \
|
||||
@ -1562,7 +1561,6 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-varargs.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heapdump.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lfstack.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgobegin_a-go-main.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgobegin_llgo_a-go-main.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgolibbegin_a-go-libmain.Po@am__quote@
|
||||
|
@ -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)
|
||||
|
50
libgo/go/runtime/lfstack.go
Normal file
50
libgo/go/runtime/lfstack.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
19
libgo/go/runtime/lfstack_32bit.go
Normal file
19
libgo/go/runtime/lfstack_32bit.go
Normal file
@ -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 uintptr) uint64 {
|
||||
}
|
||||
|
||||
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) // false - timeout
|
||||
*/
|
||||
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).
|
||||
|
Loading…
Reference in New Issue
Block a user