• 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: 事件函数实现
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