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