cpu_limiter.cc 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //
  2. // Copyright (C) 2016 The Android Open Source Project
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "update_engine/common/cpu_limiter.h"
  17. #include <string>
  18. #include <base/bind.h>
  19. #include <base/logging.h>
  20. #include <base/strings/string_number_conversions.h>
  21. #include <base/time/time.h>
  22. #include "update_engine/common/utils.h"
  23. namespace {
  24. // Cgroup container is created in update-engine's upstart script located at
  25. // /etc/init/update-engine.conf.
  26. const char kCGroupSharesPath[] = "/sys/fs/cgroup/cpu/update-engine/cpu.shares";
  27. } // namespace
  28. namespace chromeos_update_engine {
  29. CPULimiter::~CPULimiter() {
  30. // Set everything back to normal on destruction.
  31. CPULimiter::SetCpuShares(CpuShares::kNormal);
  32. }
  33. void CPULimiter::StartLimiter() {
  34. if (manage_shares_id_ != brillo::MessageLoop::kTaskIdNull) {
  35. LOG(ERROR) << "Cpu shares timeout source hasn't been destroyed.";
  36. StopLimiter();
  37. }
  38. manage_shares_id_ = brillo::MessageLoop::current()->PostDelayedTask(
  39. FROM_HERE,
  40. base::Bind(&CPULimiter::StopLimiterCallback, base::Unretained(this)),
  41. base::TimeDelta::FromHours(2));
  42. SetCpuShares(CpuShares::kLow);
  43. }
  44. void CPULimiter::StopLimiter() {
  45. if (manage_shares_id_ != brillo::MessageLoop::kTaskIdNull) {
  46. // If the shares were never set and there isn't a message loop instance,
  47. // we avoid calling CancelTask(), which otherwise would have been a no-op.
  48. brillo::MessageLoop::current()->CancelTask(manage_shares_id_);
  49. manage_shares_id_ = brillo::MessageLoop::kTaskIdNull;
  50. }
  51. SetCpuShares(CpuShares::kNormal);
  52. }
  53. bool CPULimiter::SetCpuShares(CpuShares shares) {
  54. // Short-circuit to avoid re-setting the shares.
  55. if (shares_ == shares)
  56. return true;
  57. std::string string_shares = base::IntToString(static_cast<int>(shares));
  58. LOG(INFO) << "Setting cgroup cpu shares to " << string_shares;
  59. if (!utils::WriteFile(
  60. kCGroupSharesPath, string_shares.c_str(), string_shares.size())) {
  61. LOG(ERROR) << "Failed to change cgroup cpu shares to " << string_shares
  62. << " using " << kCGroupSharesPath;
  63. return false;
  64. }
  65. shares_ = shares;
  66. LOG(INFO) << "CPU shares = " << static_cast<int>(shares_);
  67. return true;
  68. }
  69. void CPULimiter::StopLimiterCallback() {
  70. SetCpuShares(CpuShares::kNormal);
  71. manage_shares_id_ = brillo::MessageLoop::kTaskIdNull;
  72. }
  73. } // namespace chromeos_update_engine