unix: add SysctlTimeval on *bsd and darwin

Change-Id: I18daa353d101e6636a732288c8276d9f68d25f90
Reviewed-on: https://go-review.googlesource.com/c/sys/+/244237
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matt Layher <mdlayher@gmail.com>
diff --git a/unix/syscall_bsd.go b/unix/syscall_bsd.go
index 68605db..60bbe10 100644
--- a/unix/syscall_bsd.go
+++ b/unix/syscall_bsd.go
@@ -527,6 +527,23 @@
 	return &ci, nil
 }
 
+func SysctlTimeval(name string) (*Timeval, error) {
+	mib, err := sysctlmib(name)
+	if err != nil {
+		return nil, err
+	}
+
+	var tv Timeval
+	n := uintptr(unsafe.Sizeof(tv))
+	if err := sysctl(mib, (*byte)(unsafe.Pointer(&tv)), &n, nil, 0); err != nil {
+		return nil, err
+	}
+	if n != unsafe.Sizeof(tv) {
+		return nil, EIO
+	}
+	return &tv, nil
+}
+
 //sys	utimes(path string, timeval *[2]Timeval) (err error)
 
 func Utimes(path string, tv []Timeval) error {
diff --git a/unix/syscall_bsd_test.go b/unix/syscall_bsd_test.go
index f8ec9d1..81937fb 100644
--- a/unix/syscall_bsd_test.go
+++ b/unix/syscall_bsd_test.go
@@ -10,6 +10,7 @@
 	"os/exec"
 	"runtime"
 	"testing"
+	"time"
 
 	"golang.org/x/sys/unix"
 )
@@ -73,3 +74,11 @@
 	t.Logf("tick = %v, hz = %v, profhz = %v, stathz = %v",
 		ci.Tick, ci.Hz, ci.Profhz, ci.Stathz)
 }
+
+func TestSysctlTimeval(t *testing.T) {
+	tv, err := unix.SysctlTimeval("kern.boottime")
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Logf("boottime = %v", time.Unix(tv.Unix()))
+}