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: 事件函数实现
14 */
15 #include "prt_event.h"
16 #include "prt_task_external.h"
17
18 // 支持功能宏裁剪
19 #if defined(OS_OPTION_EVENT)
20
OsEventReadParaCheck(U32 eventMask,U32 flags,U32 timeOut)21 OS_SEC_L4_TEXT U32 OsEventReadParaCheck(U32 eventMask, U32 flags, U32 timeOut)
22 {
23 if (eventMask == 0) {
24 return OS_ERRNO_EVENT_EVENTMASK_INVALID;
25 }
26 /* 读事件模式非法或者(读事件模式为非等待模式且等待时间为0)时,返回错误 */
27 if (!(flags == (OS_EVENT_ALL | OS_EVENT_WAIT) || flags == (OS_EVENT_ALL | OS_EVENT_NOWAIT) ||
28 flags == (OS_EVENT_ANY | OS_EVENT_WAIT) || flags == (OS_EVENT_ANY | OS_EVENT_NOWAIT)) ||
29 (((flags & OS_EVENT_WAIT) != 0) && (timeOut == 0))) {
30 return OS_ERRNO_EVENT_FLAGS_INVALID;
31 }
32
33 return OS_OK;
34 }
35
OsIsEventNotMatch(U32 flags,U32 event,U32 eventMask,struct TagTskCb * runTsk)36 OS_SEC_ALW_INLINE INLINE bool OsIsEventNotMatch(U32 flags, U32 event, U32 eventMask, struct TagTskCb *runTsk)
37 {
38 /* 读事件非期望获得所有事件 */
39 if ((flags & OS_EVENT_ALL) != 0) {
40 TSK_STATUS_SET(runTsk, OS_TSK_EVENT_TYPE);
41 if ((eventMask != (event & eventMask))) {
42 return TRUE;
43 }
44 } else {
45 TSK_STATUS_CLEAR(runTsk, OS_TSK_EVENT_TYPE);
46 if ((event & eventMask) == 0) {
47 return TRUE;
48 }
49 }
50
51 return FALSE;
52 }
53
OsEventTimeOutSet(U32 timeOut,struct TagTskCb * runTsk)54 OS_SEC_ALW_INLINE INLINE void OsEventTimeOutSet(U32 timeOut, struct TagTskCb *runTsk)
55 {
56 if (timeOut == OS_EVENT_WAIT_FOREVER) {
57 TSK_STATUS_CLEAR(runTsk, OS_TSK_TIMEOUT);
58 } else {
59 TSK_STATUS_SET(runTsk, OS_TSK_TIMEOUT);
60 OsTskTimerAdd(runTsk, timeOut);
61 }
62 }
63
OsEventReadNeedSche(U32 flags,struct TagTskCb * runTsk,U32 timeOut,U32 * event)64 OS_SEC_ALW_INLINE INLINE U32 OsEventReadNeedSche(U32 flags, struct TagTskCb *runTsk,
65 U32 timeOut, U32 *event)
66 {
67 /* 读事件处于等待读取模式 */
68 if ((flags & OS_EVENT_NOWAIT) != 0) {
69 return OS_ERRNO_EVENT_READ_FAILED;
70 }
71
72 /* 如果锁任务的情况下 */
73 if (OS_TASK_LOCK_DATA != 0) {
74 return OS_ERRNO_EVENT_READ_IN_LOCK;
75 }
76
77 OsTskReadyDel(runTsk);
78
79 TSK_STATUS_SET(runTsk, OS_TSK_EVENT_PEND);
80
81 OsEventTimeOutSet(timeOut, runTsk);
82
83 OsTskSchedule();
84
85 /* 判断是否超时返回并做超时处理 */
86 if ((runTsk->taskStatus & OS_TSK_TIMEOUT) != 0) {
87 TSK_STATUS_CLEAR(runTsk, OS_TSK_TIMEOUT);
88 return OS_ERRNO_EVENT_READ_TIMEOUT;
89 }
90
91 *event = runTsk->event;
92 return OS_OK;
93 }
94
95 /*
96 * 描述:读事件操作
97 */
PRT_EventRead(U32 eventMask,U32 flags,U32 timeOut,U32 * events)98 OS_SEC_L4_TEXT U32 PRT_EventRead(U32 eventMask, U32 flags, U32 timeOut, U32 *events)
99 {
100 U32 ret;
101 U32 event;
102 uintptr_t intSave;
103 struct TagTskCb *runTsk = NULL;
104 bool needSchedule = FALSE;
105
106 ret = OsEventReadParaCheck(eventMask, flags, timeOut);
107 if (ret != OS_OK) {
108 return ret;
109 }
110
111 intSave = OsIntLock();
112
113 if (OS_INT_ACTIVE) {
114 OsIntRestore(intSave);
115 return OS_ERRNO_EVENT_READ_NOT_IN_TASK;
116 }
117
118 runTsk = RUNNING_TASK;
119 runTsk->eventMask = eventMask;
120 event = runTsk->event;
121
122 needSchedule = OsIsEventNotMatch(flags, event, eventMask, runTsk);
123 /* 期望的事件一件都没有发生,或者在OS_EVENT_ALL情况下没有发生期望所有事件 */
124 if (needSchedule == TRUE) {
125 ret = OsEventReadNeedSche(flags, runTsk, timeOut, &event);
126 if (ret != OS_OK) {
127 OsIntRestore(intSave);
128 return ret;
129 }
130 }
131
132 /* 清除已经读取到的事件 */
133 runTsk->event &= (~eventMask);
134
135 if (events != NULL) {
136 *events = event & eventMask;
137 }
138 OsIntRestore(intSave);
139
140 return OS_OK;
141 }
142
OsEventStateChange(U32 taskStatus,struct TagTskCb * taskCb)143 OS_SEC_ALW_INLINE INLINE void OsEventStateChange(U32 taskStatus, struct TagTskCb *taskCb)
144 {
145 if ((taskStatus & OS_TSK_TIMEOUT) != 0) {
146 /*
147 * 添加PEND状态时,会加上TIMEOUT标志和timer,或者都不加。
148 * 所以此时有TIMEOUT标志就一定有timer,且只有一个,且只用于该PEND方式
149 */
150 OS_TSK_DELAY_LOCKED_DETACH(taskCb);
151 TSK_STATUS_CLEAR(taskCb, OS_TSK_TIMEOUT);
152 }
153
154 if ((OS_TSK_SUSPEND & taskStatus) == 0) {
155 OsTskReadyAddBgd(taskCb);
156 }
157 }
158
159 /*
160 * 描述:写事件操作
161 */
PRT_EventWrite(U32 taskId,U32 events)162 OS_SEC_L4_TEXT U32 PRT_EventWrite(U32 taskId, U32 events)
163 {
164 struct TagTskCb *taskCb = NULL;
165 uintptr_t intSave;
166 bool needSchedule = FALSE;
167 U32 eventMask;
168 U32 taskStatus;
169
170 if (CHECK_TSK_PID_OVERFLOW(taskId)) {
171 return OS_ERRNO_EVENT_TASKID_INVALID;
172 }
173
174 if (events == 0) {
175 return OS_ERRNO_EVENT_INVALID;
176 }
177
178 intSave = OsIntLock();
179 taskCb = (struct TagTskCb *)GET_TCB_HANDLE(taskId);
180 taskStatus = taskCb->taskStatus;
181 if (TSK_IS_UNUSED(taskCb)) {
182 OsIntRestore(intSave);
183
184 return OS_ERRNO_EVENT_TSK_NOT_CREATED;
185 }
186
187 taskCb->event |= events;
188
189 /* 判断目的线程是否阻塞于读事件 */
190 if ((taskStatus & OS_TSK_EVENT_PEND) != 0) {
191 eventMask = taskCb->eventMask;
192
193 /* 判断是否需要任务调度 */
194 if ((taskStatus & OS_TSK_EVENT_TYPE) != 0) {
195 if (eventMask == (taskCb->event & eventMask)) {
196 needSchedule = TRUE;
197 }
198 } else {
199 if ((taskCb->event & eventMask) != 0) {
200 needSchedule = TRUE;
201 }
202 }
203
204 if (needSchedule) {
205 TSK_STATUS_CLEAR(taskCb, OS_TSK_EVENT_PEND);
206
207 OsEventStateChange(taskStatus, taskCb);
208
209 OsTskSchedule();
210
211 OsIntRestore(intSave);
212 return OS_OK;
213 }
214 }
215 OsIntRestore(intSave);
216 return OS_OK;
217 }
218
219 #endif
220