summaryrefslogtreecommitdiff
path: root/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go')
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go129
1 files changed, 129 insertions, 0 deletions
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
new file mode 100644
index 000000000..6c79f899b
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu.go
@@ -0,0 +1,129 @@
+package fs
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
+ "github.com/opencontainers/runc/libcontainer/configs"
+ "golang.org/x/sys/unix"
+)
+
+type CpuGroup struct{}
+
+func (s *CpuGroup) Name() string {
+ return "cpu"
+}
+
+func (s *CpuGroup) Apply(path string, r *configs.Resources, pid int) error {
+ if err := os.MkdirAll(path, 0o755); err != nil {
+ return err
+ }
+ // We should set the real-Time group scheduling settings before moving
+ // in the process because if the process is already in SCHED_RR mode
+ // and no RT bandwidth is set, adding it will fail.
+ if err := s.SetRtSched(path, r); err != nil {
+ return err
+ }
+ // Since we are not using apply(), we need to place the pid
+ // into the procs file.
+ return cgroups.WriteCgroupProc(path, pid)
+}
+
+func (s *CpuGroup) SetRtSched(path string, r *configs.Resources) error {
+ if r.CpuRtPeriod != 0 {
+ if err := cgroups.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(r.CpuRtPeriod, 10)); err != nil {
+ return err
+ }
+ }
+ if r.CpuRtRuntime != 0 {
+ if err := cgroups.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(r.CpuRtRuntime, 10)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (s *CpuGroup) Set(path string, r *configs.Resources) error {
+ if r.CpuShares != 0 {
+ shares := r.CpuShares
+ if err := cgroups.WriteFile(path, "cpu.shares", strconv.FormatUint(shares, 10)); err != nil {
+ return err
+ }
+ // read it back
+ sharesRead, err := fscommon.GetCgroupParamUint(path, "cpu.shares")
+ if err != nil {
+ return err
+ }
+ // ... and check
+ if shares > sharesRead {
+ return fmt.Errorf("the maximum allowed cpu-shares is %d", sharesRead)
+ } else if shares < sharesRead {
+ return fmt.Errorf("the minimum allowed cpu-shares is %d", sharesRead)
+ }
+ }
+
+ var period string
+ if r.CpuPeriod != 0 {
+ period = strconv.FormatUint(r.CpuPeriod, 10)
+ if err := cgroups.WriteFile(path, "cpu.cfs_period_us", period); err != nil {
+ // Sometimes when the period to be set is smaller
+ // than the current one, it is rejected by the kernel
+ // (EINVAL) as old_quota/new_period exceeds the parent
+ // cgroup quota limit. If this happens and the quota is
+ // going to be set, ignore the error for now and retry
+ // after setting the quota.
+ if !errors.Is(err, unix.EINVAL) || r.CpuQuota == 0 {
+ return err
+ }
+ } else {
+ period = ""
+ }
+ }
+ if r.CpuQuota != 0 {
+ if err := cgroups.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(r.CpuQuota, 10)); err != nil {
+ return err
+ }
+ if period != "" {
+ if err := cgroups.WriteFile(path, "cpu.cfs_period_us", period); err != nil {
+ return err
+ }
+ }
+ }
+ return s.SetRtSched(path, r)
+}
+
+func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
+ const file = "cpu.stat"
+ f, err := cgroups.OpenFile(path, file, os.O_RDONLY)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ }
+ return err
+ }
+ defer f.Close()
+
+ sc := bufio.NewScanner(f)
+ for sc.Scan() {
+ t, v, err := fscommon.ParseKeyValue(sc.Text())
+ if err != nil {
+ return &parseError{Path: path, File: file, Err: err}
+ }
+ switch t {
+ case "nr_periods":
+ stats.CpuStats.ThrottlingData.Periods = v
+
+ case "nr_throttled":
+ stats.CpuStats.ThrottlingData.ThrottledPeriods = v
+
+ case "throttled_time":
+ stats.CpuStats.ThrottlingData.ThrottledTime = v
+ }
+ }
+ return nil
+}