cpu.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package cgroups
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. specs "github.com/opencontainers/runtime-spec/specs-go"
  10. )
  11. func NewCpu(root string) *cpuController {
  12. return &cpuController{
  13. root: filepath.Join(root, string(Cpu)),
  14. }
  15. }
  16. type cpuController struct {
  17. root string
  18. }
  19. func (c *cpuController) Name() Name {
  20. return Cpu
  21. }
  22. func (c *cpuController) Path(path string) string {
  23. return filepath.Join(c.root, path)
  24. }
  25. func (c *cpuController) Create(path string, resources *specs.LinuxResources) error {
  26. if err := os.MkdirAll(c.Path(path), defaultDirPerm); err != nil {
  27. return err
  28. }
  29. if cpu := resources.CPU; cpu != nil {
  30. for _, t := range []struct {
  31. name string
  32. ivalue *int64
  33. uvalue *uint64
  34. }{
  35. {
  36. name: "rt_period_us",
  37. uvalue: cpu.RealtimePeriod,
  38. },
  39. {
  40. name: "rt_runtime_us",
  41. ivalue: cpu.RealtimeRuntime,
  42. },
  43. {
  44. name: "shares",
  45. uvalue: cpu.Shares,
  46. },
  47. {
  48. name: "cfs_period_us",
  49. uvalue: cpu.Period,
  50. },
  51. {
  52. name: "cfs_quota_us",
  53. ivalue: cpu.Quota,
  54. },
  55. } {
  56. var value []byte
  57. if t.uvalue != nil {
  58. value = []byte(strconv.FormatUint(*t.uvalue, 10))
  59. } else if t.ivalue != nil {
  60. value = []byte(strconv.FormatInt(*t.ivalue, 10))
  61. }
  62. if value != nil {
  63. if err := ioutil.WriteFile(
  64. filepath.Join(c.Path(path), fmt.Sprintf("cpu.%s", t.name)),
  65. value,
  66. defaultFilePerm,
  67. ); err != nil {
  68. return err
  69. }
  70. }
  71. }
  72. }
  73. return nil
  74. }
  75. func (c *cpuController) Update(path string, resources *specs.LinuxResources) error {
  76. return c.Create(path, resources)
  77. }
  78. func (c *cpuController) Stat(path string, stats *Metrics) error {
  79. f, err := os.Open(filepath.Join(c.Path(path), "cpu.stat"))
  80. if err != nil {
  81. return err
  82. }
  83. defer f.Close()
  84. // get or create the cpu field because cpuacct can also set values on this struct
  85. sc := bufio.NewScanner(f)
  86. for sc.Scan() {
  87. if err := sc.Err(); err != nil {
  88. return err
  89. }
  90. key, v, err := parseKV(sc.Text())
  91. if err != nil {
  92. return err
  93. }
  94. switch key {
  95. case "nr_periods":
  96. stats.CPU.Throttling.Periods = v
  97. case "nr_throttled":
  98. stats.CPU.Throttling.ThrottledPeriods = v
  99. case "throttled_time":
  100. stats.CPU.Throttling.ThrottledTime = v
  101. }
  102. }
  103. return nil
  104. }