1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_event_pri.h"
33 #include "los_task_pri.h"
34 #include "los_spinlock.h"
35 #include "los_mp.h"
36 #include "los_percpu_pri.h"
37 #include "los_sched_pri.h"
38 #include "los_hook.h"
39 #ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE
40 #include "los_exc.h"
41 #endif
42
LOS_EventInit(PEVENT_CB_S eventCB)43 LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
44 {
45 UINT32 intSave;
46
47 if (eventCB == NULL) {
48 return LOS_ERRNO_EVENT_PTR_NULL;
49 }
50
51 intSave = LOS_IntLock();
52 eventCB->uwEventID = 0;
53 LOS_ListInit(&eventCB->stEventList);
54 LOS_IntRestore(intSave);
55 OsHookCall(LOS_HOOK_TYPE_EVENT_INIT, eventCB);
56 return LOS_OK;
57 }
58
OsEventParamCheck(const VOID * ptr,UINT32 eventMask,UINT32 mode)59 LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode)
60 {
61 if (ptr == NULL) {
62 return LOS_ERRNO_EVENT_PTR_NULL;
63 }
64
65 if (eventMask == 0) {
66 return LOS_ERRNO_EVENT_EVENTMASK_INVALID;
67 }
68
69 if (eventMask & LOS_ERRTYPE_ERROR) {
70 return LOS_ERRNO_EVENT_SETBIT_INVALID;
71 }
72
73 if (((mode & LOS_WAITMODE_OR) && (mode & LOS_WAITMODE_AND)) ||
74 (mode & ~(LOS_WAITMODE_OR | LOS_WAITMODE_AND | LOS_WAITMODE_CLR)) ||
75 !(mode & (LOS_WAITMODE_OR | LOS_WAITMODE_AND))) {
76 return LOS_ERRNO_EVENT_FLAGS_INVALID;
77 }
78 return LOS_OK;
79 }
80
OsEventPoll(UINT32 * eventID,UINT32 eventMask,UINT32 mode)81 LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
82 {
83 UINT32 ret = 0;
84
85 LOS_ASSERT(OsIntLocked());
86 LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));
87
88 if (mode & LOS_WAITMODE_OR) {
89 if ((*eventID & eventMask) != 0) {
90 ret = *eventID & eventMask;
91 }
92 } else {
93 if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {
94 ret = *eventID & eventMask;
95 }
96 }
97
98 if (ret && (mode & LOS_WAITMODE_CLR)) {
99 *eventID = *eventID & ~ret;
100 }
101
102 return ret;
103 }
104
OsEventReadCheck(const PEVENT_CB_S eventCB,UINT32 eventMask,UINT32 mode)105 LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
106 {
107 UINT32 ret;
108 LosTaskCB *runTask = NULL;
109 ret = OsEventParamCheck(eventCB, eventMask, mode);
110 if (ret != LOS_OK) {
111 return ret;
112 }
113
114 if (OS_INT_ACTIVE) {
115 return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;
116 }
117
118 runTask = OsCurrTaskGet();
119 if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
120 OsBackTrace();
121 return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK;
122 }
123 return LOS_OK;
124 }
125
OsEventReadImp(PEVENT_CB_S eventCB,UINT32 eventMask,UINT32 mode,UINT32 timeout,BOOL once)126 LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
127 UINT32 timeout, BOOL once)
128 {
129 UINT32 ret = 0;
130 LosTaskCB *runTask = OsCurrTaskGet();
131 OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode, timeout);
132
133 if (once == FALSE) {
134 ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);
135 }
136
137 if (ret == 0) {
138 if (timeout == 0) {
139 return ret;
140 }
141
142 if (!OsPreemptableInSched()) {
143 return LOS_ERRNO_EVENT_READ_IN_LOCK;
144 }
145
146 runTask->eventMask = eventMask;
147 runTask->eventMode = mode;
148 runTask->taskEvent = eventCB;
149 OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout);
150 ret = runTask->ops->wait(runTask, &eventCB->stEventList, timeout);
151 if (ret == LOS_ERRNO_TSK_TIMEOUT) {
152 return LOS_ERRNO_EVENT_READ_TIMEOUT;
153 }
154
155 ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);
156 }
157 return ret;
158 }
159
OsEventRead(PEVENT_CB_S eventCB,UINT32 eventMask,UINT32 mode,UINT32 timeout,BOOL once)160 LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout,
161 BOOL once)
162 {
163 UINT32 ret;
164 UINT32 intSave;
165
166 ret = OsEventReadCheck(eventCB, eventMask, mode);
167 if (ret != LOS_OK) {
168 return ret;
169 }
170
171 SCHEDULER_LOCK(intSave);
172 ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once);
173 SCHEDULER_UNLOCK(intSave);
174 return ret;
175 }
176
OsEventResume(LosTaskCB * resumedTask,const PEVENT_CB_S eventCB,UINT32 events)177 LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events)
178 {
179 UINT8 exitFlag = 0;
180
181 if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) ||
182 ((resumedTask->eventMode & LOS_WAITMODE_AND) &&
183 ((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {
184 exitFlag = 1;
185
186 resumedTask->taskEvent = NULL;
187 OsTaskWakeClearPendMask(resumedTask);
188 resumedTask->ops->wake(resumedTask);
189 }
190
191 return exitFlag;
192 }
193
OsEventWriteUnsafe(PEVENT_CB_S eventCB,UINT32 events,BOOL once,UINT8 * exitFlag)194 LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag)
195 {
196 LosTaskCB *resumedTask = NULL;
197 LosTaskCB *nextTask = NULL;
198 BOOL schedFlag = FALSE;
199 OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB, events);
200 eventCB->uwEventID |= events;
201 if (!LOS_ListEmpty(&eventCB->stEventList)) {
202 for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList);
203 &resumedTask->pendList != &eventCB->stEventList;) {
204 nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);
205 if (OsEventResume(resumedTask, eventCB, events)) {
206 schedFlag = TRUE;
207 }
208 if (once == TRUE) {
209 break;
210 }
211 resumedTask = nextTask;
212 }
213 }
214
215 if ((exitFlag != NULL) && (schedFlag == TRUE)) {
216 *exitFlag = 1;
217 }
218 }
219
OsEventWrite(PEVENT_CB_S eventCB,UINT32 events,BOOL once)220 LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once)
221 {
222 UINT32 intSave;
223 UINT8 exitFlag = 0;
224
225 if (eventCB == NULL) {
226 return LOS_ERRNO_EVENT_PTR_NULL;
227 }
228
229 if (events & LOS_ERRTYPE_ERROR) {
230 return LOS_ERRNO_EVENT_SETBIT_INVALID;
231 }
232
233 SCHEDULER_LOCK(intSave);
234 OsEventWriteUnsafe(eventCB, events, once, &exitFlag);
235 SCHEDULER_UNLOCK(intSave);
236
237 if (exitFlag == 1) {
238 LOS_MpSchedule(OS_MP_CPU_ALL);
239 LOS_Schedule();
240 }
241 return LOS_OK;
242 }
243
LOS_EventPoll(UINT32 * eventID,UINT32 eventMask,UINT32 mode)244 LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
245 {
246 UINT32 ret;
247 UINT32 intSave;
248
249 ret = OsEventParamCheck((VOID *)eventID, eventMask, mode);
250 if (ret != LOS_OK) {
251 return ret;
252 }
253
254 SCHEDULER_LOCK(intSave);
255 ret = OsEventPoll(eventID, eventMask, mode);
256 SCHEDULER_UNLOCK(intSave);
257 return ret;
258 }
259
LOS_EventRead(PEVENT_CB_S eventCB,UINT32 eventMask,UINT32 mode,UINT32 timeout)260 LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
261 {
262 return OsEventRead(eventCB, eventMask, mode, timeout, FALSE);
263 }
264
LOS_EventWrite(PEVENT_CB_S eventCB,UINT32 events)265 LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
266 {
267 return OsEventWrite(eventCB, events, FALSE);
268 }
269
OsEventReadOnce(PEVENT_CB_S eventCB,UINT32 eventMask,UINT32 mode,UINT32 timeout)270 LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode,
271 UINT32 timeout)
272 {
273 return OsEventRead(eventCB, eventMask, mode, timeout, TRUE);
274 }
275
OsEventWriteOnce(PEVENT_CB_S eventCB,UINT32 events)276 LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events)
277 {
278 return OsEventWrite(eventCB, events, TRUE);
279 }
280
LOS_EventDestroy(PEVENT_CB_S eventCB)281 LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
282 {
283 UINT32 intSave;
284
285 if (eventCB == NULL) {
286 return LOS_ERRNO_EVENT_PTR_NULL;
287 }
288
289 SCHEDULER_LOCK(intSave);
290 if (!LOS_ListEmpty(&eventCB->stEventList)) {
291 SCHEDULER_UNLOCK(intSave);
292 return LOS_ERRNO_EVENT_SHOULD_NOT_DESTROY;
293 }
294
295 eventCB->uwEventID = 0;
296 LOS_ListDelInit(&eventCB->stEventList);
297 SCHEDULER_UNLOCK(intSave);
298 OsHookCall(LOS_HOOK_TYPE_EVENT_DESTROY, eventCB);
299 return LOS_OK;
300 }
301
LOS_EventClear(PEVENT_CB_S eventCB,UINT32 eventMask)302 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask)
303 {
304 UINT32 intSave;
305
306 if (eventCB == NULL) {
307 return LOS_ERRNO_EVENT_PTR_NULL;
308 }
309 OsHookCall(LOS_HOOK_TYPE_EVENT_CLEAR, eventCB, eventMask);
310 SCHEDULER_LOCK(intSave);
311 eventCB->uwEventID &= eventMask;
312 SCHEDULER_UNLOCK(intSave);
313
314 return LOS_OK;
315 }
316
317 #ifdef LOSCFG_COMPAT_POSIX
OsEventReadWithCond(const EventCond * cond,PEVENT_CB_S eventCB,UINT32 eventMask,UINT32 mode,UINT32 timeout)318 LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB,
319 UINT32 eventMask, UINT32 mode, UINT32 timeout)
320 {
321 UINT32 ret;
322 UINT32 intSave;
323
324 ret = OsEventReadCheck(eventCB, eventMask, mode);
325 if (ret != LOS_OK) {
326 return ret;
327 }
328
329 SCHEDULER_LOCK(intSave);
330
331 if (*cond->realValue != cond->value) {
332 eventCB->uwEventID &= cond->clearEvent;
333 goto OUT;
334 }
335
336 ret = OsEventReadImp(eventCB, eventMask, mode, timeout, FALSE);
337 OUT:
338 SCHEDULER_UNLOCK(intSave);
339 return ret;
340 }
341 #endif
342
343