• 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 
16 #include "dm_timer.h"
17 
18 #include <thread>
19 
20 #include "securec.h"
21 
22 namespace OHOS {
23 namespace DistributedHardware {
24 namespace {
25 const int32_t MILL_SECONDS_PER_SECOND = 1000;
26 }
DmTimer(std::string & name)27 DmTimer::DmTimer(std::string &name)
28 {
29     mStatus_ = DmTimerStatus::DM_STATUS_INIT;
30     mTimeOutSec_ = 0;
31     mHandle_ = nullptr;
32     mHandleData_ = nullptr;
33     (void)memset_s(mTimeFd_, sizeof(mTimeFd_), 0, sizeof(mTimeFd_));
34     (void)memset_s(&mEv_, sizeof(mEv_), 0, sizeof(mEv_));
35     (void)memset_s(mEvents_, sizeof(mEvents_), 0, sizeof(mEvents_));
36     mEpFd_ = 0;
37     mTimerName_ = name;
38 }
39 
~DmTimer()40 DmTimer::~DmTimer()
41 {
42     DMLOG(DM_LOG_INFO, "DmTimer %s Destory in", mTimerName_.c_str());
43     Release();
44 }
45 
Start(uint32_t timeOut,TimeoutHandle handle,void * data)46 DmTimerStatus DmTimer::Start(uint32_t timeOut, TimeoutHandle handle, void *data)
47 {
48     DMLOG(DM_LOG_INFO, "DmTimer %s start timeout(%d)", mTimerName_.c_str(), timeOut);
49     if (mStatus_ != DmTimerStatus::DM_STATUS_INIT) {
50         return DmTimerStatus::DM_STATUS_BUSY;
51     }
52 
53     mTimeOutSec_ = timeOut;
54     mHandle_ = handle;
55     mHandleData_ = data;
56 
57     if (CreateTimeFd()) {
58         return DmTimerStatus::DM_STATUS_CREATE_ERROR;
59     }
60 
61     mStatus_ = DmTimerStatus::DM_STATUS_RUNNING;
62     mThread_ = std::thread(&DmTimer::WiteforTimeout, this);
63     mThread_.detach();
64 
65     return mStatus_;
66 }
67 
Stop(int32_t code)68 void DmTimer::Stop(int32_t code)
69 {
70     DMLOG(DM_LOG_INFO, "DmTimer %s Stop code (%d)", mTimerName_.c_str(), code);
71     if (mTimeFd_[1]) {
72         char event = 'S';
73         if (write(mTimeFd_[1], &event, 1) < 0) {
74             DMLOG(DM_LOG_ERROR, "DmTimer %s Stop timer failed, errno %d", mTimerName_.c_str(), errno);
75             return;
76         }
77         DMLOG(DM_LOG_INFO, "DmTimer %s Stop success", mTimerName_.c_str());
78     }
79 
80     return;
81 }
82 
WiteforTimeout()83 void DmTimer::WiteforTimeout()
84 {
85     DMLOG(DM_LOG_INFO, "DmTimer %s start timer at (%d)s", mTimerName_.c_str(), mTimeOutSec_);
86 
87     int32_t nfds = epoll_wait(mEpFd_, mEvents_, MAXEVENTS, mTimeOutSec_ * MILL_SECONDS_PER_SECOND);
88     if (nfds < 0) {
89         DMLOG(DM_LOG_ERROR, "DmTimer %s epoll_wait returned n=%d, error: %d", mTimerName_.c_str(), nfds, errno);
90     }
91 
92     char event = 0;
93     if (nfds > 0) {
94         if (mEvents_[0].events & EPOLLIN) {
95             int num = read(mTimeFd_[0], &event, 1);
96             if (num > 0) {
97                 DMLOG(DM_LOG_INFO, "DmTimer %s exit with event %d", mTimerName_.c_str(), event);
98             } else {
99                 DMLOG(DM_LOG_ERROR, "DmTimer %s exit with errno %d", mTimerName_.c_str(), errno);
100             }
101         }
102         Release();
103         return;
104     }
105 
106     mHandle_(mHandleData_);
107     Release();
108 
109     DMLOG(DM_LOG_ERROR, "DmTimer %s end timer at (%d)s", mTimerName_.c_str(), mTimeOutSec_);
110     return;
111 }
112 
CreateTimeFd()113 int32_t DmTimer::CreateTimeFd()
114 {
115     DMLOG(DM_LOG_INFO, "DmTimer %s creatTimeFd", mTimerName_.c_str());
116     int ret = 0;
117 
118     ret = pipe(mTimeFd_);
119     if (ret < 0) {
120         DMLOG(DM_LOG_ERROR, "DmTimer %s CreateTimeFd fail:(%d) errno(%d)", mTimerName_.c_str(), ret, errno);
121         return ret;
122     }
123 
124     mEv_.data.fd = mTimeFd_[0];
125     mEv_.events = EPOLLIN | EPOLLET;
126     mEpFd_ = epoll_create(MAXEVENTS);
127     ret = epoll_ctl(mEpFd_, EPOLL_CTL_ADD, mTimeFd_[0], &mEv_);
128     if (ret != 0) {
129         Release();
130     }
131 
132     return ret;
133 }
134 
Release()135 void DmTimer::Release()
136 {
137     DMLOG(DM_LOG_INFO, "DmTimer %s Release in", mTimerName_.c_str());
138     if (mStatus_ == DmTimerStatus::DM_STATUS_INIT) {
139         DMLOG(DM_LOG_INFO, "DmTimer %s already Release", mTimerName_.c_str());
140         return;
141     }
142     mStatus_ = DmTimerStatus::DM_STATUS_INIT;
143     close(mTimeFd_[0]);
144     close(mTimeFd_[1]);
145     if (mEpFd_ >= 0) {
146         close(mEpFd_);
147     }
148     mTimeFd_[0] = 0;
149     mTimeFd_[1] = 0;
150     mEpFd_ = 0;
151 }
152 }
153 }
154