| package cgroups |
| |
| import ( |
| "bufio" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "path/filepath" |
| "strconv" |
| |
| specs "github.com/opencontainers/runtime-spec/specs-go" |
| ) |
| |
| func NewCpu(root string) *cpuController { |
| return &cpuController{ |
| root: filepath.Join(root, string(Cpu)), |
| } |
| } |
| |
| type cpuController struct { |
| root string |
| } |
| |
| func (c *cpuController) Name() Name { |
| return Cpu |
| } |
| |
| func (c *cpuController) Path(path string) string { |
| return filepath.Join(c.root, path) |
| } |
| |
| func (c *cpuController) Create(path string, resources *specs.LinuxResources) error { |
| if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil { |
| return err |
| } |
| if cpu := resources.CPU; cpu != nil { |
| for _, t := range []struct { |
| name string |
| ivalue *int64 |
| uvalue *uint64 |
| }{ |
| { |
| name: "rt_period_us", |
| uvalue: cpu.RealtimePeriod, |
| }, |
| { |
| name: "rt_runtime_us", |
| ivalue: cpu.RealtimeRuntime, |
| }, |
| { |
| name: "shares", |
| uvalue: cpu.Shares, |
| }, |
| { |
| name: "cfs_period_us", |
| uvalue: cpu.Period, |
| }, |
| { |
| name: "cfs_quota_us", |
| ivalue: cpu.Quota, |
| }, |
| } { |
| var value []byte |
| if t.uvalue != nil { |
| value = []byte(strconv.FormatUint(*t.uvalue, 10)) |
| } else if t.ivalue != nil { |
| value = []byte(strconv.FormatInt(*t.ivalue, 10)) |
| } |
| if value != nil { |
| if err := ioutil.WriteFile( |
| filepath.Join(c.Path(path), fmt.Sprintf("cpu.%s", t.name)), |
| value, |
| defaultFilePerm, |
| ); err != nil { |
| return err |
| } |
| } |
| } |
| } |
| return nil |
| } |
| |
| func (c *cpuController) Update(path string, resources *specs.LinuxResources) error { |
| return c.Create(path, resources) |
| } |
| |
| func (c *cpuController) Stat(path string, stats *Metrics) error { |
| f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat")) |
| if err != nil { |
| return err |
| } |
| defer f.Close() |
| // get or create the cpu field because cpuacct can also set values on this struct |
| sc := bufio.NewScanner(f) |
| for sc.Scan() { |
| if err := sc.Err(); err != nil { |
| return err |
| } |
| key, v, err := parseKV(sc.Text()) |
| if err != nil { |
| return err |
| } |
| switch key { |
| case "nr_periods": |
| stats.CPU.Throttling.Periods = v |
| case "nr_throttled": |
| stats.CPU.Throttling.ThrottledPeriods = v |
| case "throttled_time": |
| stats.CPU.Throttling.ThrottledTime = v |
| } |
| } |
| return nil |
| } |