Skip to content
Browse files

Add Cpu and CpuList APIs

Change-Id: I174050d5285233dd2a342c24d4cd6e049d68dba6
  • Loading branch information...
1 parent ffca5cf commit 9d112dd8729f9bfa229a39f62f47bd8d863cbfdc @dougm dougm committed Aug 9, 2012
Showing with 165 additions and 0 deletions.
  1. +20 −0 sigar.go
  2. +76 −0 sigar_darwin.go
  3. +46 −0 sigar_linux.go
  4. +23 −0 sigar_test.go
View
20 sigar.go
@@ -24,6 +24,26 @@ type Swap struct {
Free uint64
}
+type Cpu struct {
+ User uint64
+ Nice uint64
+ Sys uint64
+ Idle uint64
+ Wait uint64
+ Irq uint64
+ SoftIrq uint64
+ Stolen uint64
+}
+
+func (self *Cpu) Total() uint64 {
+ return self.User + self.Nice + self.Sys + self.Idle +
+ self.Wait + self.Irq + self.SoftIrq + self.Stolen
+}
+
+type CpuList struct {
+ List []Cpu
+}
+
type FileSystem struct {
DirName string
DevName string
View
76 sigar_darwin.go
@@ -10,6 +10,8 @@ package sigar
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <libproc.h>
+#include <mach/processor_info.h>
+#include <mach/vm_map.h>
*/
import "C"
@@ -86,6 +88,80 @@ func (self *Swap) Get() error {
return nil
}
+func (self *Cpu) Get() 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 fmt.Errorf("host_statistics error=%d", status)
+ }
+
+ self.User = uint64(cpuload.cpu_ticks[C.CPU_STATE_USER])
+ self.Sys = uint64(cpuload.cpu_ticks[C.CPU_STATE_SYSTEM])
+ self.Idle = uint64(cpuload.cpu_ticks[C.CPU_STATE_IDLE])
+ self.Nice = uint64(cpuload.cpu_ticks[C.CPU_STATE_NICE])
+
+ return nil
+}
+
+func (self *CpuList) Get() error {
+ var count C.mach_msg_type_number_t
+ var cpuload *C.processor_cpu_load_info_data_t
+ var 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 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)
+
+ self.List = make([]Cpu, 0, ncpu)
+
+ for i := 0; i < int(ncpu); i++ {
+ cpu := Cpu{}
+
+ err := binary.Read(bbuf, binary.LittleEndian, &cpu_ticks)
+ if err != nil {
+ return err
+ }
+
+ cpu.User = uint64(cpu_ticks[C.CPU_STATE_USER])
+ cpu.Sys = uint64(cpu_ticks[C.CPU_STATE_SYSTEM])
+ cpu.Idle = uint64(cpu_ticks[C.CPU_STATE_IDLE])
+ cpu.Nice = uint64(cpu_ticks[C.CPU_STATE_NICE])
+
+ self.List = append(self.List, cpu)
+ }
+
+ return nil
+}
+
func (self *FileSystemList) Get() error {
num, err := getfsstat(nil, C.MNT_NOWAIT)
if num < 0 {
View
46 sigar_linux.go
@@ -95,6 +95,37 @@ func (self *Swap) Get() error {
return nil
}
+func (self *Cpu) Get() error {
+ return readFile(procd+"stat", func(line string) bool {
+ if line[0:4] == "cpu " {
+ parseCpuStat(self, line)
+ return false
+ }
+ return true
+ })
+}
+
+func (self *CpuList) Get() error {
+ capacity := len(self.List)
+ if capacity == 0 {
+ capacity = 4
+ }
+ list := make([]Cpu, 0, capacity)
+
+ err := readFile(procd+"stat", func(line string) bool {
+ if line[0:3] == "cpu" && line[3] != ' ' {
+ cpu := Cpu{}
+ parseCpuStat(&cpu, line)
+ list = append(list, cpu)
+ }
+ return true
+ })
+
+ self.List = list
+
+ return err
+}
+
func (self *FileSystemList) Get() error {
capacity := len(self.List)
if capacity == 0 {
@@ -272,6 +303,21 @@ func parseMeminfo(table map[string]*uint64) error {
})
}
+func parseCpuStat(self *Cpu, line string) error {
+ fields := strings.Fields(line)
+
+ self.User, _ = strtoull(fields[1])
+ self.Nice, _ = strtoull(fields[2])
+ self.Sys, _ = strtoull(fields[3])
+ self.Idle, _ = strtoull(fields[4])
+ self.Wait, _ = strtoull(fields[5])
+ self.Irq, _ = strtoull(fields[6])
+ self.SoftIrq, _ = strtoull(fields[7])
+ self.Stolen, _ = strtoull(fields[8])
+
+ return nil
+}
+
func readFile(file string, handler func(string) bool) error {
contents, err := ioutil.ReadFile(file)
if err != nil {
View
23 sigar_test.go
@@ -4,6 +4,7 @@ package sigar
import (
"os"
+ "runtime"
"testing"
)
@@ -52,6 +53,28 @@ func TestSwap(t *testing.T) {
}
}
+func TestCpu(t *testing.T) {
+ cpu := Cpu{}
+ err := cpu.Get()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestCpuList(t *testing.T) {
+ cpulist := CpuList{}
+ err := cpulist.Get()
+ if err != nil {
+ t.Error(err)
+ }
+ nsigar := len(cpulist.List)
+ numcpu := runtime.NumCPU()
+ if nsigar != numcpu {
+ t.Errorf("CpuList num mismatch: sigar=%d, runtime=%d",
+ nsigar, numcpu)
+ }
+}
+
func TestFileSystemList(t *testing.T) {
fslist := FileSystemList{}
err := fslist.Get()

0 comments on commit 9d112dd

Please sign in to comment.
Something went wrong with that request. Please try again.