13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci 163f4cbf05Sopenharmony_ci#include "timer_event_handler.h" 173f4cbf05Sopenharmony_ci#include "event_reactor.h" 183f4cbf05Sopenharmony_ci#include "common_timer_errors.h" 193f4cbf05Sopenharmony_ci#include "utils_log.h" 203f4cbf05Sopenharmony_ci 213f4cbf05Sopenharmony_ci#include <unistd.h> 223f4cbf05Sopenharmony_ci#include <sys/timerfd.h> 233f4cbf05Sopenharmony_ci 243f4cbf05Sopenharmony_cinamespace OHOS { 253f4cbf05Sopenharmony_cinamespace Utils { 263f4cbf05Sopenharmony_ci 273f4cbf05Sopenharmony_ci// Unit of measure conversion 283f4cbf05Sopenharmony_cistatic const int MILLI_TO_BASE = 1000; 293f4cbf05Sopenharmony_cistatic const int NANO_TO_BASE = 1000000000; 303f4cbf05Sopenharmony_ciconstexpr int MILLI_TO_NANO = NANO_TO_BASE / MILLI_TO_BASE; 313f4cbf05Sopenharmony_ci 323f4cbf05Sopenharmony_ciTimerEventHandler::TimerEventHandler(EventReactor* p, uint32_t timeout /* ms */, bool once) 333f4cbf05Sopenharmony_ci : EventHandler(timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC), p), 343f4cbf05Sopenharmony_ci once_(once), 353f4cbf05Sopenharmony_ci interval_(timeout), 363f4cbf05Sopenharmony_ci callback_() 373f4cbf05Sopenharmony_ci{ 383f4cbf05Sopenharmony_ci} 393f4cbf05Sopenharmony_ci 403f4cbf05Sopenharmony_ciTimerEventHandler::~TimerEventHandler() 413f4cbf05Sopenharmony_ci{ 423f4cbf05Sopenharmony_ci close(GetHandle()); 433f4cbf05Sopenharmony_ci SetHandle(INVALID_TIMER_FD); 443f4cbf05Sopenharmony_ci} 453f4cbf05Sopenharmony_ci 463f4cbf05Sopenharmony_ciuint32_t TimerEventHandler::Initialize() 473f4cbf05Sopenharmony_ci{ 483f4cbf05Sopenharmony_ci if ((GetHandle() == INVALID_TIMER_FD)) { 493f4cbf05Sopenharmony_ci UTILS_LOGE("TimerEventHandler::initialize failed."); 503f4cbf05Sopenharmony_ci return TIMER_ERR_INVALID_VALUE; 513f4cbf05Sopenharmony_ci } 523f4cbf05Sopenharmony_ci 533f4cbf05Sopenharmony_ci struct itimerspec newValue = {{0, 0}, {0, 0}}; 543f4cbf05Sopenharmony_ci timespec now{0, 0}; 553f4cbf05Sopenharmony_ci if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) { 563f4cbf05Sopenharmony_ci UTILS_LOGE("Failed clock_gettime."); 573f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 583f4cbf05Sopenharmony_ci } 593f4cbf05Sopenharmony_ci 603f4cbf05Sopenharmony_ci // next time out time is now + interval 613f4cbf05Sopenharmony_ci newValue.it_value.tv_sec = now.tv_sec + interval_ / MILLI_TO_BASE; 623f4cbf05Sopenharmony_ci newValue.it_value.tv_nsec = now.tv_nsec + (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO; 633f4cbf05Sopenharmony_ci if (newValue.it_value.tv_nsec >= NANO_TO_BASE) { 643f4cbf05Sopenharmony_ci newValue.it_value.tv_sec += 1; 653f4cbf05Sopenharmony_ci newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE; 663f4cbf05Sopenharmony_ci } 673f4cbf05Sopenharmony_ci 683f4cbf05Sopenharmony_ci if (once_) { 693f4cbf05Sopenharmony_ci // interval, 0 means time out only once 703f4cbf05Sopenharmony_ci newValue.it_interval.tv_sec = 0; 713f4cbf05Sopenharmony_ci newValue.it_interval.tv_nsec = 0; 723f4cbf05Sopenharmony_ci } else { 733f4cbf05Sopenharmony_ci // interval 743f4cbf05Sopenharmony_ci newValue.it_interval.tv_sec = interval_ / MILLI_TO_BASE; 753f4cbf05Sopenharmony_ci newValue.it_interval.tv_nsec = (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO; 763f4cbf05Sopenharmony_ci } 773f4cbf05Sopenharmony_ci 783f4cbf05Sopenharmony_ci if (timerfd_settime(GetHandle(), TFD_TIMER_ABSTIME, &newValue, nullptr) == -1) { 793f4cbf05Sopenharmony_ci UTILS_LOGE("Failed in timerFd_settime"); 803f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 813f4cbf05Sopenharmony_ci } 823f4cbf05Sopenharmony_ci 833f4cbf05Sopenharmony_ci SetReadCallback([this] { this->TimeOut(); }); 843f4cbf05Sopenharmony_ci EnableRead(); 853f4cbf05Sopenharmony_ci return TIMER_ERR_OK; 863f4cbf05Sopenharmony_ci} 873f4cbf05Sopenharmony_ci 883f4cbf05Sopenharmony_civoid TimerEventHandler::Uninitialize() 893f4cbf05Sopenharmony_ci{ 903f4cbf05Sopenharmony_ci DisableAll(); 913f4cbf05Sopenharmony_ci} 923f4cbf05Sopenharmony_ci 933f4cbf05Sopenharmony_civoid TimerEventHandler::TimeOut() 943f4cbf05Sopenharmony_ci{ 953f4cbf05Sopenharmony_ci if (GetHandle() == INVALID_TIMER_FD) { 963f4cbf05Sopenharmony_ci UTILS_LOGE("timerFd_ is invalid."); 973f4cbf05Sopenharmony_ci return; 983f4cbf05Sopenharmony_ci } 993f4cbf05Sopenharmony_ci uint64_t expirations = 0; 1003f4cbf05Sopenharmony_ci ssize_t n = ::read(GetHandle(), &expirations, sizeof(expirations)); 1013f4cbf05Sopenharmony_ci if (n != sizeof(expirations)) { 1023f4cbf05Sopenharmony_ci UTILS_LOGE("epoll_loop::on_timer() reads %{public}d bytes instead of 8, errno=%{public}d", static_cast<int>(n), 1033f4cbf05Sopenharmony_ci errno); 1043f4cbf05Sopenharmony_ci } 1053f4cbf05Sopenharmony_ci if (callback_) { 1063f4cbf05Sopenharmony_ci callback_(GetHandle()); 1073f4cbf05Sopenharmony_ci } 1083f4cbf05Sopenharmony_ci} 1093f4cbf05Sopenharmony_ci 1103f4cbf05Sopenharmony_ci} // namespace Utils 1113f4cbf05Sopenharmony_ci} // namespace OHOS 112