Commit ebbdf2a1 authored by Austin Clements's avatar Austin Clements

runtime: eliminate parfor ctx field

Prior to the conversion of the runtime to Go, this void* was
necessary to get closure information in to C callbacks.  There
are no more C callbacks and parfor is perfectly capable of
invoking a Go closure now, so eliminate ctx and all of its
unsafe-ness.  (Plus, the runtime currently doesn't use ctx for
anything.)

Change-Id: I39fc53b7dd3d7f660710abc76b0d831bfc6296d8
Reviewed-on: https://go-review.googlesource.com/3395Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Reviewed-by: 's avatarDmitry Vyukov <dvyukov@google.com>
parent 8e2bb7bb
......@@ -41,7 +41,6 @@ type ParFor struct {
Nthr uint32
thrseq uint32
Cnt uint32
Ctx *byte
wait bool
}
......@@ -53,9 +52,9 @@ func NewParFor(nthrmax uint32) *ParFor {
return desc
}
func ParForSetup(desc *ParFor, nthr, n uint32, ctx *byte, wait bool, body func(*ParFor, uint32)) {
func ParForSetup(desc *ParFor, nthr, n uint32, wait bool, body func(*ParFor, uint32)) {
systemstack(func() {
parforsetup((*parfor)(unsafe.Pointer(desc)), nthr, n, unsafe.Pointer(ctx), wait,
parforsetup((*parfor)(unsafe.Pointer(desc)), nthr, n, wait,
*(*func(*parfor, uint32))(unsafe.Pointer(&body)))
})
}
......
......@@ -1490,7 +1490,7 @@ func gcscan_m() {
work.ndone = 0
work.nproc = 1 // For now do not do this in parallel.
// ackgcphase is not needed since we are not scanning running goroutines.
parforsetup(work.markfor, work.nproc, uint32(_RootCount+local_allglen), nil, false, markroot)
parforsetup(work.markfor, work.nproc, uint32(_RootCount+local_allglen), false, markroot)
parfordo(work.markfor)
lock(&allglock)
......@@ -1588,7 +1588,7 @@ func gc(start_time int64, eagersweep bool) {
traceGCScanStart()
}
parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), nil, false, markroot)
parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), false, markroot)
if work.nproc > 1 {
noteclear(&work.alldone)
helpgc(int32(work.nproc))
......
......@@ -15,7 +15,6 @@ type parfor struct {
nthr uint32 // total number of threads
thrseq uint32 // thread id sequencer
cnt uint32 // iteration space [0, cnt)
ctx unsafe.Pointer // arbitrary user context
wait bool // if true, wait while all threads finish processing,
// otherwise parfor may return while other threads are still working
......@@ -58,9 +57,7 @@ func parforalloc(nthrmax uint32) *parfor {
// If wait is false, parfordo may return when there is a small amount
// of work left, under the assumption that another thread has that
// work well in hand.
// The opaque user context ctx is recorded as desc.ctx and can be used by body.
// TODO(austin): Remove ctx in favor of using a closure for body.
func parforsetup(desc *parfor, nthr, n uint32, ctx unsafe.Pointer, wait bool, body func(*parfor, uint32)) {
func parforsetup(desc *parfor, nthr, n uint32, wait bool, body func(*parfor, uint32)) {
if desc == nil || nthr == 0 || nthr > uint32(len(desc.thr)) || body == nil {
print("desc=", desc, " nthr=", nthr, " count=", n, " body=", body, "\n")
throw("parfor: invalid args")
......@@ -71,7 +68,6 @@ func parforsetup(desc *parfor, nthr, n uint32, ctx unsafe.Pointer, wait bool, bo
desc.nthr = nthr
desc.thrseq = 0
desc.cnt = n
desc.ctx = ctx
desc.wait = wait
desc.nsteal = 0
desc.nstealcnt = 0
......
......@@ -10,11 +10,8 @@ package runtime_test
import (
. "runtime"
"testing"
"unsafe"
)
var gdata []uint64
// Simple serial sanity test for parallelfor.
func TestParFor(t *testing.T) {
const P = 1
......@@ -24,12 +21,7 @@ func TestParFor(t *testing.T) {
data[i] = i
}
desc := NewParFor(P)
// Avoid making func a closure: parfor cannot invoke them.
// Since it doesn't happen in the C code, it's not worth doing
// just for the test.
gdata = data
ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
data := gdata
ParForSetup(desc, P, N, true, func(desc *ParFor, i uint32) {
data[i] = data[i]*data[i] + 1
})
ParForDo(desc)
......@@ -49,9 +41,8 @@ func TestParFor2(t *testing.T) {
data[i] = i
}
desc := NewParFor(P)
ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) {
d := *(*[]uint64)(unsafe.Pointer(desc.Ctx))
d[i] = d[i]*d[i] + 1
ParForSetup(desc, P, N, false, func(desc *ParFor, i uint32) {
data[i] = data[i]*data[i] + 1
})
for p := 0; p < P; p++ {
ParForDo(desc)
......@@ -70,7 +61,7 @@ func TestParForSetup(t *testing.T) {
desc := NewParFor(P)
for n := uint32(0); n < N; n++ {
for p := uint32(1); p <= P; p++ {
ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {})
ParForSetup(desc, p, n, true, func(desc *ParFor, i uint32) {})
sum := uint32(0)
size0 := uint32(0)
end0 := uint32(0)
......@@ -113,9 +104,7 @@ func TestParForParallel(t *testing.T) {
P := GOMAXPROCS(-1)
c := make(chan bool, P)
desc := NewParFor(uint32(P))
gdata = data
ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
data := gdata
ParForSetup(desc, uint32(P), uint32(N), false, func(desc *ParFor, i uint32) {
data[i] = data[i]*data[i] + 1
})
for p := 1; p < P; p++ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment