1cf69771bSopenharmony_ci/* 2cf69771bSopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cf69771bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cf69771bSopenharmony_ci * you may not use this file except in compliance with the License. 5cf69771bSopenharmony_ci * You may obtain a copy of the License at 6cf69771bSopenharmony_ci * 7cf69771bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cf69771bSopenharmony_ci * 9cf69771bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cf69771bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cf69771bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cf69771bSopenharmony_ci * See the License for the specific language governing permissions and 13cf69771bSopenharmony_ci * limitations under the License. 14cf69771bSopenharmony_ci */ 15cf69771bSopenharmony_ci 16cf69771bSopenharmony_ci#include <unistd.h> 17cf69771bSopenharmony_ci#include <cstring> 18cf69771bSopenharmony_ci#include <sys/epoll.h> 19cf69771bSopenharmony_ci#include <sys/timerfd.h> 20cf69771bSopenharmony_ci#include <sys/time.h> 21cf69771bSopenharmony_ci#include <sstream> 22cf69771bSopenharmony_ci#include <fstream> 23cf69771bSopenharmony_ci#include <iostream> 24cf69771bSopenharmony_ci#include "timer_handler.h" 25cf69771bSopenharmony_ci 26cf69771bSopenharmony_cinamespace OHOS { 27cf69771bSopenharmony_cinamespace MiscServices { 28cf69771bSopenharmony_cinamespace { 29cf69771bSopenharmony_cistatic const uint32_t ALARM_TIME_CHANGE_MASK = 1 << 16; 30cf69771bSopenharmony_cistatic const clockid_t alarm_to_clock_id[N_TIMER_FDS] = { 31cf69771bSopenharmony_ci CLOCK_REALTIME_ALARM, 32cf69771bSopenharmony_ci CLOCK_REALTIME, 33cf69771bSopenharmony_ci CLOCK_BOOTTIME_ALARM, 34cf69771bSopenharmony_ci CLOCK_BOOTTIME, 35cf69771bSopenharmony_ci CLOCK_MONOTONIC, 36cf69771bSopenharmony_ci CLOCK_REALTIME, 37cf69771bSopenharmony_ci}; 38cf69771bSopenharmony_ci} 39cf69771bSopenharmony_ci 40cf69771bSopenharmony_cistd::shared_ptr<TimerHandler> TimerHandler::Create() 41cf69771bSopenharmony_ci{ 42cf69771bSopenharmony_ci int epollfd; 43cf69771bSopenharmony_ci TimerFds fds; 44cf69771bSopenharmony_ci 45cf69771bSopenharmony_ci epollfd = epoll_create(fds.size()); 46cf69771bSopenharmony_ci if (epollfd < 0) { 47cf69771bSopenharmony_ci TIME_HILOGE(TIME_MODULE_SERVICE, "epoll_create %{public}d failed: %{public}s", 48cf69771bSopenharmony_ci static_cast<int>(fds.size()), strerror(errno)); 49cf69771bSopenharmony_ci return nullptr; 50cf69771bSopenharmony_ci } 51cf69771bSopenharmony_ci 52cf69771bSopenharmony_ci for (size_t i = 0; i < fds.size(); i++) { 53cf69771bSopenharmony_ci fds[i] = timerfd_create(alarm_to_clock_id[i], 0); 54cf69771bSopenharmony_ci if (fds[i] < 0) { 55cf69771bSopenharmony_ci TIME_HILOGE(TIME_MODULE_SERVICE, "timerfd_create %{public}d failed: %{public}s", 56cf69771bSopenharmony_ci static_cast<int>(i), strerror(errno)); 57cf69771bSopenharmony_ci close(epollfd); 58cf69771bSopenharmony_ci for (size_t j = 0; j < i; j++) { 59cf69771bSopenharmony_ci close(fds[j]); 60cf69771bSopenharmony_ci } 61cf69771bSopenharmony_ci return nullptr; 62cf69771bSopenharmony_ci } 63cf69771bSopenharmony_ci } 64cf69771bSopenharmony_ci 65cf69771bSopenharmony_ci std::shared_ptr<TimerHandler> handler = std::shared_ptr<TimerHandler>(new TimerHandler(fds, epollfd)); 66cf69771bSopenharmony_ci for (size_t i = 0; i < fds.size(); i++) { 67cf69771bSopenharmony_ci epoll_event event {}; 68cf69771bSopenharmony_ci event.events = EPOLLIN | EPOLLWAKEUP; 69cf69771bSopenharmony_ci event.data.u32 = i; 70cf69771bSopenharmony_ci 71cf69771bSopenharmony_ci int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event); 72cf69771bSopenharmony_ci if (err < 0) { 73cf69771bSopenharmony_ci TIME_HILOGE(TIME_MODULE_SERVICE, "epoll_ctl(EPOLL_CTL_ADD) failed: %{public}s", strerror(errno)); 74cf69771bSopenharmony_ci return nullptr; 75cf69771bSopenharmony_ci } 76cf69771bSopenharmony_ci } 77cf69771bSopenharmony_ci itimerspec spec {}; 78cf69771bSopenharmony_ci 79cf69771bSopenharmony_ci int err = timerfd_settime(fds[ALARM_TYPE_COUNT], TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, nullptr); 80cf69771bSopenharmony_ci if (err < 0) { 81cf69771bSopenharmony_ci TIME_HILOGE(TIME_MODULE_SERVICE, "timerfd_settime() failed: %{public}s", strerror(errno)); 82cf69771bSopenharmony_ci return nullptr; 83cf69771bSopenharmony_ci } 84cf69771bSopenharmony_ci 85cf69771bSopenharmony_ci return handler; 86cf69771bSopenharmony_ci} 87cf69771bSopenharmony_ci 88cf69771bSopenharmony_ciTimerHandler::TimerHandler(const TimerFds &fds, int epollfd) 89cf69771bSopenharmony_ci : fds_ {fds}, epollFd_ {epollfd} 90cf69771bSopenharmony_ci{ 91cf69771bSopenharmony_ci} 92cf69771bSopenharmony_ci 93cf69771bSopenharmony_ciTimerHandler::~TimerHandler() 94cf69771bSopenharmony_ci{ 95cf69771bSopenharmony_ci for (auto fd : fds_) { 96cf69771bSopenharmony_ci epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr); 97cf69771bSopenharmony_ci close(fd); 98cf69771bSopenharmony_ci } 99cf69771bSopenharmony_ci close(epollFd_); 100cf69771bSopenharmony_ci} 101cf69771bSopenharmony_ci 102cf69771bSopenharmony_ciint TimerHandler::Set(uint32_t type, std::chrono::nanoseconds when, std::chrono::steady_clock::time_point bootTime) 103cf69771bSopenharmony_ci{ 104cf69771bSopenharmony_ci if (static_cast<size_t>(type) > ALARM_TYPE_COUNT) { 105cf69771bSopenharmony_ci errno = EINVAL; 106cf69771bSopenharmony_ci return -1; 107cf69771bSopenharmony_ci } 108cf69771bSopenharmony_ci 109cf69771bSopenharmony_ci auto second = std::chrono::duration_cast<std::chrono::seconds>(when); 110cf69771bSopenharmony_ci TIME_SIMPLIFY_HILOGI(TIME_MODULE_SERVICE, "typ:%{public}d trig: %{public}lld %{public}lld, bt: %{public}lld", 111cf69771bSopenharmony_ci type, second.count(), (when - second).count(), bootTime.time_since_epoch().count()); 112cf69771bSopenharmony_ci timespec ts {second.count(), (when - second).count()}; 113cf69771bSopenharmony_ci itimerspec spec {timespec {}, ts}; 114cf69771bSopenharmony_ci int ret = timerfd_settime(fds_[type], TFD_TIMER_ABSTIME, &spec, nullptr); 115cf69771bSopenharmony_ci if (ret != 0) { 116cf69771bSopenharmony_ci TIME_HILOGE(TIME_MODULE_SERVICE, "Set timer to kernel. ret: %{public}d. error: %{public}s.", 117cf69771bSopenharmony_ci ret, strerror(errno)); 118cf69771bSopenharmony_ci } 119cf69771bSopenharmony_ci return ret; 120cf69771bSopenharmony_ci} 121cf69771bSopenharmony_ci 122cf69771bSopenharmony_ciuint32_t TimerHandler::WaitForAlarm() 123cf69771bSopenharmony_ci{ 124cf69771bSopenharmony_ci epoll_event events[N_TIMER_FDS]; 125cf69771bSopenharmony_ci 126cf69771bSopenharmony_ci int nevents = 0; 127cf69771bSopenharmony_ci do { 128cf69771bSopenharmony_ci nevents = epoll_wait(epollFd_, events, N_TIMER_FDS, -1); 129cf69771bSopenharmony_ci } while (nevents < 0 && errno == EINTR); 130cf69771bSopenharmony_ci 131cf69771bSopenharmony_ci uint32_t result = 0; 132cf69771bSopenharmony_ci for (int i = 0; i < nevents; i++) { 133cf69771bSopenharmony_ci uint32_t alarm_idx = events[i].data.u32; 134cf69771bSopenharmony_ci uint64_t unused; 135cf69771bSopenharmony_ci ssize_t err = read(fds_[alarm_idx], &unused, sizeof(unused)); 136cf69771bSopenharmony_ci if (err < 0) { 137cf69771bSopenharmony_ci if (alarm_idx == ALARM_TYPE_COUNT && errno == ECANCELED) { 138cf69771bSopenharmony_ci result |= ALARM_TIME_CHANGE_MASK; 139cf69771bSopenharmony_ci } else { 140cf69771bSopenharmony_ci return err; 141cf69771bSopenharmony_ci } 142cf69771bSopenharmony_ci } else { 143cf69771bSopenharmony_ci result |= (1 << alarm_idx); 144cf69771bSopenharmony_ci } 145cf69771bSopenharmony_ci } 146cf69771bSopenharmony_ci return result; 147cf69771bSopenharmony_ci} 148cf69771bSopenharmony_ci} // MiscServices 149cf69771bSopenharmony_ci} // OHOS