• 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 <stdlib.h>
20 #include <sys/timerfd.h>
21 #include <unistd.h>
22 
23 #include "le_loop.h"
24 #include "le_task.h"
25 #include "loop_event.h"
26 
SetTimer_(int tfd,uint64_t timeout)27 static LE_STATUS SetTimer_(int tfd, uint64_t timeout)
28 {
29     struct itimerspec timeValue;
30     time_t sec = timeout / TIMEOUT_BASE;
31     timeValue.it_interval.tv_sec = sec;
32     long nsec = (timeout % TIMEOUT_BASE) * TIMEOUT_BASE;
33     timeValue.it_interval.tv_nsec = nsec;
34     timeValue.it_value.tv_sec = sec;
35     timeValue.it_value.tv_nsec = nsec;
36     LE_LOGV("SetTimer_ sec %lu tv_nsec %lu", sec, nsec);
37     int ret = timerfd_settime(tfd, 0, &timeValue, NULL);
38     LE_CHECK(ret == 0, return LE_FAILURE, "Failed to set timer %d", errno);
39     return 0;
40 }
41 
HandleTimerEvent_(const LoopHandle loop,const TaskHandle task,uint32_t oper)42 static LE_STATUS HandleTimerEvent_(const LoopHandle loop, const TaskHandle task, uint32_t oper)
43 {
44     if (!LE_TEST_FLAGS(oper, Event_Read)) {
45         return LE_FAILURE;
46     }
47     uint64_t repeat = 0;
48     (void)read(GetSocketFd(task), &repeat, sizeof(repeat));
49     TimerTask *timer = (TimerTask *)task;
50     int fd = GetSocketFd(task);
51     if (timer->processTimer) {
52         uint64_t userData = *(uint64_t *)LE_GetUserData(task);
53         timer->processTimer(task, (void *)userData);
54     }
55     timer = (TimerTask *)GetTaskByFd((EventLoop *)loop, fd);
56     if (timer == NULL) {
57         return LE_SUCCESS;
58     }
59     if (timer->repeat <= repeat) {
60         SetTimer_(fd, 0);
61         return LE_SUCCESS;
62     }
63     timer->repeat -= repeat;
64     return LE_SUCCESS;
65 }
66 
HandleTimerClose_(const LoopHandle loopHandle,const TaskHandle taskHandle)67 static void HandleTimerClose_(const LoopHandle loopHandle, const TaskHandle taskHandle)
68 {
69     BaseTask *task = (BaseTask *)taskHandle;
70     CloseTask(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 }