[dev.cc] runtime: convert parallel support code from C to Go

The conversion was done with an automated tool and then
modified only as necessary to make it compile and run.

[This CL is part of the removal of C code from package runtime.
See golang.org/s/dev.cc for an overview.]

LGTM=r
R=r, austin
CC=dvyukov, golang-codereviews, iant, khr
https://golang.org/cl/172250043
This commit is contained in:
Russ Cox 2014-11-11 17:07:54 -05:00
parent 580ef3e4af
commit ece09790af
7 changed files with 281 additions and 366 deletions

51
src/runtime/lfstack.go Normal file
View file

@ -0,0 +1,51 @@
// 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.
// The following code runs only on g0 stack.
package runtime
import "unsafe"
const (
// 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 {
print("p=", node, "\n")
gothrow("lfstackpush: invalid pointer")
}
node.pushcnt++
new := uint64(unode) | (uint64(node.pushcnt)&lfCountMask)<<lfPtrBits
for {
old := atomicload64(head)
node.next = (*lfnode)(unsafe.Pointer(uintptr(old & lfPtrMask)))
if cas64(head, old, new) {
break
}
}
}
func lfstackpop(head *uint64) unsafe.Pointer {
for {
old := atomicload64(head)
if old == 0 {
return nil
}
node := (*lfnode)(unsafe.Pointer(uintptr(old & lfPtrMask)))
node2 := (*lfnode)(atomicloadp(unsafe.Pointer(&node.next)))
new := uint64(0)
if node2 != nil {
new = uint64(uintptr(unsafe.Pointer(node2))) | uint64(node2.pushcnt&lfCountMask)<<lfPtrBits
}
if cas64(head, old, new) {
return unsafe.Pointer(node)
}
}
}