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 { ...@@ -41,7 +41,6 @@ type ParFor struct {
Nthr uint32 Nthr uint32
thrseq uint32 thrseq uint32
Cnt uint32 Cnt uint32
Ctx *byte
wait bool wait bool
} }
...@@ -53,9 +52,9 @@ func NewParFor(nthrmax uint32) *ParFor { ...@@ -53,9 +52,9 @@ func NewParFor(nthrmax uint32) *ParFor {
return desc 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() { 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))) *(*func(*parfor, uint32))(unsafe.Pointer(&body)))
}) })
} }
......
...@@ -1490,7 +1490,7 @@ func gcscan_m() { ...@@ -1490,7 +1490,7 @@ func gcscan_m() {
work.ndone = 0 work.ndone = 0
work.nproc = 1 // For now do not do this in parallel. work.nproc = 1 // For now do not do this in parallel.
// ackgcphase is not needed since we are not scanning running goroutines. // 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) parfordo(work.markfor)
lock(&allglock) lock(&allglock)
...@@ -1588,7 +1588,7 @@ func gc(start_time int64, eagersweep bool) { ...@@ -1588,7 +1588,7 @@ func gc(start_time int64, eagersweep bool) {
traceGCScanStart() 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 { if work.nproc > 1 {
noteclear(&work.alldone) noteclear(&work.alldone)
helpgc(int32(work.nproc)) helpgc(int32(work.nproc))
......
...@@ -15,7 +15,6 @@ type parfor struct { ...@@ -15,7 +15,6 @@ type parfor struct {
nthr uint32 // total number of threads nthr uint32 // total number of threads
thrseq uint32 // thread id sequencer thrseq uint32 // thread id sequencer
cnt uint32 // iteration space [0, cnt) cnt uint32 // iteration space [0, cnt)
ctx unsafe.Pointer // arbitrary user context
wait bool // if true, wait while all threads finish processing, wait bool // if true, wait while all threads finish processing,
// otherwise parfor may return while other threads are still working // otherwise parfor may return while other threads are still working
...@@ -58,9 +57,7 @@ func parforalloc(nthrmax uint32) *parfor { ...@@ -58,9 +57,7 @@ func parforalloc(nthrmax uint32) *parfor {
// If wait is false, parfordo may return when there is a small amount // If wait is false, parfordo may return when there is a small amount
// of work left, under the assumption that another thread has that // of work left, under the assumption that another thread has that
// work well in hand. // work well in hand.
// The opaque user context ctx is recorded as desc.ctx and can be used by body. func parforsetup(desc *parfor, nthr, n uint32, wait bool, body func(*parfor, uint32)) {
// 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)) {
if desc == nil || nthr == 0 || nthr > uint32(len(desc.thr)) || body == nil { if desc == nil || nthr == 0 || nthr > uint32(len(desc.thr)) || body == nil {
print("desc=", desc, " nthr=", nthr, " count=", n, " body=", body, "\n") print("desc=", desc, " nthr=", nthr, " count=", n, " body=", body, "\n")
throw("parfor: invalid args") throw("parfor: invalid args")
...@@ -71,7 +68,6 @@ func parforsetup(desc *parfor, nthr, n uint32, ctx unsafe.Pointer, wait bool, bo ...@@ -71,7 +68,6 @@ func parforsetup(desc *parfor, nthr, n uint32, ctx unsafe.Pointer, wait bool, bo
desc.nthr = nthr desc.nthr = nthr
desc.thrseq = 0 desc.thrseq = 0
desc.cnt = n desc.cnt = n
desc.ctx = ctx
desc.wait = wait desc.wait = wait
desc.nsteal = 0 desc.nsteal = 0
desc.nstealcnt = 0 desc.nstealcnt = 0
......
...@@ -10,11 +10,8 @@ package runtime_test ...@@ -10,11 +10,8 @@ package runtime_test
import ( import (
. "runtime" . "runtime"
"testing" "testing"
"unsafe"
) )
var gdata []uint64
// Simple serial sanity test for parallelfor. // Simple serial sanity test for parallelfor.
func TestParFor(t *testing.T) { func TestParFor(t *testing.T) {
const P = 1 const P = 1
...@@ -24,12 +21,7 @@ func TestParFor(t *testing.T) { ...@@ -24,12 +21,7 @@ func TestParFor(t *testing.T) {
data[i] = i data[i] = i
} }
desc := NewParFor(P) desc := NewParFor(P)
// Avoid making func a closure: parfor cannot invoke them. ParForSetup(desc, P, N, true, func(desc *ParFor, i uint32) {
// 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
data[i] = data[i]*data[i] + 1 data[i] = data[i]*data[i] + 1
}) })
ParForDo(desc) ParForDo(desc)
...@@ -49,9 +41,8 @@ func TestParFor2(t *testing.T) { ...@@ -49,9 +41,8 @@ func TestParFor2(t *testing.T) {
data[i] = i data[i] = i
} }
desc := NewParFor(P) desc := NewParFor(P)
ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) { ParForSetup(desc, P, N, false, func(desc *ParFor, i uint32) {
d := *(*[]uint64)(unsafe.Pointer(desc.Ctx)) data[i] = data[i]*data[i] + 1
d[i] = d[i]*d[i] + 1
}) })
for p := 0; p < P; p++ { for p := 0; p < P; p++ {
ParForDo(desc) ParForDo(desc)
...@@ -70,7 +61,7 @@ func TestParForSetup(t *testing.T) { ...@@ -70,7 +61,7 @@ func TestParForSetup(t *testing.T) {
desc := NewParFor(P) desc := NewParFor(P)
for n := uint32(0); n < N; n++ { for n := uint32(0); n < N; n++ {
for p := uint32(1); p <= P; p++ { 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) sum := uint32(0)
size0 := uint32(0) size0 := uint32(0)
end0 := uint32(0) end0 := uint32(0)
...@@ -113,9 +104,7 @@ func TestParForParallel(t *testing.T) { ...@@ -113,9 +104,7 @@ func TestParForParallel(t *testing.T) {
P := GOMAXPROCS(-1) P := GOMAXPROCS(-1)
c := make(chan bool, P) c := make(chan bool, P)
desc := NewParFor(uint32(P)) desc := NewParFor(uint32(P))
gdata = data ParForSetup(desc, uint32(P), uint32(N), false, func(desc *ParFor, i uint32) {
ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
data := gdata
data[i] = data[i]*data[i] + 1 data[i] = data[i]*data[i] + 1
}) })
for p := 1; p < P; p++ { 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