1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-26 13:48:59 +08:00

Use common implementation for BootTime/Uptime on all BSDs

All BSDs use the same implementation to get BootTime{,WithContext} and
Uptime{,WithContext} based on the kern.boottime sysctl. Move this
implementation to a separate host/host_bsd.go file shared by darwin,
freebsd and openbsd. Also use SysctlTimeval to get
the boot time directly as a type Timeval instead of manually
extracting it using package unsafe. It will also allow for easier reuse
to support package host on e.g. Dragonfly BSD or NetBSD.

This requires updating the golang.org/x/sys/unix dependency to the
latest revision.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
This commit is contained in:
Tobias Klauser 2020-07-23 13:12:59 +02:00
parent 10a398abdd
commit 28890b0482
5 changed files with 51 additions and 132 deletions

4
Gopkg.lock generated
View File

@ -49,7 +49,7 @@
[[projects]]
branch = "master"
digest = "1:c33af8636b2c5128b62b5bacd6fbdf6bf65a76e95b5b0111bfa134cb8ad5676d"
digest = "1:e7b553682850788c6b266faaf25218ce901558e541102d12b2998cad99f6b4fb"
name = "golang.org/x/sys"
packages = [
"internal/unsafeheader",
@ -59,7 +59,7 @@
"windows/svc/mgr",
]
pruneopts = "UT"
revision = "ed371f2e16b4b305ee99df548828de367527b76b"
revision = "76b94024e4b621e672466e8db3d7f084e7ddcad2"
[[projects]]
branch = "v3"

49
host/host_bsd.go Normal file
View File

@ -0,0 +1,49 @@
// +build darwin freebsd openbsd
package host
import (
"context"
"sync/atomic"
"time"
"golang.org/x/sys/unix"
)
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
tv, err := unix.SysctlTimeval("kern.boottime")
if err != nil {
return 0, err
}
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
return uint64(tv.Sec), nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTimeWithContext(ctx)
if err != nil {
return 0, err
}
return uptime(boot), nil
}

View File

@ -11,8 +11,6 @@ import (
"os/exec"
"runtime"
"strings"
"sync/atomic"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@ -80,48 +78,6 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
// https://github.com/AaronO/dashd/blob/222e32ef9f7a1f9bea4a8da2c3627c4cb992f860/probe/probe_darwin.go
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
value, err := unix.Sysctl("kern.boottime")
if err != nil {
return 0, err
}
bytes := []byte(value[:])
var boottime uint64
boottime = uint64(bytes[0]) + uint64(bytes[1])*256 + uint64(bytes[2])*256*256 + uint64(bytes[3])*256*256*256
atomic.StoreUint64(&cachedBootTime, boottime)
return boottime, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTimeWithContext(ctx)
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}

View File

@ -11,9 +11,6 @@ import (
"os"
"runtime"
"strings"
"sync/atomic"
"syscall"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@ -80,45 +77,6 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
buf, err := unix.SysctlRaw("kern.boottime")
if err != nil {
return 0, err
}
tv := *(*syscall.Timeval)(unsafe.Pointer((&buf[0])))
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
return t, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}

View File

@ -10,8 +10,6 @@ import (
"os"
"runtime"
"strings"
"sync/atomic"
"time"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
@ -71,48 +69,6 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
return ret, nil
}
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func BootTime() (uint64, error) {
return BootTimeWithContext(context.Background())
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
// https://github.com/AaronO/dashd/blob/222e32ef9f7a1f9bea4a8da2c3627c4cb992f860/probe/probe_darwin.go
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
value, err := unix.Sysctl("kern.boottime")
if err != nil {
return 0, err
}
bytes := []byte(value[:])
var boottime uint64
boottime = uint64(bytes[0]) + uint64(bytes[1])*256 + uint64(bytes[2])*256*256 + uint64(bytes[3])*256*256*256
atomic.StoreUint64(&cachedBootTime, boottime)
return boottime, nil
}
func uptime(boot uint64) uint64 {
return uint64(time.Now().Unix()) - boot
}
func Uptime() (uint64, error) {
return UptimeWithContext(context.Background())
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
boot, err := BootTime()
if err != nil {
return 0, err
}
return uptime(boot), nil
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}