runtime: use hw.ncpuonline sysctl in getncpu on netbsd

Since NetBSD 7, hw.ncpuonline reports the number of CPUs online, while
hw.cpu reports the number of CPUs configured. Try hw.cpuonline first and
fall back to hw.ncpu in case it fails (which is the case on NetBSD
before 7.0).

This follows the behavior on OpenBSD (see CL 161757). Also, Go
in pkgsrc is patched to use hw.cpuonline, so this CL would allow said
patch to be dropped.

Updates #30824

Change-Id: Id1c19dff2c1e4401e6074179fae7c708ba0e3098
Reviewed-on: https://go-review.googlesource.com/c/go/+/231957
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
index 97106c7..f7f90ce 100644
--- a/src/runtime/os_netbsd.go
+++ b/src/runtime/os_netbsd.go
@@ -95,18 +95,28 @@
 
 // From NetBSD's <sys/sysctl.h>
 const (
-	_CTL_HW      = 6
-	_HW_NCPU     = 3
-	_HW_PAGESIZE = 7
+	_CTL_HW        = 6
+	_HW_NCPU       = 3
+	_HW_PAGESIZE   = 7
+	_HW_NCPUONLINE = 16
 )
 
-func getncpu() int32 {
-	mib := [2]uint32{_CTL_HW, _HW_NCPU}
-	out := uint32(0)
+func sysctlInt(mib []uint32) (int32, bool) {
+	var out int32
 	nout := unsafe.Sizeof(out)
-	ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
-	if ret >= 0 {
-		return int32(out)
+	ret := sysctl(&mib[0], uint32(len(mib)), (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
+	if ret < 0 {
+		return 0, false
+	}
+	return out, true
+}
+
+func getncpu() int32 {
+	if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPUONLINE}); ok {
+		return int32(n)
+	}
+	if n, ok := sysctlInt([]uint32{_CTL_HW, _HW_NCPU}); ok {
+		return int32(n)
 	}
 	return 1
 }