[fuchsia] Expose runtime threads

Exposes all runtime threads through the channel signaling mechanism and
not only worker threads.

Bug: 122472

Change-Id: I2718617b3782ff0bda25912fcfe21587b2a14cb2
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/go/+/808487
Reviewed-by: Tamir Duberstein <tamird@google.com>
Fuchsia-Auto-Submit: Bruno Dal Bo <brunodalbo@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
(cherry picked from commit 1e1d3be4725fcd1ea756acccdb7dff1206e312f3)
diff --git a/src/runtime/os_fuchsia.go b/src/runtime/os_fuchsia.go
index 853d1ff..232ee1c 100644
--- a/src/runtime/os_fuchsia.go
+++ b/src/runtime/os_fuchsia.go
@@ -73,7 +73,7 @@
 func zx_set_namespace(m map[string]uint32)
 
 //go:linkname zx_notify_new_thread syscall/zx.notify_new_thread
-func zx_notify_new_thread(h uint32)
+func zx_notify_new_thread(h uint32, w byte)
 
 //go:linkname zx_init_threads_channel syscall/zx.init_threads_channel
 func zx_init_threads_channel()
@@ -279,6 +279,18 @@
 	_cgo_write1                 unsafe.Pointer
 )
 
+type ThreadType byte
+
+const (
+	_ ThreadType = iota
+	WorkerThread
+	UnknownRuntimeThread
+	SysmonThread
+	WatchExceptionsThread
+	ProfileLoopThread
+	TemplateThread
+)
+
 //go:nosplit
 func minit() {
 	_g_ := getg()
@@ -291,8 +303,11 @@
 
 	mp.thread = h
 
+	// NB: Write barrier restrictions in this function disallow a nicer pattern
+	// to assign these variables.
 	isWorker := mp.p != 0 || mp.nextp != 0
 	threadName := []byte("go-worker")
+	threadType := WorkerThread
 	if !isWorker {
 		// There are some known functions that we can compare against,
 		// unfortunately we can't use FuncForPC here because of the write
@@ -300,14 +315,19 @@
 		switch abi.FuncPCABIInternal(mp.mstartfn) {
 		case abi.FuncPCABIInternal(sysmon):
 			threadName = []byte("sysmon")
+			threadType = SysmonThread
 		case abi.FuncPCABIInternal(watchexceptions):
 			threadName = []byte("watchexceptions")
+			threadType = WatchExceptionsThread
 		case abi.FuncPCABIInternal(profileLoop):
 			threadName = []byte("profileLoop")
+			threadType = ProfileLoopThread
 		case abi.FuncPCABIInternal(templateThread):
 			threadName = []byte("templateThread")
+			threadType = TemplateThread
 		default:
 			threadName = []byte("unknown-runtime-thread")
+			threadType = UnknownRuntimeThread
 		}
 	}
 
@@ -325,10 +345,7 @@
 		mp.threadKoid = info.koid
 	}
 
-	if isWorker {
-		// Don't notifiy users of runtime threads.
-		zx_notify_new_thread(h)
-	}
+	zx_notify_new_thread(h, byte(threadType))
 	unlock(&mp.threadLock)
 }
 
diff --git a/src/syscall/zx/threads_fuchsia.go b/src/syscall/zx/threads_fuchsia.go
index d300090..1bc6f03 100644
--- a/src/syscall/zx/threads_fuchsia.go
+++ b/src/syscall/zx/threads_fuchsia.go
@@ -4,6 +4,8 @@
 
 package zx
 
+import "unsafe"
+
 var threadQueue struct {
 	writer, reader Channel
 }
@@ -25,8 +27,11 @@
 // this because minit is a very restricted environment where we can't allocate
 // or do much else.
 //
+// h is the thread handle. w is a constant exported from the runtime package
+// saying which thread type this is.
+//
 //go:nosplit
-func notify_new_thread(h int32) {
+func notify_new_thread(h uint32, w byte) {
 	var dup Handle
 	// Duplicate the handle with the minimum set of rights to accomplish
 	// exposing the threads to applications and installing thread profiles.
@@ -34,14 +39,17 @@
 		// NB: Can't allocate here to provide status in panic.
 		panic("failed to duplicate thread handle")
 	}
-	if status := Sys_channel_write(threadQueue.writer.Handle().Load(), 0, nil, 0, &dup, 1); status != ErrOk {
+
+	if status := Sys_channel_write(threadQueue.writer.Handle().Load(), 0, unsafe.Pointer(&w), 1, &dup, 1); status != ErrOk {
 		// NB: Can't allocate here to provide status in panic.
 		panic("failed to write thread to channel")
 	}
 }
 
 // GetThreadsChannel returns a reference to a channel that will be enqueued with
-// a zero-byte single-handle message for every thread that the runtime creates.
+// a single-byte single-handle message for every thread that the runtime
+// creates. The single byte encodes the thread type. See runtime.ThreadType.
+//
 // Applications may read from this channel to retrieve handles to the runtime
 // threads.
 //