• 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 samgr::mutex mtx;
30 
GetInstance()31 SamgrTimeHandler* SamgrTimeHandler::GetInstance()
32 {
33     if (singleton == nullptr) {
34         lock_guard<samgr::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     if (!func) {
113         HILOGE("SamgrTimeHandler PostTask failed, func is null");
114         return false;
115     }
116     HILOGI("SamgrTimeHandler postTask start: %{public}" PRId64 "s", delayTime);
117     int timerfd = CreateAndRetry();
118     if (timerfd == -1) {
119         timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
120         if (timerfd == -1) {
121             HILOGE("timerfd_create fail : %{public}s", strerror(errno));
122             return false;
123         }
124     }
125     epoll_event event {};
126     event.events = EPOLLIN | EPOLLWAKEUP;
127     event.data.u32 = static_cast<uint32_t>(timerfd);
128     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &event) == -1) {
129         HILOGE("epoll_ctl(EPOLL_CTL_ADD) failed : %{public}s", strerror(errno));
130         ::close(timerfd);
131         return false;
132     }
133     struct itimerspec newValue = {};
134     newValue.it_value.tv_sec = static_cast<int64_t>(delayTime);
135     newValue.it_value.tv_nsec = 0;
136     newValue.it_interval.tv_sec = 0;
137     newValue.it_interval.tv_nsec = 0;
138 
139     if (timerfd_settime(timerfd, 0, &newValue, NULL) == -1) {
140         HILOGE("timerfd_settime failed : %{public}s", strerror(errno));
141         ::close(timerfd);
142         return false;
143     }
144     auto isFirst = timeFunc.FirstInsert(timerfd, func);
145     if (isFirst) {
146         StartThread();
147     }
148     return true;
149 }
150 } // namespace OHOS