diff --git a/cpu/cpu_darwin.go b/cpu/cpu_darwin.go index 4552947..4066b65 100644 --- a/cpu/cpu_darwin.go +++ b/cpu/cpu_darwin.go @@ -2,27 +2,10 @@ package cpu -/* -#include -#include -#include -#include -#include -#include -#include -#include -#include -*/ -import "C" - import ( - "bytes" - "encoding/binary" - "fmt" "os/exec" "strconv" "strings" - "unsafe" ) // sys/resource.h @@ -38,89 +21,6 @@ const ( // default value. from time.h var ClocksPerSec = float64(128) -// these CPU times for darwin is borrowed from influxdb/telegraf. - -func perCPUTimes() ([]CPUTimesStat, error) { - var ( - count C.mach_msg_type_number_t - cpuload *C.processor_cpu_load_info_data_t - ncpu C.natural_t - ) - - status := C.host_processor_info(C.host_t(C.mach_host_self()), - C.PROCESSOR_CPU_LOAD_INFO, - &ncpu, - (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), - &count) - - if status != C.KERN_SUCCESS { - return nil, fmt.Errorf("host_processor_info error=%d", status) - } - - // jump through some cgo casting hoops and ensure we properly free - // the memory that cpuload points to - target := C.vm_map_t(C.mach_task_self_) - address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) - defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) - - // the body of struct processor_cpu_load_info - // aka processor_cpu_load_info_data_t - var cpu_ticks [C.CPU_STATE_MAX]uint32 - - // copy the cpuload array to a []byte buffer - // where we can binary.Read the data - size := int(ncpu) * binary.Size(cpu_ticks) - buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size)) - - bbuf := bytes.NewBuffer(buf) - - var ret []CPUTimesStat - - for i := 0; i < int(ncpu); i++ { - err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) - if err != nil { - return nil, err - } - - c := CPUTimesStat{ - CPU: fmt.Sprintf("cpu%d", i), - User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, - System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, - Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, - Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, - } - - ret = append(ret, c) - } - - return ret, nil -} - -func allCPUTimes() ([]CPUTimesStat, error) { - var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT - var cpuload C.host_cpu_load_info_data_t - - status := C.host_statistics(C.host_t(C.mach_host_self()), - C.HOST_CPU_LOAD_INFO, - C.host_info_t(unsafe.Pointer(&cpuload)), - &count) - - if status != C.KERN_SUCCESS { - return nil, fmt.Errorf("host_statistics error=%d", status) - } - - c := CPUTimesStat{ - CPU: "cpu-total", - User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, - System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, - Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, - Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, - } - - return []CPUTimesStat{c}, nil - -} - func CPUTimes(percpu bool) ([]CPUTimesStat, error) { if percpu { return perCPUTimes() diff --git a/cpu/cpu_darwin_cgo.go b/cpu/cpu_darwin_cgo.go new file mode 100644 index 0000000..2973217 --- /dev/null +++ b/cpu/cpu_darwin_cgo.go @@ -0,0 +1,107 @@ +// +build darwin +// +build cgo + +package cpu + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +import "C" + +import ( + "bytes" + "encoding/binary" + "fmt" + "unsafe" +) + +// these CPU times for darwin is borrowed from influxdb/telegraf. + +func perCPUTimes() ([]CPUTimesStat, error) { + var ( + count C.mach_msg_type_number_t + cpuload *C.processor_cpu_load_info_data_t + ncpu C.natural_t + ) + + status := C.host_processor_info(C.host_t(C.mach_host_self()), + C.PROCESSOR_CPU_LOAD_INFO, + &ncpu, + (*C.processor_info_array_t)(unsafe.Pointer(&cpuload)), + &count) + + if status != C.KERN_SUCCESS { + return nil, fmt.Errorf("host_processor_info error=%d", status) + } + + // jump through some cgo casting hoops and ensure we properly free + // the memory that cpuload points to + target := C.vm_map_t(C.mach_task_self_) + address := C.vm_address_t(uintptr(unsafe.Pointer(cpuload))) + defer C.vm_deallocate(target, address, C.vm_size_t(ncpu)) + + // the body of struct processor_cpu_load_info + // aka processor_cpu_load_info_data_t + var cpu_ticks [C.CPU_STATE_MAX]uint32 + + // copy the cpuload array to a []byte buffer + // where we can binary.Read the data + size := int(ncpu) * binary.Size(cpu_ticks) + buf := C.GoBytes(unsafe.Pointer(cpuload), C.int(size)) + + bbuf := bytes.NewBuffer(buf) + + var ret []CPUTimesStat + + for i := 0; i < int(ncpu); i++ { + err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks) + if err != nil { + return nil, err + } + + c := CPUTimesStat{ + CPU: fmt.Sprintf("cpu%d", i), + User: float64(cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, + System: float64(cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, + Nice: float64(cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, + Idle: float64(cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, + } + + ret = append(ret, c) + } + + return ret, nil +} + +func allCPUTimes() ([]CPUTimesStat, error) { + var count C.mach_msg_type_number_t = C.HOST_CPU_LOAD_INFO_COUNT + var cpuload C.host_cpu_load_info_data_t + + status := C.host_statistics(C.host_t(C.mach_host_self()), + C.HOST_CPU_LOAD_INFO, + C.host_info_t(unsafe.Pointer(&cpuload)), + &count) + + if status != C.KERN_SUCCESS { + return nil, fmt.Errorf("host_statistics error=%d", status) + } + + c := CPUTimesStat{ + CPU: "cpu-total", + User: float64(cpuload.cpu_ticks[C.CPU_STATE_USER]) / ClocksPerSec, + System: float64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM]) / ClocksPerSec, + Nice: float64(cpuload.cpu_ticks[C.CPU_STATE_NICE]) / ClocksPerSec, + Idle: float64(cpuload.cpu_ticks[C.CPU_STATE_IDLE]) / ClocksPerSec, + } + + return []CPUTimesStat{c}, nil + +} diff --git a/cpu/cpu_darwin_nocgo.go b/cpu/cpu_darwin_nocgo.go new file mode 100644 index 0000000..ca54570 --- /dev/null +++ b/cpu/cpu_darwin_nocgo.go @@ -0,0 +1,14 @@ +// +build darwin +// +build !cgo + +package cpu + +import "github.com/shirou/gopsutil/common" + +func perCPUTimes() ([]CPUTimesStat, error) { + return []CPUTimesStat{}, common.NotImplementedError +} + +func allCPUTimes() ([]CPUTimesStat, error) { + return []CPUTimesStat{}, common.NotImplementedError +}