• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2009-12-22
13  * Description: 软件定时器模块的C文件
14  */
15 #include "prt_swtmr_internal.h"
16 
OsSwtmrProc(struct TagSwTmrCtrl * swtmr)17 OS_SEC_ALW_INLINE INLINE void OsSwtmrProc(struct TagSwTmrCtrl *swtmr)
18 {
19     switch (swtmr->state & OS_SWTMR_PRE_STATUS_MASK) {
20         /* 为了超时状态未改变的情况下执行效率,先对定时器的此种状态进行处理 */
21         case OS_SWTMR_STATUS_DEFAULT:
22             if (swtmr->mode == (U8)OS_TIMER_LOOP) {
23                 OsSwTmrStart(swtmr, swtmr->interval);
24             } else {
25                 swtmr->idxRollNum = 0;
26                 swtmr->state = (U8)OS_TIMER_CREATED;
27             }
28             break;
29         case OS_SWTMR_PRE_RUNNING:
30             OsSwTmrStart(swtmr, swtmr->interval);
31             break;
32         case OS_SWTMR_PRE_CREATED:
33             // ,定时器超时处理后,剩余时间置为0,启动定时器时再赋值swtmr->interval
34             swtmr->idxRollNum = 0;
35             swtmr->state = (U8)OS_TIMER_CREATED;
36             break;
37         case OS_SWTMR_PRE_FREE:
38             OsSwTmrDelete(swtmr);
39             break;
40         default:
41             break;
42     }
43     return;
44 }
45 
46 /*
47  * 描述:调用本函数需要先锁上timer, 调用osIntLock
48  */
OsSwTmrScanProcess(struct TagListObject * object,struct TagListObject * listObject,struct TagSwTmrSortLinkAttr * tmrSort,struct TagSwTmrCtrl * outLink)49 OS_SEC_ALW_INLINE INLINE void OsSwTmrScanProcess(struct TagListObject *object, struct TagListObject *listObject,
50                                                  struct TagSwTmrSortLinkAttr *tmrSort, struct TagSwTmrCtrl *outLink)
51 {
52     /*
53      * 处理3种情况
54      * [1] 如果第一个节点的rollNum就大于0,则outLink=NULL。
55      * [2] 如果是从中间跳出,则第一个rollNum非0节点为swtmr,前面的定时器为超时定时器。
56      * 最后一个超时定时器的next置为NULL,listObject->next指向swtmr。
57      * swtmr->prev指向listObject。
58      * [3] 如果全部节点都超时,则是从while条件语句跳出。swtmr为listObject。
59      * 最后一个定时器的next置为NULL,listObject->next指向swtmr即本身。
60      * swtmr->prev指向listObject即本身。
61      */
62     struct TagSwTmrCtrl *temp = NULL;
63     struct TagSwTmrCtrl *swtmr = (struct TagSwTmrCtrl *)object->next;
64     (void)tmrSort;
65     object->next = NULL;
66     /* 更新SortLink成员next指针 */
67     listObject->next = (struct TagListObject *)swtmr;
68     /* 第一个rollNum非0节点的prev指针指向SortLink成员 */
69     swtmr->prev = (struct TagSwTmrCtrl *)listObject;
70     (void)OsIntUnLock();
71 
72     /* 处理超时链表中的定时器 */
73     swtmr = outLink;
74     while ((swtmr != NULL) && (swtmr != (struct TagSwTmrCtrl *)listObject)) {
75         temp = swtmr->next;
76         swtmr->handler(OS_SWTMR_INDEX_2_ID(swtmr->swtmrIndex), swtmr->arg1, swtmr->arg2, swtmr->arg3, swtmr->arg4);
77 
78         (void)OsIntLock();
79 
80         swtmr->prev = NULL;
81         swtmr->next = NULL;
82         OsSwtmrProc(swtmr);
83 
84         (void)OsIntUnLock();
85 
86         swtmr = temp;
87     }
88 }
89 
90 /*
91  * 描述:软件定时器模块的Tick中断运行接口
92  */
OsSwTmrScan(void)93 OS_SEC_TEXT void OsSwTmrScan(void)
94 {
95     struct TagSwTmrCtrl *swtmr = NULL;
96     struct TagSwTmrCtrl *outLink = NULL;
97     struct TagListObject *listObject = NULL;
98     struct TagListObject *object = NULL;
99     uintptr_t intSave;
100 
101     /*
102      * 扫描计时链表,把超时定时器从计时链表中删除,状态置为OUT状态
103      * 超时的定时器形成超时链表(从首节点到第一个rollNum非0节点)。
104      */
105     intSave = OsIntLock();
106 
107     g_tmrSortLink.cursor = (g_tmrSortLink.cursor + 1) % OS_SWTMR_SORTLINK_LEN;
108     /*
109      * 从计时链表中获取超时链表
110      */
111     listObject = g_tmrSortLink.sortLink + g_tmrSortLink.cursor;
112     if (listObject->next == listObject) { /* 没有计时定时器 */
113         OsIntRestore(intSave);
114         return;
115     }
116 
117     outLink = (struct TagSwTmrCtrl *)listObject->next;
118     object = listObject;
119     while (object->next != listObject) {
120         swtmr = (struct TagSwTmrCtrl *)object->next;
121         if (UWROLLNUM(swtmr->idxRollNum) > 0) {
122             UWROLLNUMDEC(swtmr->idxRollNum);
123             if (swtmr->prev == (struct TagSwTmrCtrl *)listObject) {
124                 /*
125                  * 如果第一个定时器rollNum>0,则表示没有超时链表为空
126                  */
127                 outLink = NULL;
128             }
129             break;
130         }
131         swtmr->state = (U8)OS_TIMER_EXPIRED;
132         object = object->next;
133     }
134 
135     OsSwTmrScanProcess(object, listObject, NULL, outLink);
136 
137     return;
138 }
139 
OsSwtmrCtrlInit(struct TagSwTmrCtrl * swtmr,U32 interval)140 OS_SEC_ALW_INLINE INLINE struct TagListObject *OsSwtmrCtrlInit(struct TagSwTmrCtrl *swtmr, U32 interval)
141 {
142     U32 sortIndex;
143     U32 rollNum;
144 
145     sortIndex = interval & OS_SWTMR_SORTLINK_MASK;
146     rollNum = (interval / OS_SWTMR_SORTLINK_LEN);
147     (sortIndex > 0) ? 0 : (rollNum--);
148     EVALUATE_L(swtmr->idxRollNum, rollNum);
149     sortIndex = (sortIndex + g_tmrSortLink.cursor);
150     /* sortIndex % 64; */
151     sortIndex = sortIndex & OS_SWTMR_SORTLINK_MASK;
152     EVALUATE_H(swtmr->idxRollNum, sortIndex);
153 
154     swtmr->state = (U8)OS_TIMER_RUNNING;
155 
156     return g_tmrSortLink.sortLink + sortIndex;
157 }
158 /*
159  * 描述:软件定时器的启动接口
160  */
OsSwTmrStart(struct TagSwTmrCtrl * swtmr,U32 interval)161 OS_SEC_TEXT void OsSwTmrStart(struct TagSwTmrCtrl *swtmr, U32 interval)
162 {
163     struct TagSwTmrCtrl *temp = NULL;
164     struct TagListObject *listObject = NULL;
165 
166     listObject = OsSwtmrCtrlInit(swtmr, interval);
167     if (listObject->next == listObject) { // 该SortLink成员上是空链
168         swtmr->next = (struct TagSwTmrCtrl *)listObject;
169         swtmr->prev = (struct TagSwTmrCtrl *)listObject;
170         listObject->next = (struct TagListObject *)swtmr;
171         listObject->prev = (struct TagListObject *)swtmr;
172     } else {
173         /*
174          * 从链表头开始查找,从小往大找
175          * 每个链表节点的成员idxRollNum 都是相对于前一个
176          * 节点的到期时间增量,这样就每次到期拿掉一个节点后,
177          * idxRollNum还都是相对时间,不用更新
178          */
179         /* The First Node */
180         temp = (struct TagSwTmrCtrl *)listObject->next;
181         while (temp != (struct TagSwTmrCtrl *)listObject) {
182             if (UWROLLNUM(temp->idxRollNum) > UWROLLNUM(swtmr->idxRollNum)) {
183                 UWROLLNUMSUB(temp->idxRollNum, swtmr->idxRollNum);
184                 break;
185             }
186             UWROLLNUMSUB(swtmr->idxRollNum, temp->idxRollNum);
187             temp = temp->next;
188         }
189         swtmr->next = temp;
190         swtmr->prev = temp->prev;
191         temp->prev->next = swtmr;
192         temp->prev = swtmr;
193     }
194 }
195