• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "cgroup_manager.h"
16 #include <cerrno>
17 #include <cinttypes>
18 #include <cstdlib>
19 #include <cstdio>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <sys/eventfd.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include "app_log_wrapper.h"
26 #include "event_handler.h"
27 #include "securec.h"
28 
29 constexpr std::string_view CG_CPUSET_DEFAULT_TASKS_PATH("/dev/cpuset/tasks");
30 constexpr std::string_view CG_CPUSET_BACKGROUND_TASKS_PATH("/dev/cpuset/background/tasks");
31 constexpr std::string_view CG_CPUCTL_DEFAULT_TASKS_PATH("/dev/cpuctl/tasks");
32 constexpr std::string_view CG_CPUCTL_BACKGROUND_TASKS_PATH("/dev/cpuctl/background/tasks");
33 constexpr std::string_view CG_FREEZER_FROZEN_TASKS_PATH("/dev/freezer/frozen/tasks");
34 constexpr std::string_view CG_FREEZER_THAWED_TASKS_PATH("/dev/freezer/thawed/tasks");
35 [[maybe_unused]] constexpr std::string_view CG_MEM_OOMCTL_PATH("/dev/memcg/memory.oom_control");
36 constexpr std::string_view CG_MEM_EVTCTL_PATH("/dev/memcg/cgroup.event_control");
37 constexpr std::string_view CG_MEM_PRESSURE_LEVEL_PATH("/dev/memcg/memory.pressure_level");
38 
39 namespace OHOS {
40 namespace AppExecFwk {
41 namespace {
42 class ScopeGuard final {
43 public:
44     using Function = std::function<void()>;
45 
46 public:
ScopeGuard(Function fn)47     explicit ScopeGuard(Function fn) : fn_(fn), dismissed_(false)
48     {}
49 
~ScopeGuard()50     ~ScopeGuard()
51     {
52         if (!dismissed_) {
53             fn_();
54         }
55     }
56 
57 public:
Dismiss()58     void Dismiss()
59     {
60         dismissed_ = true;
61     }
62 
63 private:
64     Function fn_;
65     bool dismissed_ = false;
66 };
67 
WriteValue(int fd,std::string_view v)68 int WriteValue(int fd, std::string_view v)
69 {
70     if (fd < 0) {
71         errno = EINVAL;
72         return -1;
73     }
74 
75     int ret = TEMP_FAILURE_RETRY(write(fd, v.data(), v.size()));
76     if (ret != 0) {
77         APP_LOGE("%{public}s(%{public}d) err: %{public}s.", __func__, __LINE__, strerror(errno));
78     }
79     fsync(fd);
80 
81     return ret;
82 }
83 
WriteValue(int fd,int v,bool newLine=true)84 int WriteValue(int fd, int v, bool newLine = true)
85 {
86     if (fd < 0) {
87         errno = EINVAL;
88         return -1;
89     }
90 
91     char str[32] = {0};
92 
93     int len = snprintf_s(str, sizeof(str), sizeof(str) - 1, newLine ? "%d\n" : "%d", v);
94     if (len < 1) {
95         return -1;
96     }
97 
98     return WriteValue(fd, str);
99 }
100 
101 }  // namespace
102 
CgroupManager()103 CgroupManager::CgroupManager()
104 {}
105 
~CgroupManager()106 CgroupManager::~CgroupManager()
107 {
108     for (int i = 0; i < LOW_MEMORY_LEVEL_MAX; ++i) {
109         if (memoryEventFds_[i] >= 0) {
110             if (eventHandler_) {
111                 eventHandler_->RemoveFileDescriptorListener(memoryEventFds_[i]);
112             }
113             close(memoryEventFds_[i]);
114         }
115         if (memoryPressureFds_[i] >= 0) {
116             close(memoryPressureFds_[i]);
117         }
118     }
119 
120     if (memoryEventControlFd_ >= 0) {
121         close(memoryEventControlFd_);
122     }
123 
124     for (int i = 0; i < SCHED_POLICY_CPU_MAX; ++i) {
125         if (cpusetTasksFds_[i] >= 0) {
126             close(cpusetTasksFds_[i]);
127         }
128     }
129 }
130 
Init()131 bool CgroupManager::Init()
132 {
133     APP_LOGE("%{public}s(%{public}d) Init enter.", __func__, __LINE__);
134     if (IsInited()) {
135         APP_LOGE("%{public}s(%{public}d) already inited.", __func__, __LINE__);
136         return false;
137     }
138 
139     auto eventHandler = std::make_shared<EventHandler>(EventRunner::Create());
140     if (!eventHandler) {
141         APP_LOGE("%{public}s(%{public}d) failed to get event handler.", __func__, __LINE__);
142         return false;
143     }
144 
145     if(!InitCheck()){
146         return false;
147     }
148 
149     if (!RegisterLowMemoryMonitor(
150         memoryEventFds_, memoryPressureFds_, memoryEventControlFd_, LOW_MEMORY_LEVEL_LOW, eventHandler)) {
151         return false;
152     }
153 
154     ScopeGuard lowLevelListenerGuard(
155         [&]() { eventHandler->RemoveFileDescriptorListener(memoryEventFds_[LOW_MEMORY_LEVEL_LOW]); });
156 
157     if (!RegisterLowMemoryMonitor(
158         memoryEventFds_, memoryPressureFds_, memoryEventControlFd_, LOW_MEMORY_LEVEL_MEDIUM, eventHandler)) {
159         return false;
160     }
161 
162     ScopeGuard mediumLevelListenerGuard(
163         [&]() { eventHandler->RemoveFileDescriptorListener(memoryEventFds_[LOW_MEMORY_LEVEL_MEDIUM]); });
164 
165     if (!RegisterLowMemoryMonitor(
166         memoryEventFds_, memoryPressureFds_, memoryEventControlFd_, LOW_MEMORY_LEVEL_CRITICAL, eventHandler)) {
167         return false;
168     }
169 
170     ScopeGuard criticalLevelListenerGuard(
171         [&]() { eventHandler->RemoveFileDescriptorListener(memoryEventFds_[LOW_MEMORY_LEVEL_CRITICAL]); });
172 
173     eventHandler_ = eventHandler;
174     lowLevelListenerGuard.Dismiss();
175     mediumLevelListenerGuard.Dismiss();
176     criticalLevelListenerGuard.Dismiss();
177 
178     return true;
179 }
180 
InitCheck()181 bool CgroupManager::InitCheck()
182 {
183     UniqueFd cpusetTasksFds[SCHED_POLICY_CPU_MAX];
184     if (!InitCpusetTasksFds(cpusetTasksFds)) {
185         return false;
186     }
187 
188     UniqueFd cpuctlTasksFds[SCHED_POLICY_CPU_MAX];
189     if (!InitCpuctlTasksFds(cpuctlTasksFds)) {
190         return false;
191     }
192 
193     UniqueFd freezerTasksFds[SCHED_POLICY_FREEZER_MAX];
194     if (!InitFreezerTasksFds(freezerTasksFds)) {
195         return false;
196     }
197 
198     UniqueFd memoryEventControlFd;
199     if (!InitMemoryEventControlFd(memoryEventControlFd)) {
200         return false;
201     }
202 
203     UniqueFd memoryEventFds[LOW_MEMORY_LEVEL_MAX];
204     if (!InitMemoryEventFds(memoryEventFds)) {
205         return false;
206     }
207 
208     UniqueFd memoryPressureFds[LOW_MEMORY_LEVEL_MAX];
209     if (!InitMemoryPressureFds(memoryPressureFds)) {
210         return false;
211     }
212     return true;
213 }
214 
IsInited() const215 bool CgroupManager::IsInited() const
216 {
217     return bool(eventHandler_);
218 }
219 
SetThreadSchedPolicy(int tid,SchedPolicy schedPolicy)220 bool CgroupManager::SetThreadSchedPolicy(int tid, SchedPolicy schedPolicy)
221 {
222     if (!IsInited()) {
223         APP_LOGE("%{public}s(%{public}d) not inited.", __func__, __LINE__);
224         return false;
225     }
226 
227     if (tid < 1) {
228         APP_LOGE("%{public}s(%{public}d) invalid tid %{public}d.", __func__, __LINE__, tid);
229         return false;
230     }
231 
232     if (schedPolicy < 0 || schedPolicy >= SchedPolicy::SCHED_POLICY_MAX) {
233         APP_LOGE("%{public}s(%{public}d) invalid sched policy %{public}d.", __func__, __LINE__, schedPolicy);
234         return false;
235     }
236 
237     if (schedPolicy == SchedPolicy::SCHED_POLICY_FREEZED) {
238         // set frozen of freezer
239         if (!SetFreezerSubsystem(tid, SchedPolicyFreezer::SCHED_POLICY_FREEZER_FROZEN)) {
240             APP_LOGE("%{public}s(%{public}d) set freezer subsystem failed sched policy %{public}d.",
241                 __func__,
242                 __LINE__,
243                 schedPolicy);
244             return false;
245         }
246     } else {
247         // set cpuset
248         if (!SetCpusetSubsystem(tid, schedPolicy)) {
249             APP_LOGE("%{public}s(%{public}d) set cpuset subsystem failed sched policy %{public}d.",
250                 __func__,
251                 __LINE__,
252                 schedPolicy);
253             return false;
254         }
255         // set cpuctl
256         if (!SetCpuctlSubsystem(tid, schedPolicy)) {
257             APP_LOGE("%{public}s(%{public}d) set cpuctl subsystem failed sched policy %{public}d.",
258                 __func__,
259                 __LINE__,
260                 schedPolicy);
261             return false;
262         }
263 
264         // set thawed of freezer
265         if (!SetFreezerSubsystem(tid, SchedPolicyFreezer::SCHED_POLICY_FREEZER_THAWED)) {
266             APP_LOGE("%{public}s(%{public}d) set freezer subsystem failed sched policy %{public}d.",
267                 __func__,
268                 __LINE__,
269                 schedPolicy);
270             return false;
271         }
272     }
273 
274     return true;
275 }
276 
SetProcessSchedPolicy(int pid,SchedPolicy schedPolicy)277 bool CgroupManager::SetProcessSchedPolicy(int pid, SchedPolicy schedPolicy)
278 {
279     if (!IsInited()) {
280         APP_LOGE("%{public}s(%{public}d) not inited.", __func__, __LINE__);
281         return false;
282     }
283 
284     if (pid < 1) {
285         APP_LOGE("%{public}s(%{public}d) invalid pid %{public}d", __func__, __LINE__, pid);
286         return false;
287     }
288 
289     if (schedPolicy < 0 && schedPolicy >= SCHED_POLICY_MAX) {
290         APP_LOGE("%{public}s(%{public}d) invalid sched policy %{public}d", __func__, __LINE__, schedPolicy);
291         return false;
292     }
293 
294     // Set all threads's sched policy inside this process.
295     char taskDir[64];
296     if (snprintf_s(taskDir, sizeof(taskDir), sizeof(taskDir) - 1, "/proc/%d/task", pid) < 0) {
297         return false;
298     }
299 
300     DIR *dir = opendir(taskDir);
301     if (dir == nullptr) {
302         APP_LOGE("%{public}s(%{public}d) failed to opendir invalid pid %{public}d taskDir %{public}s , %{public}s",
303             __func__,
304             __LINE__,
305             pid,
306             taskDir,
307             strerror(errno));
308         return false;
309     }
310 
311     struct dirent *dent;
312     while ((dent = readdir(dir))) {
313         // Filter out '.' & '..'
314         if (dent->d_name[0] != '.') {
315             SetThreadSchedPolicy(atoi(dent->d_name), schedPolicy);
316         }
317     }
318 
319     closedir(dir);
320 
321     return true;
322 }
323 
OnReadable(int32_t fd)324 void CgroupManager::OnReadable(int32_t fd)
325 {
326     APP_LOGW("%{public}s(%{public}d) system low memory alert.", __func__, __LINE__);
327 
328     if (!LowMemoryAlert) {
329         APP_LOGE("%{public}s(%{public}d) 'LowMemoryAlert' not available.", __func__, __LINE__);
330         return;
331     }
332 
333     auto TryToRaiseLowMemoryAlert = [=](LowMemoryLevel level) {
334         if (fd == memoryEventFds_[level]) {
335             APP_LOGW("%{public}s(%{public}d) checking level %{public}d", __func__, __LINE__, level);
336             uint64_t count = 0;
337             int ret = TEMP_FAILURE_RETRY(read(fd, &count, sizeof(uint64_t)));
338             if (ret <= 0) {
339                 APP_LOGW("%{public}s(%{public}d) failed to read eventfd %{public}d.", __func__, __LINE__, errno);
340                 return false;
341             }
342             if (count < 1) {
343                 APP_LOGW(
344                     "%{public}s(%{public}d) invalid eventfd count %{public}" PRIu64 ".", __func__, __LINE__, count);
345                 return false;
346             }
347             APP_LOGW(
348                 "%{public}s(%{public}d) raising low memory alert for level %{public}d...", __func__, __LINE__, level);
349             LowMemoryAlert(level);
350             return true;
351         }
352         return false;
353     };
354 
355     if (TryToRaiseLowMemoryAlert(LOW_MEMORY_LEVEL_LOW)) {
356         return;
357     }
358 
359     if (TryToRaiseLowMemoryAlert(LOW_MEMORY_LEVEL_MEDIUM)) {
360         return;
361     }
362 
363     if (TryToRaiseLowMemoryAlert(LOW_MEMORY_LEVEL_CRITICAL)) {
364         return;
365     }
366 
367     // Should not reach here!
368     APP_LOGE("%{public}s(%{public}d) Unknown fd %{public}d.", __func__, __LINE__, fd);
369 }
370 
RegisterLowMemoryMonitor(const int memoryEventFds[LOW_MEMORY_LEVEL_MAX],const int memoryPressureFds[LOW_MEMORY_LEVEL_MAX],const int memoryEventControlFd,const LowMemoryLevel level,const std::shared_ptr<EventHandler> & eventHandler)371 bool CgroupManager::RegisterLowMemoryMonitor(const int memoryEventFds[LOW_MEMORY_LEVEL_MAX],
372     const int memoryPressureFds[LOW_MEMORY_LEVEL_MAX], const int memoryEventControlFd, const LowMemoryLevel level,
373     const std::shared_ptr<EventHandler> &eventHandler)
374 {
375     APP_LOGI("RegisterLowMemoryMonitor(%{public}d) registering low memory monitor %{public}d...", __LINE__, level);
376 
377     char buf[64] = {0};
378     static const char *levelName[] = {"low", "medium", "critical"};
379 
380     if (snprintf_s(buf,
381         sizeof(buf),
382         sizeof(buf) - 1,
383         "%d %d %s",
384         memoryEventFds[level],
385         memoryPressureFds[level],
386         levelName[level]) < 0) {
387         return false;
388     }
389 
390     int ret = TEMP_FAILURE_RETRY(write(memoryEventControlFd, buf, strlen(buf) + 1));
391     if (ret < 0) {
392         APP_LOGI("RegisterLowMemoryMonitor(%{public}d) failed to write memory control %{public}d...", __LINE__, errno);
393         return false;
394     }
395 
396     eventHandler->AddFileDescriptorListener(memoryEventFds[level], FILE_DESCRIPTOR_INPUT_EVENT, shared_from_this());
397 
398     return true;
399 }
400 
InitCpusetTasksFds(UniqueFd cpusetTasksFds[SCHED_POLICY_CPU_MAX])401 bool CgroupManager::InitCpusetTasksFds(UniqueFd cpusetTasksFds[SCHED_POLICY_CPU_MAX])
402 {
403     cpusetTasksFds[SCHED_POLICY_CPU_DEFAULT] = UniqueFd(open(CG_CPUSET_DEFAULT_TASKS_PATH.data(), O_RDWR));
404     cpusetTasksFds[SCHED_POLICY_CPU_BACKGROUND] = UniqueFd(open(CG_CPUSET_BACKGROUND_TASKS_PATH.data(), O_RDWR));
405     if (cpusetTasksFds[SCHED_POLICY_CPU_DEFAULT].Get() < 0 || cpusetTasksFds[SCHED_POLICY_CPU_BACKGROUND].Get() < 0) {
406         APP_LOGE("%{public}s(%{public}d) cannot open cpuset cgroups %{public}d.", __func__, __LINE__, errno);
407         return false;
408     }
409 
410     cpusetTasksFds_[SCHED_POLICY_CPU_DEFAULT] = cpusetTasksFds[SCHED_POLICY_CPU_DEFAULT].Release();
411     cpusetTasksFds_[SCHED_POLICY_CPU_BACKGROUND] = cpusetTasksFds[SCHED_POLICY_CPU_BACKGROUND].Release();
412     return true;
413 }
414 
InitCpuctlTasksFds(UniqueFd cpuctlTasksFds[SCHED_POLICY_CPU_MAX])415 bool CgroupManager::InitCpuctlTasksFds(UniqueFd cpuctlTasksFds[SCHED_POLICY_CPU_MAX])
416 {
417     cpuctlTasksFds[SCHED_POLICY_CPU_DEFAULT] = UniqueFd(open(CG_CPUCTL_DEFAULT_TASKS_PATH.data(), O_RDWR));
418     cpuctlTasksFds[SCHED_POLICY_CPU_BACKGROUND] = UniqueFd(open(CG_CPUCTL_BACKGROUND_TASKS_PATH.data(), O_RDWR));
419     if (cpuctlTasksFds[SCHED_POLICY_CPU_DEFAULT].Get() < 0 || cpuctlTasksFds[SCHED_POLICY_CPU_BACKGROUND].Get() < 0) {
420         APP_LOGE("%{public}s(%{public}d) cannot open cpuctl cgroups %{public}d.", __func__, __LINE__, errno);
421         return false;
422     }
423 
424     cpuctlTasksFds_[SCHED_POLICY_CPU_DEFAULT] = cpuctlTasksFds[SCHED_POLICY_CPU_DEFAULT].Release();
425     cpuctlTasksFds_[SCHED_POLICY_CPU_BACKGROUND] = cpuctlTasksFds[SCHED_POLICY_CPU_BACKGROUND].Release();
426     return true;
427 }
428 
InitFreezerTasksFds(UniqueFd freezerTasksFds[SCHED_POLICY_FREEZER_MAX])429 bool CgroupManager::InitFreezerTasksFds(UniqueFd freezerTasksFds[SCHED_POLICY_FREEZER_MAX])
430 {
431     freezerTasksFds[SCHED_POLICY_FREEZER_FROZEN] = UniqueFd(open(CG_FREEZER_FROZEN_TASKS_PATH.data(), O_RDWR));
432     freezerTasksFds[SCHED_POLICY_FREEZER_THAWED] = UniqueFd(open(CG_FREEZER_THAWED_TASKS_PATH.data(), O_RDWR));
433     if (freezerTasksFds[SCHED_POLICY_FREEZER_FROZEN].Get() < 0 ||
434         freezerTasksFds[SCHED_POLICY_FREEZER_THAWED].Get() < 0) {
435         APP_LOGE("%{public}s(%{public}d) cannot open freezer cgroups %{public}d.", __func__, __LINE__, errno);
436         return false;
437     }
438 
439     freezerTasksFds_[SCHED_POLICY_FREEZER_FROZEN] = freezerTasksFds[SCHED_POLICY_FREEZER_FROZEN].Release();
440     freezerTasksFds_[SCHED_POLICY_FREEZER_THAWED] = freezerTasksFds[SCHED_POLICY_FREEZER_THAWED].Release();
441     return true;
442 }
443 
InitMemoryEventControlFd(UniqueFd & memoryEventControlFd)444 bool CgroupManager::InitMemoryEventControlFd(UniqueFd &memoryEventControlFd)
445 {
446     memoryEventControlFd = UniqueFd(open(CG_MEM_EVTCTL_PATH.data(), O_WRONLY));
447     if (memoryEventControlFd.Get() < 0) {
448         APP_LOGE(
449             "%{pubid}s(%{publid}d) failed to open memory event control node %{public}d.", __func__, __LINE__, errno);
450         return false;
451     }
452 
453     memoryEventControlFd_ = memoryEventControlFd.Release();
454     return true;
455 }
456 
InitMemoryEventFds(UniqueFd memoryEventFds[LOW_MEMORY_LEVEL_MAX])457 bool CgroupManager::InitMemoryEventFds(UniqueFd memoryEventFds[LOW_MEMORY_LEVEL_MAX])
458 {
459     memoryEventFds[LOW_MEMORY_LEVEL_LOW] = UniqueFd(eventfd(0, EFD_NONBLOCK));
460     memoryEventFds[LOW_MEMORY_LEVEL_MEDIUM] = UniqueFd(eventfd(0, EFD_NONBLOCK));
461     memoryEventFds[LOW_MEMORY_LEVEL_CRITICAL] = UniqueFd(eventfd(0, EFD_NONBLOCK));
462     if (memoryEventFds[LOW_MEMORY_LEVEL_LOW].Get() < 0 || memoryEventFds[LOW_MEMORY_LEVEL_MEDIUM].Get() < 0 ||
463         memoryEventFds[LOW_MEMORY_LEVEL_CRITICAL].Get() < 0) {
464         APP_LOGE("%{public}s(${public}d) failed to create memory eventfd %{public}d.", __func__, __LINE__, errno);
465         return false;
466     }
467 
468     memoryEventFds_[LOW_MEMORY_LEVEL_LOW] = memoryEventFds[LOW_MEMORY_LEVEL_LOW].Release();
469     memoryEventFds_[LOW_MEMORY_LEVEL_MEDIUM] = memoryEventFds[LOW_MEMORY_LEVEL_MEDIUM].Release();
470     memoryEventFds_[LOW_MEMORY_LEVEL_CRITICAL] = memoryEventFds[LOW_MEMORY_LEVEL_CRITICAL].Release();
471     return true;
472 }
473 
InitMemoryPressureFds(UniqueFd memoryPressureFds[LOW_MEMORY_LEVEL_MAX])474 bool CgroupManager::InitMemoryPressureFds(UniqueFd memoryPressureFds[LOW_MEMORY_LEVEL_MAX])
475 {
476     memoryPressureFds[LOW_MEMORY_LEVEL_LOW] = UniqueFd(open(CG_MEM_PRESSURE_LEVEL_PATH.data(), O_RDONLY));
477     memoryPressureFds[LOW_MEMORY_LEVEL_MEDIUM] = UniqueFd(open(CG_MEM_PRESSURE_LEVEL_PATH.data(), O_RDONLY));
478     memoryPressureFds[LOW_MEMORY_LEVEL_CRITICAL] = UniqueFd(open(CG_MEM_PRESSURE_LEVEL_PATH.data(), O_RDONLY));
479     if (memoryPressureFds[LOW_MEMORY_LEVEL_LOW].Get() < 0 || memoryPressureFds[LOW_MEMORY_LEVEL_MEDIUM].Get() < 0 ||
480         memoryPressureFds[LOW_MEMORY_LEVEL_CRITICAL].Get() < 0) {
481         APP_LOGE("%{public}s(${public}d) failed to open memory pressure fd %{public}d.", __func__, __LINE__, errno);
482         return false;
483     }
484 
485     memoryPressureFds_[LOW_MEMORY_LEVEL_LOW] = memoryPressureFds[LOW_MEMORY_LEVEL_LOW].Release();
486     memoryPressureFds_[LOW_MEMORY_LEVEL_MEDIUM] = memoryPressureFds[LOW_MEMORY_LEVEL_MEDIUM].Release();
487     memoryPressureFds_[LOW_MEMORY_LEVEL_CRITICAL] = memoryPressureFds[LOW_MEMORY_LEVEL_CRITICAL].Release();
488     return true;
489 }
490 
SetCpusetSubsystem(const int tid,const SchedPolicy schedPolicy)491 bool CgroupManager::SetCpusetSubsystem(const int tid, const SchedPolicy schedPolicy)
492 {
493     int fd = cpusetTasksFds_[schedPolicy];
494     if (fd < 0) {
495         APP_LOGE("%{public}s(%{public}d) invalid cpuset fd for policy %{public}d.", __func__, __LINE__, schedPolicy);
496         return false;
497     }
498 
499     int ret = WriteValue(fd, tid);
500     if (ret < 0) {
501         APP_LOGE("%{public}s(%{public}d) write cpuset tid failed %{public}d.", __func__, __LINE__, errno);
502         return false;
503     }
504 
505     return true;
506 }
507 
SetCpuctlSubsystem(const int tid,const SchedPolicy schedPolicy)508 bool CgroupManager::SetCpuctlSubsystem(const int tid, const SchedPolicy schedPolicy)
509 {
510     int fd = cpuctlTasksFds_[schedPolicy];
511     if (fd < 0) {
512         APP_LOGE("%{public}s(%{public}d) invalid cpuctl fd for policy %{public}d.", __func__, __LINE__, schedPolicy);
513         return false;
514     }
515 
516     int ret = WriteValue(fd, tid);
517     if (ret < 0) {
518         APP_LOGE("%{public}s(%{public}d) write cpuctl tid failed %{public}d.", __func__, __LINE__, errno);
519         return false;
520     }
521 
522     return true;
523 }
524 
SetFreezerSubsystem(const int tid,const SchedPolicyFreezer state)525 bool CgroupManager::SetFreezerSubsystem(const int tid, const SchedPolicyFreezer state)
526 {
527     int fd = freezerTasksFds_[state];
528     if (fd < 0) {
529         APP_LOGE("%{public}s(%{public}d) invalid freezer fd for state %{public}d.", __func__, __LINE__, state);
530         return false;
531     }
532 
533     int ret = WriteValue(fd, tid);
534     if (ret < 0) {
535         APP_LOGE("%{public}s(%{public}d) write freezer tid failed %{public}d.", __func__, __LINE__, errno);
536         return false;
537     }
538 
539     return true;
540 }
541 }  // namespace AppExecFwk
542 }  // namespace OHOS
543