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