• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 
16 #include "samgr_time_handler.h"
17 #include "sam_log.h"
18 #include <cinttypes>
19 
20 using namespace std;
21 namespace OHOS {
22 namespace {
23 constexpr uint32_t INIT_NUM = 4;
24 constexpr uint32_t MAX_EVENT = 8;
25 constexpr int32_t RETRY_TIMES = 3;
26 }
27 SamgrTimeHandler* volatile SamgrTimeHandler::singleton = nullptr;
28 SamgrTimeHandler::Deletor SamgrTimeHandler::deletor;
29 static mutex mtx;
30 
GetInstance()31 SamgrTimeHandler* SamgrTimeHandler::GetInstance()
32 {
33     if (singleton == nullptr) {
34         lock_guard<mutex> autoLock(mtx);
35         if (singleton == nullptr) {
36             singleton = new SamgrTimeHandler;
37         }
38     }
39     return singleton;
40 }
41 
SamgrTimeHandler()42 SamgrTimeHandler::SamgrTimeHandler()
43 {
44     HILOGI("SamgrTimeHandler init start");
45     epollfd = epoll_create(INIT_NUM);
46     if (epollfd == -1) {
47         HILOGE("SamgrTimeHandler epoll_create error");
48     }
49 }
50 
StartThread()51 void SamgrTimeHandler::StartThread()
52 {
53     std::function<void()> func = [this]() {
54         HILOGI("SamgrTimeHandler thread start");
55         struct epoll_event events[MAX_EVENT];
56         while (!this->timeFunc.IsEmpty()) {
57             int number = epoll_wait(this->epollfd, events, MAX_EVENT, -1);
58             OnTime((*this), number, events);
59         }
60         HILOGI("SamgrTimeHandler thread end");
61     };
62     std::thread t(func);
63     t.detach();
64 }
65 
OnTime(SamgrTimeHandler & handle,int number,struct epoll_event events[])66 void SamgrTimeHandler::OnTime(SamgrTimeHandler &handle, int number, struct epoll_event events[])
67 {
68     if (number > 0) {
69         HILOGI("SamgrTimeHandler OnTime: %{public}d", number);
70     }
71     for (int i = 0; i < number; i++) {
72         uint32_t timerfd = events[i].data.u32;
73         uint64_t unused = 0;
74         HILOGI("SamgrTimeHandler timerfd: %{public}u", timerfd);
75         int ret = read(timerfd, &unused, sizeof(unused));
76         if (ret == sizeof(uint64_t)) {
77             TaskType funcTime;
78             bool hasFunction = handle.timeFunc.Find(timerfd, funcTime);
79             HILOGI("SamgrTimeHandler hasFunction: %{public}d", hasFunction);
80             funcTime();
81             handle.timeFunc.Erase(timerfd);
82             epoll_ctl(this->epollfd, EPOLL_CTL_DEL, timerfd, nullptr);
83             ::close(timerfd);
84         }
85     }
86 }
87 
~SamgrTimeHandler()88 SamgrTimeHandler::~SamgrTimeHandler()
89 {
90     auto closeFunc = [this](uint32_t fd) {
91         epoll_ctl(this->epollfd, EPOLL_CTL_DEL, fd, nullptr);
92         ::close(fd);
93     };
94     timeFunc.Clear(closeFunc);
95     ::close(epollfd);
96 }
97 
CreateAndRetry()98 int SamgrTimeHandler::CreateAndRetry()
99 {
100     for (int32_t i = 0; i < RETRY_TIMES; i++) {
101         int timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
102         if (timerfd != -1) {
103             return timerfd;
104         }
105         HILOGE("timerfd_create set alarm err: %{public}s", strerror(errno));
106     }
107     return -1;
108 }
109 
PostTask(TaskType func,uint64_t delayTime)110 bool SamgrTimeHandler::PostTask(TaskType func, uint64_t delayTime)
111 {
112     HILOGI("SamgrTimeHandler postTask start: %{public}" PRId64 "s", delayTime);
113     int timerfd = CreateAndRetry();
114     if (timerfd == -1) {
115         timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
116         if (timerfd == -1) {
117             HILOGE("timerfd_create fail : %{public}s", strerror(errno));
118             return false;
119         }
120     }
121     epoll_event event {};
122     event.events = EPOLLIN | EPOLLWAKEUP;
123     event.data.u32 = static_cast<uint32_t>(timerfd);
124     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &event) == -1) {
125         HILOGE("epoll_ctl(EPOLL_CTL_ADD) failed : %{public}s", strerror(errno));
126         ::close(timerfd);
127         return false;
128     }
129     struct itimerspec newValue = {};
130     newValue.it_value.tv_sec = static_cast<int64_t>(delayTime);
131     newValue.it_value.tv_nsec = 0;
132     newValue.it_interval.tv_sec = 0;
133     newValue.it_interval.tv_nsec = 0;
134 
135     if (timerfd_settime(timerfd, 0, &newValue, NULL) == -1) {
136         HILOGE("timerfd_settime failed : %{public}s", strerror(errno));
137         ::close(timerfd);
138         return false;
139     }
140     auto isFirst = timeFunc.FirstInsert(timerfd, func);
141     if (isFirst) {
142         StartThread();
143     }
144     return true;
145 }
146 } // namespace OHOS