• 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 "le_timer.h"
17 
18 #include <stdio.h>
19 #include <sys/timerfd.h>
20 #include <unistd.h>
21 
22 #include "le_loop.h"
23 #include "le_task.h"
24 #include "loop_event.h"
25 
SetTimer_(int tfd,uint64_t timeout)26 static LE_STATUS SetTimer_(int tfd, uint64_t timeout)
27 {
28     struct itimerspec timeValue;
29     time_t sec = timeout / TIMEOUT_BASE;
30     timeValue.it_interval.tv_sec = sec;
31     long nsec = (timeout % TIMEOUT_BASE) * TIMEOUT_BASE * TIMEOUT_BASE;
32     timeValue.it_interval.tv_nsec = nsec;
33     timeValue.it_value.tv_sec = sec;
34     timeValue.it_value.tv_nsec = nsec;
35     LE_LOGV("SetTimer_ sec %llu tv_nsec %lu", sec, nsec);
36     int ret = timerfd_settime(tfd, 0, &timeValue, NULL);
37     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to set timer %d", errno);
38     return 0;
39 }
40 
HandleTimerEvent_(const LoopHandle loop,const TaskHandle task,uint32_t oper)41 static LE_STATUS HandleTimerEvent_(const LoopHandle loop, const TaskHandle task, uint32_t oper)
42 {
43     if (!LE_TEST_FLAGS(oper, Event_Read)) {
44         return LE_FAILURE;
45     }
46     uint64_t repeat = 0;
47     (void)read(GetSocketFd(task), &repeat, sizeof(repeat));
48     TimerTask *timer = (TimerTask *)task;
49     int fd = GetSocketFd(task);
50     if (timer->processTimer) {
51         uint64_t userData = *(uint64_t *)LE_GetUserData(task);
52         timer->processTimer(task, (void *)userData);
53     }
54     timer = (TimerTask *)GetTaskByFd((EventLoop *)loop, fd);
55     if (timer == NULL) {
56         return LE_SUCCESS;
57     }
58     if (timer->repeat <= repeat) {
59         SetTimer_(fd, 0);
60         return LE_SUCCESS;
61     }
62     timer->repeat -= repeat;
63     return LE_SUCCESS;
64 }
65 
HandleTimerClose_(const LoopHandle loopHandle,const TaskHandle taskHandle)66 static void HandleTimerClose_(const LoopHandle loopHandle, const TaskHandle taskHandle)
67 {
68     BaseTask *task = (BaseTask *)taskHandle;
69     CloseTask(loopHandle, task);
70     DelTask((EventLoop *)loopHandle, task);
71     close(task->taskId.fd);
72 }
73 
LE_CreateTimer(const LoopHandle loopHandle,TimerHandle * timer,LE_ProcessTimer processTimer,void * context)74 LE_STATUS LE_CreateTimer(const LoopHandle loopHandle,
75     TimerHandle *timer, LE_ProcessTimer processTimer, void *context)
76 {
77     LE_CHECK(loopHandle != NULL && timer != NULL, return LE_INVALID_PARAM, "Invalid parameters");
78     LE_CHECK(processTimer != NULL, return LE_FAILURE, "Invalid parameters processTimer");
79     LE_BaseInfo baseInfo = {};
80     baseInfo.flags = TASK_TIME;
81     baseInfo.userDataSize = sizeof(uint64_t);
82     baseInfo.close = NULL;
83     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
84     LE_CHECK(fd >= 0, return LE_FAILURE, "Failed to create timer");
85     SetNoBlock(fd);
86     TimerTask *task = (TimerTask *)CreateTask(loopHandle, fd, &baseInfo, sizeof(TimerTask));
87     LE_CHECK(task != NULL, close(fd);
88         return LE_NO_MEMORY, "Failed to create task");
89     task->base.handleEvent = HandleTimerEvent_;
90     task->base.innerClose = HandleTimerClose_;
91     task->processTimer = processTimer;
92     *(uint64_t *)(task + 1) = (uint64_t)context;
93     *timer = (TimerHandle)task;
94     return LE_SUCCESS;
95 }
96 
LE_StartTimer(const LoopHandle loopHandle,const TimerHandle timer,uint64_t timeout,uint64_t repeat)97 LE_STATUS LE_StartTimer(const LoopHandle loopHandle,
98     const TimerHandle timer, uint64_t timeout, uint64_t repeat)
99 {
100     LE_CHECK(loopHandle != NULL && timer != NULL, return LE_INVALID_PARAM, "Invalid parameters");
101     EventLoop *loop = (EventLoop *)loopHandle;
102     TimerTask *task = (TimerTask *)timer;
103     task->timeout = timeout;
104     task->repeat = repeat;
105     int ret = SetTimer_(GetSocketFd(timer), task->timeout);
106     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to set timer");
107     ret = loop->addEvent(loop, (const BaseTask *)task, Event_Read);
108     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add event");
109     return LE_SUCCESS;
110 }
111 
LE_StopTimer(const LoopHandle loopHandle,const TimerHandle timer)112 void LE_StopTimer(const LoopHandle loopHandle, const TimerHandle timer)
113 {
114     LE_CHECK(loopHandle != NULL && timer != NULL, return, "Invalid parameters");
115     LE_CloseTask(loopHandle, timer);
116 }