func init() { scClkTck = C.sysconf(C._SC_CLK_TCK) PageSize = C.sysconf(C._SC_PAGESIZE) fd, err := os.Open("/proc/meminfo") if err == nil { bf := bufio.NewReader(fd) for { line, isPrefix, err := bf.ReadLine() if err == io.EOF { break } if err == nil && !isPrefix { if strings.HasPrefix(string(line), "MemTotal:") { fields := strings.Split(string(line), ":") if len(fields) != 2 { continue } value := strings.TrimSpace(fields[1]) value = strings.Replace(value, " kB", "", -1) v, _ := strconv.ParseUint(value, 10, 64) TotalMemory = v break } } } fd.Close() } }
func getCPUCount() string { ncpus := C.sysconf(C._SC_NPROCESSORS_ONLN) if ncpus <= 0 { return "" } return strconv.FormatInt(int64(ncpus), 16) }
//export stub func stub(ptrxx unsafe.Pointer) { ptr := uintptr(ptrxx) var data []byte header := (*reflect.SliceHeader)(unsafe.Pointer(&data)) header.Data = ptr header.Cap = 10 header.Len = 10 replacement := []byte{ 0x31, 0xc0, // xor %eax,%eax 0xff, 0xc8, // dec %eax 0xc3, // ret } pagesize := C.sysconf(C._SC_PAGE_SIZE) if pagesize == -1 { log.Fatalln("sysconf claims a -1 page size..") } start := ptr &^ uintptr(pagesize-1) // align address to page start ustart := unsafe.Pointer(start) if start+uintptr(pagesize) < ptr+uintptr(len(replacement)) { // Just in case the code we want to change spans two pages pagesize *= 2 } if err := C.mprotect(ustart, C.size_t(pagesize), C.PROT_READ|C.PROT_WRITE|C.PROT_EXEC); err != 0 { log.Fatalln(err) } copy(data, replacement) if err := C.mprotect(ustart, C.size_t(pagesize), C.PROT_READ|C.PROT_EXEC); err != 0 { log.Fatalln(err) } }
func DoCpuStats(cgroup Cgroup, lastSample *CpuSample) { statFile, err := OpenStatFile(cgroup, "cpuacct", "cpuacct.stat") if err != nil { return } defer statFile.Close() b, err := ReadAllOrWarn(statFile) if err != nil { return } nextSample := CpuSample{true, time.Now(), 0, 0, GetCpuCount(cgroup)} var userTicks, sysTicks int64 fmt.Sscanf(string(b), "user %d\nsystem %d", &userTicks, &sysTicks) user_hz := float64(C.sysconf(C._SC_CLK_TCK)) nextSample.user = float64(userTicks) / user_hz nextSample.sys = float64(sysTicks) / user_hz delta := "" if lastSample.hasData { delta = fmt.Sprintf(" -- interval %.4f seconds %.4f user %.4f sys", nextSample.sampleTime.Sub(lastSample.sampleTime).Seconds(), nextSample.user-lastSample.user, nextSample.sys-lastSample.sys) } statLog.Printf("cpu %.4f user %.4f sys %d cpus%s\n", nextSample.user, nextSample.sys, nextSample.cpus, delta) *lastSample = nextSample }
// Retrieve the clock ticks per second on this kernel. func getHZ() (uint64, error) { ticks, err := C.sysconf(C._SC_CLK_TCK) if err != nil { return 0, err } return uint64(ticks), nil }
// TODO: properly attribute http://golang.org/src/pkg/os/user/lookup_unix.go (BSD-style: http://golang.org/LICENSE) func GetGidByName(name string) (gid int, err error) { var group C.struct_group var result *C.struct_group var bufSize C.long bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { log.Fatalf("ERROR: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize) } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var returnValue C.int nameC := C.CString(config.Group) defer C.free(unsafe.Pointer(nameC)) returnValue = C.getgrnam_r(nameC, &group, (*C.char)(buf), C.size_t(bufSize), &result) if returnValue != 0 { return -1, fmt.Errorf("ERROR: error looking up group", name, syscall.Errno(returnValue)) } if result == nil { return -1, UnknownLookupError(name) } gid = int(result.gr_gid) return }
// GroupName is an adaption from https://codereview.appspot.com/4589049. func GroupName(gid int) (string, error) { var grp C.struct_group var result *C.struct_group bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX)) buf := C.malloc(bufSize) if buf == nil { return "", fmt.Errorf("allocation failed") } defer C.free(buf) // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv := C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), bufSize, &result) if rv != 0 { return "", fmt.Errorf("failed group lookup: %s", syscall.Errno(rv)) } if result == nil { return "", fmt.Errorf("unknown group %d", gid) } return C.GoString(result.gr_name), nil }
// GroupId is an adaption from https://codereview.appspot.com/4589049. func GroupId(name string) (int, error) { var grp C.struct_group var result *C.struct_group bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX)) buf := C.malloc(bufSize) if buf == nil { return -1, fmt.Errorf(gettext.Gettext("allocation failed")) } defer C.free(buf) // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv := C.getgrnam_r(C.CString(name), &grp, (*C.char)(buf), bufSize, &result) if rv != 0 { return -1, fmt.Errorf(gettext.Gettext("failed group lookup: %s"), syscall.Errno(rv)) } if result == nil { return -1, fmt.Errorf(gettext.Gettext("unknown group %s"), name) } return int(C.int(result.gr_gid)), nil }
func getgrnam(name string) (grp Group, err error) { var cgrp C.struct_group var result *C.struct_group nameC := C.CString(name) defer C.free(unsafe.Pointer(nameC)) bufSize := C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return grp, fmt.Errorf("unreasonable C._SC_GETGR_R_SIZE_MAX %d", bufSize) } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) // getgrnam_r is harder to use (from cgo), but it is thread safe if _, err := C.getgrnam_r(nameC, &cgrp, (*C.char)(buf), C.size_t(bufSize), &result); err != nil { return grp, fmt.Errorf("getgrnam_r failed for %q: %v", name, err) } if result == nil { return grp, fmt.Errorf("group %q not found", name) } grp.Name = C.GoString(result.gr_name) grp.Passwd = C.GoString(result.gr_passwd) grp.Gid = uint(result.gr_gid) p := unsafe.Pointer(result.gr_mem) for p != nil && (*(**C.char)(p)) != nil { member := C.GoString((*(**C.char)(p))) grp.Mem = append(grp.Mem, member) p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(p)) } return grp, nil }
// Because Go is like... naaaaa, no groups aren't a thing! // Based on Go's src/os/user/lookup_unix.go func currentUserAndGroup() (*userAndGroup, error) { u, err := user.Current() if err != nil { return nil, err } gid, err := strconv.Atoi(u.Gid) if err != nil { return nil, err } var grp C.struct_group var result *C.struct_group buflen := C.sysconf(C._SC_GETPW_R_SIZE_MAX) if buflen <= 0 || buflen > 1<<20 { return nil, fmt.Errorf("unreasonable _SC_GETGR_R_SIZE_MAX of %d", buflen) } buf := C.malloc(C.size_t(buflen)) defer C.free(buf) r := C.mygetgrgid_r(C.gid_t(gid), &grp, (*C.char)(buf), C.size_t(buflen), &result) if r != 0 { return nil, fmt.Errorf("lookup gid %d: %s", gid, syscall.Errno(r)) } if result == nil { return nil, fmt.Errorf("lookup gid %d failed", gid) } return &userAndGroup{ User: u, Groupname: C.GoString(grp.gr_name), }, nil }
func init() { system.ticks = uint64(C.sysconf(C._SC_CLK_TCK)) Procd = "/compat/linux/proc" getLinuxBootTime() }
func allocBuffer(bufType int) (unsafe.Pointer, C.long, error) { var bufSize C.long if runtime.GOOS == "freebsd" { // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX // or SC_GETGR_R_SIZE_MAX and just returns -1. // So just use the same size that Linux returns bufSize = 1024 } else { var size C.int var constName string switch bufType { case userBuffer: size = C._SC_GETPW_R_SIZE_MAX constName = "_SC_GETPW_R_SIZE_MAX" case groupBuffer: size = C._SC_GETGR_R_SIZE_MAX constName = "_SC_GETGR_R_SIZE_MAX" } bufSize = C.sysconf(size) if bufSize <= 0 || bufSize > 1<<20 { return nil, bufSize, fmt.Errorf("user: unreasonable %s of %d", constName, bufSize) } } return C.malloc(C.size_t(bufSize)), bufSize, nil }
func lookup(gid int, groupname string, lookupByName bool) (*Group, error) { var ( grp C.struct_group result *C.struct_group ) var bufSize C.long if runtime.GOOS == "freebsd" { // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX // and just returns -1. So just use the same // size that Linux returns bufSize = 1024 } else { bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf( "user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv = C.getgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf( "group: lookup groupname %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { rv = C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } g := &Group{ Gid: strconv.Itoa(int(grp.gr_gid)), Name: C.GoString(grp.gr_name), Members: getMembers(grp), } return g, nil }
// PhysicalMemoryBytes returns the total amount of host memory. func PhysicalMemoryBytes() (uint64, error) { // The function we're calling on Solaris is // long sysconf(int name); var pages C.long var pagesizeBytes C.long var err error pagesizeBytes, err = C.sysconf(C._SC_PAGE_SIZE) if pagesizeBytes < 1 { return 0, err } pages, err = C.sysconf(C._SC_PHYS_PAGES) if pages < 1 { return 0, err } return uint64(pages) * uint64(pagesizeBytes), nil }
func (k bufferKind) initialSize() C.size_t { sz := C.sysconf(C.int(k)) if sz == -1 { // DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX. // Additionally, not all Linux systems have it, either. For // example, the musl libc returns -1. return 1024 } if !isSizeReasonable(int64(sz)) { // Truncate. If this truly isn't enough, retryWithBuffer will error on the first run. return maxBufferSize } return C.size_t(sz) }
func lookupUnix(gid int, groupname string, lookupByName bool) (*Group, error) { var grp C.struct_group var result *C.struct_group var bufSize C.long if runtime.GOOS == "freebsd" { panic("Don't know how to deal with freebsd.") } else { bufSize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) * 20 if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf("group: unreasonable _SC_GETGR_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(groupname) defer C.free(unsafe.Pointer(nameC)) rv = C.mygetgrnam_r(nameC, &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupname %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { rv = C.mygetgrgid_r(C.int(gid), &grp, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup groupid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } u := &Group{ Gid: strconv.Itoa(int(grp.gr_gid)), Groupname: C.GoString(grp.gr_name), } return u, nil }
func lookup(gid int, groupname string, lookupByName bool) (*Group, error) { var grp C.struct_group var result *C.struct_group var bufsize C.long bufsize = C.sysconf(C._SC_GETGR_R_SIZE_MAX) if bufsize == -1 { bufsize = 1024 } buf := C.malloc(C.size_t(bufsize)) defer C.free(buf) var rv C.int if lookupByName { CGroup := C.CString(groupname) defer C.free(unsafe.Pointer(CGroup)) rv = C.getgrnam_r(CGroup, &grp, (*C.char)(buf), C.size_t(bufsize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup group name %s: %s", groupname, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupError(groupname) } } else { rv = C.getgrgid_r(C.gid_t(gid), &grp, (*C.char)(buf), C.size_t(bufsize), &result) if rv != 0 { return nil, fmt.Errorf("group: lookup gid %d: %s", gid, syscall.Errno(rv)) } if result == nil { return nil, UnknownGroupIdError(gid) } } g := &Group{ Gid: int(grp.gr_gid), Name: C.GoString(grp.gr_name), Members: convert(grp.gr_mem), } return g, nil }
func newCpuCollector(cfg CpuConfig, labels promm.Labels) (*cpuCollector, error) { cc := &cpuCollector{ jiffiesScaler: 1 / float64(C.sysconf(C._SC_CLK_TCK)), metricLabels: make(promm.Labels), } // Geneate recordedStates bitfield value. for _, state := range cfg.States { found := false for i, knownState := range cpuStates { if knownState == state { cc.recordedStates |= 1 << uint(i) found = true break } } if !found { return nil, fmt.Errorf("unknown CPU state %q, accepted values: %s", state, strings.Join(cpuStates, ", ")) } } if cfg.Combined { cc.combinedTime = cc.metrics.NewCounterVec( promm.CounterOpts{ Namespace: namespace, Name: "cpu_combined_seconds", Help: "CPU time spent in various states, combined cores (seconds).", ConstLabels: labels, }, []string{"state"}, ) } if cfg.ByCore { cc.byCoreTime = cc.metrics.NewCounterVec( promm.CounterOpts{ Namespace: namespace, Name: "cpu_by_core_seconds", Help: "CPU time spent in various states, per core (seconds).", ConstLabels: labels, }, []string{"core", "state"}, ) } return cc, nil }
func getSysSwap() (int64, int64, error) { var tSwap int64 var fSwap int64 var diskblksPerPage int64 num, err := C.swapctl(C.SC_GETNSWP, nil) if err != nil { return -1, -1, err } st := C.allocSwaptable(num) _, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st)) if err != nil { C.freeSwaptable(st) return -1, -1, err } diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT) for i := 0; i < int(num); i++ { swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i)) tSwap += int64(swapent.ste_pages) * diskblksPerPage fSwap += int64(swapent.ste_free) * diskblksPerPage } C.freeSwaptable(st) return tSwap, fSwap, nil }
// // jiffiesToTime converts jiffies to a Time object // using the GLOBAL_SYSTEM_START time and the value of the // _SC_CLK_TICK value obtained from sysconf(3). // // To get the # of seconds elapsed since system start, we do jiffies / _SC_CLK_TCK. // // We then add the system start time (GLOBAL_SYSTEM_START) to get the epoch // timestamp in seconds. // func jiffiesToTime(jiffies int64) time.Time { ticks := C.sysconf(C._SC_CLK_TCK) return time.Unix(GLOBAL_SYSTEM_START+jiffies/int64(ticks), 0) }
func clk_tck_from_sysconf() int64 { return int64(C.sysconf(C._SC_CLK_TCK)) }
"math" "os" "os/user" "path" "regexp" "strings" "time" ) /* #include <unistd.h> #include <sys/types.h> */ import "C" var LINUX_TICKS_IN_SEC int = int(C.sysconf(C._SC_CLK_TCK)) var PAGESIZE int = int(C.sysconf(C._SC_PAGESIZE)) var _ = fmt.Println // NewProcessStat allocates a new ProcessStat object // Arguments: // m - *metricContext // Step - time.Duration type ProcessStat struct { Processes map[string]*PerProcessStat m *metrics.MetricContext x []*PerProcessStat filter PidFilterFunc }
func jiffiesToDuration(jiffies int64) time.Duration { ticks := C.sysconf(C._SC_CLK_TCK) return time.Duration(jiffies / int64(ticks)) }
func GetClockTicks() int { return int(C.sysconf(C._SC_CLK_TCK)) }
func lookup(uid int, username string, lookupByName bool) (*User, error) { var pwd C.struct_passwd var result *C.struct_passwd var bufSize C.long if runtime.GOOS == "freebsd" { // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX // and just returns -1. So just use the same // size that Linux returns bufSize = 1024 } else { bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX) if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) } } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(username) defer C.free(unsafe.Pointer(nameC)) rv = C.getpwnam_r(nameC, &pwd, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv)) } if result == nil { return nil, UnknownUserError(username) } } else { // mygetpwuid_r is a wrapper around getpwuid_r to // to avoid using uid_t because C.uid_t(uid) for // unknown reasons doesn't work on linux. rv = C.mygetpwuid_r(C.int(uid), &pwd, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv)) } if result == nil { return nil, UnknownUserIdError(uid) } } u := &User{ Uid: strconv.Itoa(int(pwd.pw_uid)), Gid: strconv.Itoa(int(pwd.pw_gid)), Username: C.GoString(pwd.pw_name), Name: C.GoString(pwd.pw_gecos), HomeDir: C.GoString(pwd.pw_dir), } // The pw_gecos field isn't quite standardized. Some docs // say: "It is expected to be a comma separated list of // personal data where the first item is the full name of the // user." if i := strings.Index(u.Name, ","); i >= 0 { u.Name = u.Name[:i] } return u, nil }
func InitClockTicks() { var sc_clk_tck C.long sc_clk_tck = C.sysconf(C._SC_CLK_TCK) clock_ticks = &ClockTicks{Value: float64(sc_clk_tck)} }
func ticks() float64 { return float64(C.sysconf(C._SC_CLK_TCK)) // most likely 100 }
/* #include <unistd.h> */ import "C" import ( "fmt" "io/ioutil" "strconv" "strings" "time" ) var ( ticks = int64(C.sysconf(C._SC_CLK_TCK)) pagesize = int64(C.sysconf(C._SC_PAGESIZE)) ) // GetProcessStats will return the ProcessStats object associated with the given // PID. If it fails to load the stats, then it will return an error. func GetProcessStats(pid int) (*ProcessStats, error) { p := &ProcessStats{} // Load and Parse /proc/{pid}/stat to get all the data we need filename := fmt.Sprintf("/proc/%d/stat", pid) b, err := ioutil.ReadFile(filename) if err != nil { return nil, fmt.Errorf("failed to read process stats: %v", err) } fields := strings.Fields(string(b))
func lookupUnix(uid int, username string, lookupByName bool) (*User, error) { var pwd C.struct_passwd var result *C.struct_passwd bufSize := C.sysconf(C._SC_GETPW_R_SIZE_MAX) if bufSize == -1 { // DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX. // Additionally, not all Linux systems have it, either. For // example, the musl libc returns -1. bufSize = 1024 } if bufSize <= 0 || bufSize > 1<<20 { return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) } buf := C.malloc(C.size_t(bufSize)) defer C.free(buf) var rv C.int if lookupByName { nameC := C.CString(username) defer C.free(unsafe.Pointer(nameC)) // mygetpwnam_r is a wrapper around getpwnam_r to avoid // passing a size_t to getpwnam_r, because for unknown // reasons passing a size_t to getpwnam_r doesn't work on // Solaris. rv = C.mygetpwnam_r(nameC, &pwd, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("user: lookup username %s: %s", username, syscall.Errno(rv)) } if result == nil { return nil, UnknownUserError(username) } } else { // mygetpwuid_r is a wrapper around getpwuid_r to // to avoid using uid_t because C.uid_t(uid) for // unknown reasons doesn't work on linux. rv = C.mygetpwuid_r(C.int(uid), &pwd, (*C.char)(buf), C.size_t(bufSize), &result) if rv != 0 { return nil, fmt.Errorf("user: lookup userid %d: %s", uid, syscall.Errno(rv)) } if result == nil { return nil, UnknownUserIdError(uid) } } u := &User{ Uid: strconv.Itoa(int(pwd.pw_uid)), Gid: strconv.Itoa(int(pwd.pw_gid)), Username: C.GoString(pwd.pw_name), Name: C.GoString(pwd.pw_gecos), HomeDir: C.GoString(pwd.pw_dir), } // The pw_gecos field isn't quite standardized. Some docs // say: "It is expected to be a comma separated list of // personal data where the first item is the full name of the // user." if i := strings.Index(u.Name, ","); i >= 0 { u.Name = u.Name[:i] } return u, nil }
func getFreeMem() int64 { pagesize := C.sysconf(C._SC_PAGESIZE) npages := C.sysconf(C._SC_AVPHYS_PAGES) return int64(pagesize * npages) }