// +build linux package cpu import ( "bufio" "fmt" "io" "os" "path" "strconv" "strings" ) const cgroupRootDir = "/sys/fs/cgroup" // cgroup Linux cgroup type cgroup struct { cgroupSet map[string]string } // CPUCFSQuotaUs cpu.cfs_quota_us func (c *cgroup) CPUCFSQuotaUs() (int64, error) { data, err := readFile(path.Join(c.cgroupSet["cpu"], "cpu.cfs_quota_us")) if err != nil { return 0, err } return strconv.ParseInt(data, 10, 64) } // CPUCFSPeriodUs cpu.cfs_period_us func (c *cgroup) CPUCFSPeriodUs() (uint64, error) { data, err := readFile(path.Join(c.cgroupSet["cpu"], "cpu.cfs_period_us")) if err != nil { return 0, err } return parseUint(data) } // CPUAcctUsage cpuacct.usage func (c *cgroup) CPUAcctUsage() (uint64, error) { data, err := readFile(path.Join(c.cgroupSet["cpuacct"], "cpuacct.usage")) if err != nil { return 0, err } return parseUint(data) } // CPUAcctUsagePerCPU cpuacct.usage_percpu func (c *cgroup) CPUAcctUsagePerCPU() ([]uint64, error) { data, err := readFile(path.Join(c.cgroupSet["cpuacct"], "cpuacct.usage_percpu")) if err != nil { return nil, err } var usage []uint64 for _, v := range strings.Fields(string(data)) { var u uint64 if u, err = parseUint(v); err != nil { return nil, err } usage = append(usage, u) } return usage, nil } // CPUSetCPUs cpuset.cpus func (c *cgroup) CPUSetCPUs() ([]uint64, error) { data, err := readFile(path.Join(c.cgroupSet["cpuset"], "cpuset.cpus")) if err != nil { return nil, err } cpus, err := ParseUintList(data) if err != nil { return nil, err } var sets []uint64 for k := range cpus { sets = append(sets, uint64(k)) } return sets, nil } // CurrentcGroup get current process cgroup func currentcGroup() (*cgroup, error) { pid := os.Getpid() cgroupFile := fmt.Sprintf("/proc/%d/cgroup", pid) cgroupSet := make(map[string]string) fp, err := os.Open(cgroupFile) if err != nil { return nil, err } defer fp.Close() buf := bufio.NewReader(fp) for { line, err := buf.ReadString('\n') if err != nil { if err == io.EOF { break } return nil, err } col := strings.Split(strings.TrimSpace(line), ":") if len(col) != 3 { return nil, fmt.Errorf("invalid cgroup format %s", line) } dir := col[2] // When dir is not equal to /, it must be in docker if dir != "/" { cgroupSet[col[1]] = path.Join(cgroupRootDir, col[1]) if strings.Contains(col[1], ",") { for _, k := range strings.Split(col[1], ",") { cgroupSet[k] = path.Join(cgroupRootDir, k) } } } else { cgroupSet[col[1]] = path.Join(cgroupRootDir, col[1], col[2]) if strings.Contains(col[1], ",") { for _, k := range strings.Split(col[1], ",") { cgroupSet[k] = path.Join(cgroupRootDir, k, col[2]) } } } } return &cgroup{cgroupSet: cgroupSet}, nil }