• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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