From 428afae027548e079335d25cacb70082a0ef8d9f Mon Sep 17 00:00:00 2001
From: Austin Clements <austin@google.com>
Date: Wed, 28 Jan 2015 15:55:23 -0500
Subject: [PATCH] runtime: use func value for parfor body

Yet another leftover from C: parfor took a func value for the
callback, casted it to an unsafe.Pointer for storage, and then casted
it back to a func value to call it.  This is unnecessary, so just
store the body as a func value.  Beyond general cleanup, this also
eliminates the last use of unsafe in parfor.

Change-Id: Ia904af7c6c443ba75e2699835aee8e9a39b26dd8
Reviewed-on: https://go-review.googlesource.com/3396
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
---
 src/runtime/export_test.go |  2 +-
 src/runtime/parfor.go      | 18 ++++++++----------
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 51798efe0b..a5d923e860 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -36,7 +36,7 @@ func LFStackPop(head *uint64) *LFNode {
 }
 
 type ParFor struct {
-	body   *byte
+	body   func(*ParFor, uint32)
 	done   uint32
 	Nthr   uint32
 	thrseq uint32
diff --git a/src/runtime/parfor.go b/src/runtime/parfor.go
index 31fefeb9d8..c82beee3fd 100644
--- a/src/runtime/parfor.go
+++ b/src/runtime/parfor.go
@@ -6,16 +6,14 @@
 
 package runtime
 
-import "unsafe"
-
 // A parfor holds state for the parallel for operation.
 type parfor struct {
-	body   unsafe.Pointer // go func(*parfor, uint32), executed for each element
-	done   uint32         // number of idle threads
-	nthr   uint32         // total number of threads
-	thrseq uint32         // thread id sequencer
-	cnt    uint32         // iteration space [0, cnt)
-	wait   bool           // if true, wait while all threads finish processing,
+	body   func(*parfor, uint32) // executed for each element
+	done   uint32                // number of idle threads
+	nthr   uint32                // total number of threads
+	thrseq uint32                // thread id sequencer
+	cnt    uint32                // iteration space [0, cnt)
+	wait   bool                  // if true, wait while all threads finish processing,
 	// otherwise parfor may return while other threads are still working
 
 	thr []parforthread // thread descriptors
@@ -63,7 +61,7 @@ func parforsetup(desc *parfor, nthr, n uint32, wait bool, body func(*parfor, uin
 		throw("parfor: invalid args")
 	}
 
-	desc.body = *(*unsafe.Pointer)(unsafe.Pointer(&body))
+	desc.body = body
 	desc.done = 0
 	desc.nthr = nthr
 	desc.thrseq = 0
@@ -91,7 +89,7 @@ func parfordo(desc *parfor) {
 	}
 
 	// If single-threaded, just execute the for serially.
-	body := *(*func(*parfor, uint32))(unsafe.Pointer(&desc.body))
+	body := desc.body
 	if desc.nthr == 1 {
 		for i := uint32(0); i < desc.cnt; i++ {
 			body(desc, i)
-- 
2.30.9