1f9f848faSopenharmony_ci/*-
2f9f848faSopenharmony_ci * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org>
3f9f848faSopenharmony_ci *
4f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without
5f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions
6f9f848faSopenharmony_ci * are met:
7f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright
8f9f848faSopenharmony_ci *    notice unmodified, this list of conditions, and the following
9f9f848faSopenharmony_ci *    disclaimer.
10f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
11f9f848faSopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
12f9f848faSopenharmony_ci *    documentation and/or other materials provided with the distribution.
13f9f848faSopenharmony_ci *
14f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15f9f848faSopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16f9f848faSopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17f9f848faSopenharmony_ci * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18f9f848faSopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19f9f848faSopenharmony_ci * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20f9f848faSopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21f9f848faSopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22f9f848faSopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23f9f848faSopenharmony_ci * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24f9f848faSopenharmony_ci */
25f9f848faSopenharmony_ci
26f9f848faSopenharmony_ci#include "linux/hrtimer.h"
27f9f848faSopenharmony_ci
28f9f848faSopenharmony_ci#include "los_task_pri.h"
29f9f848faSopenharmony_ci#include "los_spinlock.h"
30f9f848faSopenharmony_ci#include "target_config.h"
31f9f848faSopenharmony_ci#include "los_init.h"
32f9f848faSopenharmony_ci
33f9f848faSopenharmony_ci#define US_PER_SECOND 1000000
34f9f848faSopenharmony_ci
35f9f848faSopenharmony_ci/* spinlock for hrtimer module only available on SMP mode */
36f9f848faSopenharmony_ciLITE_OS_SEC_BSS SPIN_LOCK_INIT(g_hrtimerSpin);
37f9f848faSopenharmony_ci
38f9f848faSopenharmony_ciLITE_OS_SEC_BSS struct hrtimer_list_node *g_hrtimerList;
39f9f848faSopenharmony_ci
40f9f848faSopenharmony_ciSTATIC VOID HandlerNodeAdd(struct hrtimer_list_node *htrimer, struct handler_list_node *handlerNode)
41f9f848faSopenharmony_ci{
42f9f848faSopenharmony_ci    struct handler_list_node *tmpNode = NULL;
43f9f848faSopenharmony_ci
44f9f848faSopenharmony_ci    if (htrimer == NULL) {
45f9f848faSopenharmony_ci        return;
46f9f848faSopenharmony_ci    }
47f9f848faSopenharmony_ci
48f9f848faSopenharmony_ci    tmpNode = htrimer->HandlerHead;
49f9f848faSopenharmony_ci    if (tmpNode == NULL) {
50f9f848faSopenharmony_ci        htrimer->HandlerHead = handlerNode;
51f9f848faSopenharmony_ci    } else {
52f9f848faSopenharmony_ci        while (tmpNode->pstNext != NULL) {
53f9f848faSopenharmony_ci            tmpNode = tmpNode->pstNext;
54f9f848faSopenharmony_ci        }
55f9f848faSopenharmony_ci        tmpNode->pstNext = handlerNode;
56f9f848faSopenharmony_ci    } /* FIFO */
57f9f848faSopenharmony_ci}
58f9f848faSopenharmony_ci
59f9f848faSopenharmony_ciSTATIC VOID HrtimerNodeAdd(struct hrtimer_list_node *htrimer, struct handler_list_node *handlerNode)
60f9f848faSopenharmony_ci{
61f9f848faSopenharmony_ci    struct hrtimer_list_node *prevNode = NULL;
62f9f848faSopenharmony_ci    struct hrtimer_list_node *curNode = NULL;
63f9f848faSopenharmony_ci    struct hrtimer_list_node *tmpNode = NULL;
64f9f848faSopenharmony_ci    UINT32 temp;
65f9f848faSopenharmony_ci
66f9f848faSopenharmony_ci    if (g_hrtimerList == NULL) {
67f9f848faSopenharmony_ci        g_hrtimerList = htrimer;
68f9f848faSopenharmony_ci        HrtimerClockStart(htrimer->set_time_reload);
69f9f848faSopenharmony_ci    } else {
70f9f848faSopenharmony_ci        temp = HrtimerClockValueGet();
71f9f848faSopenharmony_ci        g_hrtimerList->set_time_reload = temp;
72f9f848faSopenharmony_ci        curNode = g_hrtimerList;
73f9f848faSopenharmony_ci        while (curNode != NULL) {
74f9f848faSopenharmony_ci            if (curNode->set_time_reload > htrimer->set_time_reload) {
75f9f848faSopenharmony_ci                break;
76f9f848faSopenharmony_ci            }
77f9f848faSopenharmony_ci            if (curNode->set_time_reload == htrimer->set_time_reload) {
78f9f848faSopenharmony_ci                HandlerNodeAdd(curNode, handlerNode);
79f9f848faSopenharmony_ci                (VOID)LOS_MemFree(m_aucSysMem0, htrimer);
80f9f848faSopenharmony_ci                return;
81f9f848faSopenharmony_ci            }
82f9f848faSopenharmony_ci            htrimer->set_time_reload -= curNode->set_time_reload;
83f9f848faSopenharmony_ci            prevNode = curNode;
84f9f848faSopenharmony_ci            curNode = curNode->pstNext;
85f9f848faSopenharmony_ci        }
86f9f848faSopenharmony_ci        if (curNode == g_hrtimerList) {
87f9f848faSopenharmony_ci            tmpNode = g_hrtimerList;
88f9f848faSopenharmony_ci            HrtimerClockStop();
89f9f848faSopenharmony_ci            HrtimerClockStart(htrimer->set_time_reload);
90f9f848faSopenharmony_ci
91f9f848faSopenharmony_ci            tmpNode->set_time_reload -= htrimer->set_time_reload;
92f9f848faSopenharmony_ci            htrimer->pstNext = curNode;
93f9f848faSopenharmony_ci            g_hrtimerList = htrimer;
94f9f848faSopenharmony_ci        } else if (curNode == NULL) {
95f9f848faSopenharmony_ci            prevNode->pstNext = htrimer;
96f9f848faSopenharmony_ci        } else {
97f9f848faSopenharmony_ci            htrimer->pstNext = curNode;
98f9f848faSopenharmony_ci            prevNode->pstNext = htrimer;
99f9f848faSopenharmony_ci            curNode->set_time_reload -= htrimer->set_time_reload;
100f9f848faSopenharmony_ci        }
101f9f848faSopenharmony_ci    }
102f9f848faSopenharmony_ci    if (handlerNode != NULL) {
103f9f848faSopenharmony_ci        HandlerNodeAdd(htrimer, handlerNode);
104f9f848faSopenharmony_ci    }
105f9f848faSopenharmony_ci}
106f9f848faSopenharmony_ci
107f9f848faSopenharmony_ciSTATIC VOID HrtimerHandlerRunAddNode(struct hrtimer_list_node *hrtimer, struct handler_list_node *handlerHead)
108f9f848faSopenharmony_ci{
109f9f848faSopenharmony_ci    if (handlerHead == NULL) {
110f9f848faSopenharmony_ci        (VOID)LOS_MemFree(m_aucSysMem0, hrtimer);
111f9f848faSopenharmony_ci    } else {
112f9f848faSopenharmony_ci        hrtimer->set_time_reload = (UINT32)((hrtimer->_softexpires.tv.sec * US_PER_SECOND +
113f9f848faSopenharmony_ci                                    hrtimer->_softexpires.tv.usec) * HRTIMER_PERUS);
114f9f848faSopenharmony_ci        LOS_SpinLock(&g_hrtimerSpin);
115f9f848faSopenharmony_ci        HrtimerNodeAdd(hrtimer, handlerHead);
116f9f848faSopenharmony_ci        LOS_SpinUnlock(&g_hrtimerSpin);
117f9f848faSopenharmony_ci    }
118f9f848faSopenharmony_ci}
119f9f848faSopenharmony_ci
120f9f848faSopenharmony_ciSTATIC VOID HrtimerHandlerRun(VOID)
121f9f848faSopenharmony_ci{
122f9f848faSopenharmony_ci    struct hrtimer_list_node *hrtimer = NULL;
123f9f848faSopenharmony_ci    struct handler_list_node *curNode = NULL;
124f9f848faSopenharmony_ci    struct handler_list_node *handler = NULL;
125f9f848faSopenharmony_ci    struct handler_list_node *handlerTail = NULL;
126f9f848faSopenharmony_ci    struct handler_list_node *handlerHead = NULL;
127f9f848faSopenharmony_ci    struct hrtimer timer;
128f9f848faSopenharmony_ci    enum hrtimer_restart restart;
129f9f848faSopenharmony_ci
130f9f848faSopenharmony_ci    LOS_SpinLock(&g_hrtimerSpin);
131f9f848faSopenharmony_ci    if (g_hrtimerList == NULL) {
132f9f848faSopenharmony_ci        LOS_SpinUnlock(&g_hrtimerSpin);
133f9f848faSopenharmony_ci        return;
134f9f848faSopenharmony_ci    }
135f9f848faSopenharmony_ci    hrtimer = g_hrtimerList;
136f9f848faSopenharmony_ci    g_hrtimerList = hrtimer->pstNext;
137f9f848faSopenharmony_ci    if (g_hrtimerList != NULL) {
138f9f848faSopenharmony_ci        HrtimerClockStop();
139f9f848faSopenharmony_ci        HrtimerClockStart(g_hrtimerList->set_time_reload);
140f9f848faSopenharmony_ci    }
141f9f848faSopenharmony_ci    LOS_SpinUnlock(&g_hrtimerSpin);
142f9f848faSopenharmony_ci
143f9f848faSopenharmony_ci    timer._softexpires.tv.usec = hrtimer->_softexpires.tv.usec;
144f9f848faSopenharmony_ci    timer._softexpires.tv.sec = hrtimer->_softexpires.tv.sec;
145f9f848faSopenharmony_ci    handler = hrtimer->HandlerHead;
146f9f848faSopenharmony_ci    hrtimer->pstNext = NULL;
147f9f848faSopenharmony_ci    hrtimer->HandlerHead = NULL;
148f9f848faSopenharmony_ci
149f9f848faSopenharmony_ci    while ((handler != NULL) && (handler->pfnHandler != NULL)) {
150f9f848faSopenharmony_ci        timer.function = handler->pfnHandler;
151f9f848faSopenharmony_ci        restart = handler->pfnHandler(&timer);
152f9f848faSopenharmony_ci        curNode = handler;
153f9f848faSopenharmony_ci        handler = handler->pstNext;
154f9f848faSopenharmony_ci        curNode->pstNext = NULL;
155f9f848faSopenharmony_ci
156f9f848faSopenharmony_ci        if (restart == HRTIMER_NORESTART) {
157f9f848faSopenharmony_ci            (VOID)LOS_MemFree(m_aucSysMem0, curNode);
158f9f848faSopenharmony_ci        } else if (restart == HRTIMER_RESTART) {
159f9f848faSopenharmony_ci            if (handlerHead != NULL) {
160f9f848faSopenharmony_ci                handlerTail->pstNext = curNode;
161f9f848faSopenharmony_ci                handlerTail = curNode;
162f9f848faSopenharmony_ci            } else {
163f9f848faSopenharmony_ci                handlerHead = curNode;
164f9f848faSopenharmony_ci                handlerTail = curNode;
165f9f848faSopenharmony_ci            }
166f9f848faSopenharmony_ci        } else {
167f9f848faSopenharmony_ci            PRINT_ERR("The return value of hrtimer function is not defined!\n");
168f9f848faSopenharmony_ci        }
169f9f848faSopenharmony_ci    }
170f9f848faSopenharmony_ci
171f9f848faSopenharmony_ci    HrtimerHandlerRunAddNode(hrtimer, handlerHead);
172f9f848faSopenharmony_ci}
173f9f848faSopenharmony_ci
174f9f848faSopenharmony_ciSTATIC VOID HrtimerListScan(VOID)
175f9f848faSopenharmony_ci{
176f9f848faSopenharmony_ci    HrtimerClockIrqClear();
177f9f848faSopenharmony_ci    HrtimerHandlerRun();
178f9f848faSopenharmony_ci}
179f9f848faSopenharmony_ci
180f9f848faSopenharmony_ciSTATIC VOID GetHandlerNodePosition(const struct hrtimer *timer, struct hrtimer_list_node *hrtimerNode,
181f9f848faSopenharmony_ci                                   struct handler_list_node **prevNode, struct handler_list_node **curNode)
182f9f848faSopenharmony_ci{
183f9f848faSopenharmony_ci    struct handler_list_node *curHandler = NULL;
184f9f848faSopenharmony_ci    struct handler_list_node *prevHandler = NULL;
185f9f848faSopenharmony_ci
186f9f848faSopenharmony_ci    curHandler = hrtimerNode->HandlerHead;
187f9f848faSopenharmony_ci    while (curHandler != NULL) {
188f9f848faSopenharmony_ci        if ((curHandler->pfnHandler == timer->function) &&
189f9f848faSopenharmony_ci            (curHandler->_softexpires.tv.sec == timer->_softexpires.tv.sec) &&
190f9f848faSopenharmony_ci            (curHandler->_softexpires.tv.usec == timer->_softexpires.tv.usec)) {
191f9f848faSopenharmony_ci            *prevNode = prevHandler;
192f9f848faSopenharmony_ci            *curNode = curHandler;
193f9f848faSopenharmony_ci            return;
194f9f848faSopenharmony_ci        }
195f9f848faSopenharmony_ci        prevHandler = curHandler;
196f9f848faSopenharmony_ci        curHandler = curHandler->pstNext;
197f9f848faSopenharmony_ci    }
198f9f848faSopenharmony_ci}
199f9f848faSopenharmony_ci
200f9f848faSopenharmony_ciSTATIC VOID GetHrtimerNodePosition(const struct hrtimer *timer, struct hrtimer_list_node **prevNode,
201f9f848faSopenharmony_ci                                   struct hrtimer_list_node **curNode)
202f9f848faSopenharmony_ci{
203f9f848faSopenharmony_ci    struct handler_list_node *curHandler = NULL;
204f9f848faSopenharmony_ci
205f9f848faSopenharmony_ci    *curNode = g_hrtimerList;
206f9f848faSopenharmony_ci    while (*curNode != NULL) {
207f9f848faSopenharmony_ci        curHandler = (*curNode)->HandlerHead;
208f9f848faSopenharmony_ci        while (curHandler != NULL) {
209f9f848faSopenharmony_ci            if ((curHandler->pfnHandler == timer->function) &&
210f9f848faSopenharmony_ci                (curHandler->_softexpires.tv.sec == timer->_softexpires.tv.sec) &&
211f9f848faSopenharmony_ci                (curHandler->_softexpires.tv.usec == timer->_softexpires.tv.usec)) {
212f9f848faSopenharmony_ci                return;
213f9f848faSopenharmony_ci            }
214f9f848faSopenharmony_ci            curHandler = curHandler->pstNext;
215f9f848faSopenharmony_ci        }
216f9f848faSopenharmony_ci        *prevNode = *curNode;
217f9f848faSopenharmony_ci        *curNode = (*curNode)->pstNext;
218f9f848faSopenharmony_ci    }
219f9f848faSopenharmony_ci}
220f9f848faSopenharmony_ci
221f9f848faSopenharmony_ciSTATIC struct hrtimer_list_node *HrtimerListNodeInit(union ktime time)
222f9f848faSopenharmony_ci{
223f9f848faSopenharmony_ci    struct hrtimer_list_node *hrtimer = (struct hrtimer_list_node *)LOS_MemAlloc(m_aucSysMem0,
224f9f848faSopenharmony_ci                                                                                 sizeof(struct hrtimer_list_node));
225f9f848faSopenharmony_ci    if (hrtimer == NULL) {
226f9f848faSopenharmony_ci        return NULL;
227f9f848faSopenharmony_ci    }
228f9f848faSopenharmony_ci    hrtimer->_softexpires = time;
229f9f848faSopenharmony_ci    hrtimer->set_time_reload = (UINT32)((time.tv.sec * US_PER_SECOND + time.tv.usec) * HRTIMER_PERUS);
230f9f848faSopenharmony_ci    hrtimer->HandlerHead = NULL;
231f9f848faSopenharmony_ci    hrtimer->pstNext = NULL;
232f9f848faSopenharmony_ci    return hrtimer;
233f9f848faSopenharmony_ci}
234f9f848faSopenharmony_ci
235f9f848faSopenharmony_ciSTATIC UINT32 ChangeNodePosition(struct hrtimer_list_node *prevNode, struct hrtimer_list_node *curNode,
236f9f848faSopenharmony_ci                                 struct handler_list_node *prevHandler, struct handler_list_node *curHandler,
237f9f848faSopenharmony_ci                                 union ktime time)
238f9f848faSopenharmony_ci{
239f9f848faSopenharmony_ci    struct hrtimer_list_node *htrimer = NULL;
240f9f848faSopenharmony_ci
241f9f848faSopenharmony_ci    if ((prevHandler != NULL) || (curHandler->pstNext != NULL)) {
242f9f848faSopenharmony_ci        if (prevHandler == NULL) {
243f9f848faSopenharmony_ci            curNode->HandlerHead = curHandler->pstNext;
244f9f848faSopenharmony_ci        } else {
245f9f848faSopenharmony_ci            prevHandler->pstNext = curHandler->pstNext;
246f9f848faSopenharmony_ci        }
247f9f848faSopenharmony_ci
248f9f848faSopenharmony_ci        curHandler->pstNext = NULL;
249f9f848faSopenharmony_ci        curHandler->_softexpires = time;
250f9f848faSopenharmony_ci
251f9f848faSopenharmony_ci        htrimer = HrtimerListNodeInit(time);
252f9f848faSopenharmony_ci        if (htrimer == NULL) {
253f9f848faSopenharmony_ci            return LOS_NOK;
254f9f848faSopenharmony_ci        }
255f9f848faSopenharmony_ci
256f9f848faSopenharmony_ci        HrtimerNodeAdd(htrimer, curHandler);
257f9f848faSopenharmony_ci    } else {
258f9f848faSopenharmony_ci        if (curNode->pstNext != NULL) {
259f9f848faSopenharmony_ci            if (curNode == g_hrtimerList) {
260f9f848faSopenharmony_ci                g_hrtimerList = curNode->pstNext;
261f9f848faSopenharmony_ci                g_hrtimerList->set_time_reload += HrtimerClockValueGet();
262f9f848faSopenharmony_ci                HrtimerClockStop();
263f9f848faSopenharmony_ci                HrtimerClockStart(g_hrtimerList->set_time_reload);
264f9f848faSopenharmony_ci            } else {
265f9f848faSopenharmony_ci                prevNode->pstNext = curNode->pstNext;
266f9f848faSopenharmony_ci                curNode->pstNext->set_time_reload += curNode->set_time_reload;
267f9f848faSopenharmony_ci            }
268f9f848faSopenharmony_ci        } else {
269f9f848faSopenharmony_ci            if (curNode == g_hrtimerList) {
270f9f848faSopenharmony_ci                g_hrtimerList = NULL;
271f9f848faSopenharmony_ci                HrtimerClockStop();
272f9f848faSopenharmony_ci            } else {
273f9f848faSopenharmony_ci                prevNode->pstNext = NULL;
274f9f848faSopenharmony_ci            }
275f9f848faSopenharmony_ci        }
276f9f848faSopenharmony_ci        curNode->pstNext = NULL;
277f9f848faSopenharmony_ci        curNode->_softexpires = time;
278f9f848faSopenharmony_ci        curNode->set_time_reload = (UINT32)((time.tv.sec * US_PER_SECOND + time.tv.usec) * HRTIMER_PERUS);
279f9f848faSopenharmony_ci        curNode->HandlerHead->_softexpires = time;
280f9f848faSopenharmony_ci        HrtimerNodeAdd(curNode, NULL);
281f9f848faSopenharmony_ci    }
282f9f848faSopenharmony_ci
283f9f848faSopenharmony_ci    return LOS_OK;
284f9f848faSopenharmony_ci}
285f9f848faSopenharmony_ci
286f9f848faSopenharmony_ciSTATIC VOID CancelHandlerNode(const struct hrtimer *timer, struct hrtimer_list_node *curNode)
287f9f848faSopenharmony_ci{
288f9f848faSopenharmony_ci    struct handler_list_node *curHandler = curNode->HandlerHead;
289f9f848faSopenharmony_ci    struct handler_list_node *prevHandler = curHandler;
290f9f848faSopenharmony_ci
291f9f848faSopenharmony_ci    while (curHandler != NULL) {
292f9f848faSopenharmony_ci        if ((curHandler->pfnHandler == timer->function) &&
293f9f848faSopenharmony_ci            (curHandler->_softexpires.tv.sec == timer->_softexpires.tv.sec) &&
294f9f848faSopenharmony_ci            (curHandler->_softexpires.tv.usec == timer->_softexpires.tv.usec)) {
295f9f848faSopenharmony_ci            if (curHandler == curNode->HandlerHead) {
296f9f848faSopenharmony_ci                curNode->HandlerHead = curHandler->pstNext;
297f9f848faSopenharmony_ci            } else {
298f9f848faSopenharmony_ci                prevHandler->pstNext = curHandler->pstNext;
299f9f848faSopenharmony_ci            }
300f9f848faSopenharmony_ci            curHandler->pstNext = NULL;
301f9f848faSopenharmony_ci            (VOID)LOS_MemFree(m_aucSysMem0, curHandler);
302f9f848faSopenharmony_ci            break;
303f9f848faSopenharmony_ci        }
304f9f848faSopenharmony_ci        prevHandler = curHandler;
305f9f848faSopenharmony_ci        curHandler = curHandler->pstNext;
306f9f848faSopenharmony_ci    }
307f9f848faSopenharmony_ci}
308f9f848faSopenharmony_ci
309f9f848faSopenharmony_ciSTATIC UINT32 CheckTime(union ktime *time)
310f9f848faSopenharmony_ci{
311f9f848faSopenharmony_ci    if ((time->tv.sec == 0) && (time->tv.usec == 0)) {
312f9f848faSopenharmony_ci        return LOS_NOK;
313f9f848faSopenharmony_ci    }
314f9f848faSopenharmony_ci
315f9f848faSopenharmony_ci    if (time->tv.usec >= US_PER_SECOND) {
316f9f848faSopenharmony_ci        time->tv.sec += time->tv.usec / US_PER_SECOND;
317f9f848faSopenharmony_ci        time->tv.usec = time->tv.usec % US_PER_SECOND;
318f9f848faSopenharmony_ci    }
319f9f848faSopenharmony_ci
320f9f848faSopenharmony_ci    return LOS_OK;
321f9f848faSopenharmony_ci}
322f9f848faSopenharmony_ci
323f9f848faSopenharmony_civoid linux_hrtimer_init(struct hrtimer *timer, clockid_t clockID, enum hrtimer_mode mode)
324f9f848faSopenharmony_ci{
325f9f848faSopenharmony_ci    (VOID)clockID;
326f9f848faSopenharmony_ci    if ((timer == NULL) || (mode != HRTIMER_MODE_REL)) {
327f9f848faSopenharmony_ci        PRINT_ERR("The timer is NULL OR The mode is not HRTIMER_MODE_REL!\n");
328f9f848faSopenharmony_ci    }
329f9f848faSopenharmony_ci    return;
330f9f848faSopenharmony_ci}
331f9f848faSopenharmony_ci
332f9f848faSopenharmony_ciint linux_hrtimer_create(struct hrtimer *timer, union ktime time, Handler handler)
333f9f848faSopenharmony_ci{
334f9f848faSopenharmony_ci    UINT32 ret;
335f9f848faSopenharmony_ci
336f9f848faSopenharmony_ci    if ((timer == NULL) || (handler == NULL)) {
337f9f848faSopenharmony_ci        return -1;
338f9f848faSopenharmony_ci    }
339f9f848faSopenharmony_ci
340f9f848faSopenharmony_ci    ret = CheckTime(&time);
341f9f848faSopenharmony_ci    if (ret != LOS_OK) {
342f9f848faSopenharmony_ci        return -1;
343f9f848faSopenharmony_ci    }
344f9f848faSopenharmony_ci
345f9f848faSopenharmony_ci    timer->_softexpires.tv.sec = time.tv.sec;
346f9f848faSopenharmony_ci    timer->_softexpires.tv.usec = time.tv.usec;
347f9f848faSopenharmony_ci    timer->function = handler;
348f9f848faSopenharmony_ci
349f9f848faSopenharmony_ci    return 0;
350f9f848faSopenharmony_ci}
351f9f848faSopenharmony_ci
352f9f848faSopenharmony_ciSTATIC struct handler_list_node *HandleNodeInit(union ktime time, struct hrtimer *timer)
353f9f848faSopenharmony_ci{
354f9f848faSopenharmony_ci    struct handler_list_node *handler = NULL;
355f9f848faSopenharmony_ci    handler = (struct handler_list_node *)LOS_MemAlloc(m_aucSysMem0, sizeof(struct handler_list_node));
356f9f848faSopenharmony_ci    if (handler == NULL) {
357f9f848faSopenharmony_ci        return NULL;
358f9f848faSopenharmony_ci    }
359f9f848faSopenharmony_ci    handler->_softexpires = time;
360f9f848faSopenharmony_ci    handler->pfnHandler = timer->function;
361f9f848faSopenharmony_ci    handler->pstNext = NULL;
362f9f848faSopenharmony_ci    return handler;
363f9f848faSopenharmony_ci}
364f9f848faSopenharmony_ci
365f9f848faSopenharmony_ciint linux_hrtimer_start(struct hrtimer *timer, union ktime time, const enum hrtimer_mode mode)
366f9f848faSopenharmony_ci{
367f9f848faSopenharmony_ci    struct hrtimer_list_node *hrtimer = NULL;
368f9f848faSopenharmony_ci    struct hrtimer_list_node *prevNode = NULL;
369f9f848faSopenharmony_ci    struct hrtimer_list_node *curNode = NULL;
370f9f848faSopenharmony_ci    struct handler_list_node *handler = NULL;
371f9f848faSopenharmony_ci    struct handler_list_node *prevHandler = NULL;
372f9f848faSopenharmony_ci    struct handler_list_node *curHandler = NULL;
373f9f848faSopenharmony_ci    UINT32 intSave;
374f9f848faSopenharmony_ci
375f9f848faSopenharmony_ci    if ((timer == NULL) || (mode != HRTIMER_MODE_REL)) {
376f9f848faSopenharmony_ci        return -1;
377f9f848faSopenharmony_ci    }
378f9f848faSopenharmony_ci
379f9f848faSopenharmony_ci    if (CheckTime(&time) != LOS_OK) {
380f9f848faSopenharmony_ci        return -1;
381f9f848faSopenharmony_ci    }
382f9f848faSopenharmony_ci
383f9f848faSopenharmony_ci    LOS_SpinLockSave(&g_hrtimerSpin, &intSave);
384f9f848faSopenharmony_ci    GetHrtimerNodePosition(timer, &prevNode, &curNode);
385f9f848faSopenharmony_ci    if (curNode == NULL) {
386f9f848faSopenharmony_ci        LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
387f9f848faSopenharmony_ci        if (timer->function == NULL) {
388f9f848faSopenharmony_ci            return -1;
389f9f848faSopenharmony_ci        }
390f9f848faSopenharmony_ci        hrtimer = HrtimerListNodeInit(time);
391f9f848faSopenharmony_ci        if (hrtimer == NULL) {
392f9f848faSopenharmony_ci            return -1;
393f9f848faSopenharmony_ci        }
394f9f848faSopenharmony_ci        handler = HandleNodeInit(time, timer);
395f9f848faSopenharmony_ci        if (handler == NULL) {
396f9f848faSopenharmony_ci            (VOID)LOS_MemFree(m_aucSysMem0, hrtimer);
397f9f848faSopenharmony_ci            return -1;
398f9f848faSopenharmony_ci        }
399f9f848faSopenharmony_ci
400f9f848faSopenharmony_ci        LOS_SpinLockSave(&g_hrtimerSpin, &intSave);
401f9f848faSopenharmony_ci        HrtimerNodeAdd(hrtimer, handler);
402f9f848faSopenharmony_ci        LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
403f9f848faSopenharmony_ci        return 0;
404f9f848faSopenharmony_ci    } else {
405f9f848faSopenharmony_ci        GetHandlerNodePosition(timer, curNode, &prevHandler, &curHandler);
406f9f848faSopenharmony_ci        if (ChangeNodePosition(prevNode, curNode, prevHandler, curHandler, time) == LOS_OK) {
407f9f848faSopenharmony_ci            LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
408f9f848faSopenharmony_ci            return 1;
409f9f848faSopenharmony_ci        }
410f9f848faSopenharmony_ci    }
411f9f848faSopenharmony_ci
412f9f848faSopenharmony_ci    LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
413f9f848faSopenharmony_ci    return -1;
414f9f848faSopenharmony_ci}
415f9f848faSopenharmony_ci
416f9f848faSopenharmony_ciint linux_hrtimer_cancel(struct hrtimer *timer)
417f9f848faSopenharmony_ci{
418f9f848faSopenharmony_ci    struct hrtimer_list_node *prevNode = NULL;
419f9f848faSopenharmony_ci    struct hrtimer_list_node *curNode = NULL;
420f9f848faSopenharmony_ci    UINT32 intSave;
421f9f848faSopenharmony_ci
422f9f848faSopenharmony_ci    if (timer == NULL) {
423f9f848faSopenharmony_ci        return -1;
424f9f848faSopenharmony_ci    }
425f9f848faSopenharmony_ci
426f9f848faSopenharmony_ci    LOS_SpinLockSave(&g_hrtimerSpin, &intSave);
427f9f848faSopenharmony_ci    curNode = g_hrtimerList;
428f9f848faSopenharmony_ci    if (curNode == NULL) {
429f9f848faSopenharmony_ci        LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
430f9f848faSopenharmony_ci        return 0;
431f9f848faSopenharmony_ci    }
432f9f848faSopenharmony_ci
433f9f848faSopenharmony_ci    GetHrtimerNodePosition(timer, &prevNode, &curNode);
434f9f848faSopenharmony_ci
435f9f848faSopenharmony_ci    if (curNode == NULL) {
436f9f848faSopenharmony_ci        LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
437f9f848faSopenharmony_ci        return 0;
438f9f848faSopenharmony_ci    } else if (curNode == g_hrtimerList) {
439f9f848faSopenharmony_ci        CancelHandlerNode(timer, curNode);
440f9f848faSopenharmony_ci
441f9f848faSopenharmony_ci        if (curNode->HandlerHead == NULL) {
442f9f848faSopenharmony_ci            g_hrtimerList = curNode->pstNext;
443f9f848faSopenharmony_ci            if (g_hrtimerList != NULL) {
444f9f848faSopenharmony_ci                g_hrtimerList->set_time_reload += HrtimerClockValueGet();
445f9f848faSopenharmony_ci                HrtimerClockStop();
446f9f848faSopenharmony_ci                HrtimerClockStart(g_hrtimerList->set_time_reload);
447f9f848faSopenharmony_ci            } else {
448f9f848faSopenharmony_ci                HrtimerClockStop();
449f9f848faSopenharmony_ci            }
450f9f848faSopenharmony_ci            curNode->pstNext = NULL;
451f9f848faSopenharmony_ci            (VOID)LOS_MemFree(m_aucSysMem0, curNode);
452f9f848faSopenharmony_ci        }
453f9f848faSopenharmony_ci    } else {
454f9f848faSopenharmony_ci        CancelHandlerNode(timer, curNode);
455f9f848faSopenharmony_ci
456f9f848faSopenharmony_ci        if (curNode->HandlerHead == NULL) {
457f9f848faSopenharmony_ci            if (curNode->pstNext == NULL) {
458f9f848faSopenharmony_ci                prevNode->pstNext = NULL;
459f9f848faSopenharmony_ci            } else {
460f9f848faSopenharmony_ci                prevNode->pstNext = curNode->pstNext;
461f9f848faSopenharmony_ci                prevNode->pstNext->set_time_reload += curNode->set_time_reload;
462f9f848faSopenharmony_ci            }
463f9f848faSopenharmony_ci            curNode->pstNext = NULL;
464f9f848faSopenharmony_ci            (VOID)LOS_MemFree(m_aucSysMem0, curNode);
465f9f848faSopenharmony_ci        }
466f9f848faSopenharmony_ci    }
467f9f848faSopenharmony_ci    LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
468f9f848faSopenharmony_ci    return 1;
469f9f848faSopenharmony_ci}
470f9f848faSopenharmony_ci
471f9f848faSopenharmony_ciu64 linux_hrtimer_forward(struct hrtimer *timer, union ktime interval)
472f9f848faSopenharmony_ci{
473f9f848faSopenharmony_ci    struct hrtimer_list_node *prevNode = NULL;
474f9f848faSopenharmony_ci    struct hrtimer_list_node *curNode = NULL;
475f9f848faSopenharmony_ci    struct handler_list_node *prevHandler = NULL;
476f9f848faSopenharmony_ci    struct handler_list_node *curHandler = NULL;
477f9f848faSopenharmony_ci    UINT32 intSave;
478f9f848faSopenharmony_ci    UINT32 ret;
479f9f848faSopenharmony_ci
480f9f848faSopenharmony_ci    if (timer == NULL) {
481f9f848faSopenharmony_ci        return 0;
482f9f848faSopenharmony_ci    }
483f9f848faSopenharmony_ci
484f9f848faSopenharmony_ci    ret = CheckTime(&interval);
485f9f848faSopenharmony_ci    if (ret != LOS_OK) {
486f9f848faSopenharmony_ci        return 0;
487f9f848faSopenharmony_ci    }
488f9f848faSopenharmony_ci
489f9f848faSopenharmony_ci    LOS_SpinLockSave(&g_hrtimerSpin, &intSave);
490f9f848faSopenharmony_ci    GetHrtimerNodePosition(timer, &prevNode, &curNode);
491f9f848faSopenharmony_ci    if (curNode == NULL) {
492f9f848faSopenharmony_ci        LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
493f9f848faSopenharmony_ci        return 0;
494f9f848faSopenharmony_ci    }
495f9f848faSopenharmony_ci    GetHandlerNodePosition(timer, curNode, &prevHandler, &curHandler);
496f9f848faSopenharmony_ci    timer->_softexpires = interval;
497f9f848faSopenharmony_ci    ret = ChangeNodePosition(prevNode, curNode, prevHandler, curHandler, interval);
498f9f848faSopenharmony_ci    LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
499f9f848faSopenharmony_ci    if (ret != LOS_OK) {
500f9f848faSopenharmony_ci        return 0;
501f9f848faSopenharmony_ci    } else {
502f9f848faSopenharmony_ci        return (u64)((interval.tv.sec * US_PER_SECOND + interval.tv.usec) * HRTIMER_PERUS);
503f9f848faSopenharmony_ci    }
504f9f848faSopenharmony_ci}
505f9f848faSopenharmony_ci
506f9f848faSopenharmony_ciint linux_hrtimer_is_queued(struct hrtimer *timer)
507f9f848faSopenharmony_ci{
508f9f848faSopenharmony_ci    struct hrtimer_list_node *curNode = NULL;
509f9f848faSopenharmony_ci    struct handler_list_node *handler = NULL;
510f9f848faSopenharmony_ci    INT32 ret = LOS_NOK;
511f9f848faSopenharmony_ci    UINT32 intSave;
512f9f848faSopenharmony_ci
513f9f848faSopenharmony_ci    if (timer == NULL) {
514f9f848faSopenharmony_ci        return -1;
515f9f848faSopenharmony_ci    }
516f9f848faSopenharmony_ci
517f9f848faSopenharmony_ci    LOS_SpinLockSave(&g_hrtimerSpin, &intSave);
518f9f848faSopenharmony_ci    curNode = g_hrtimerList;
519f9f848faSopenharmony_ci    while (curNode != NULL) {
520f9f848faSopenharmony_ci        handler = curNode->HandlerHead;
521f9f848faSopenharmony_ci        while (handler != NULL) {
522f9f848faSopenharmony_ci            if (handler->pfnHandler == timer->function) {
523f9f848faSopenharmony_ci                break;
524f9f848faSopenharmony_ci            }
525f9f848faSopenharmony_ci            handler = handler->pstNext;
526f9f848faSopenharmony_ci        }
527f9f848faSopenharmony_ci
528f9f848faSopenharmony_ci        if ((handler != NULL) && (handler->pfnHandler == timer->function) &&
529f9f848faSopenharmony_ci            (handler->_softexpires.tv.sec == timer->_softexpires.tv.sec) &&
530f9f848faSopenharmony_ci            (handler->_softexpires.tv.usec == timer->_softexpires.tv.usec)) {
531f9f848faSopenharmony_ci            ret = LOS_OK;
532f9f848faSopenharmony_ci            break;
533f9f848faSopenharmony_ci        }
534f9f848faSopenharmony_ci        curNode = curNode->pstNext;
535f9f848faSopenharmony_ci    }
536f9f848faSopenharmony_ci    LOS_SpinUnlockRestore(&g_hrtimerSpin, intSave);
537f9f848faSopenharmony_ci
538f9f848faSopenharmony_ci    return ret;
539f9f848faSopenharmony_ci}
540f9f848faSopenharmony_ci
541f9f848faSopenharmony_ciUINT32 HrtimersInit(VOID)
542f9f848faSopenharmony_ci{
543f9f848faSopenharmony_ci    UINT32 ret;
544f9f848faSopenharmony_ci
545f9f848faSopenharmony_ci    g_hrtimerList = NULL;
546f9f848faSopenharmony_ci    /* Initialize the timer */
547f9f848faSopenharmony_ci    HrtimerClockInit();
548f9f848faSopenharmony_ci    /* Create interrupt of the timer */
549f9f848faSopenharmony_ci    ret = LOS_HwiCreate(NUM_HAL_INTERRUPT_HRTIMER, 0, 0, HrtimerListScan, 0);
550f9f848faSopenharmony_ci    if (ret != LOS_OK) {
551f9f848faSopenharmony_ci        return LOS_NOK;
552f9f848faSopenharmony_ci    }
553f9f848faSopenharmony_ci    HalIrqUnmask(NUM_HAL_INTERRUPT_HRTIMER);
554f9f848faSopenharmony_ci
555f9f848faSopenharmony_ci    return LOS_OK;
556f9f848faSopenharmony_ci}
557f9f848faSopenharmony_ci
558f9f848faSopenharmony_ciLOS_MODULE_INIT(HrtimersInit, LOS_INIT_LEVEL_PLATFROM_EARLY);
559