更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
los_event.c 文件参考

浏览源代码.

函数

LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit (PEVENT_CB_S eventCB)
 初始化一个事件控制块 更多...
 
LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck (const VOID *ptr, UINT32 eventMask, UINT32 mode)
 事件参数检查 更多...
 
LITE_OS_SEC_TEXT UINT32 OsEventPoll (UINT32 *eventID, UINT32 eventMask, UINT32 mode)
 根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期 更多...
 
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck (const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
 检查读事件 更多...
 
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp (PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once)
 读取指定事件类型的实现函数,超时时间为相对时间:单位为Tick 更多...
 
LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead (PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once)
 读取指定事件类型,超时时间为相对时间:单位为Tick 更多...
 
LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume (LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events)
 事件恢复操作 更多...
 
LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe (PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag)
 以不安全的方式写事件 更多...
 
LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite (PEVENT_CB_S eventCB, UINT32 events, BOOL once)
 写入事件 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_EventPoll (UINT32 *eventID, UINT32 eventMask, UINT32 mode)
 根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_EventRead (PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
 读取指定事件类型,超时时间为相对时间:单位为Tick 更多...
 
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite (PEVENT_CB_S eventCB, UINT32 events)
 写指定的事件类型 更多...
 
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce (PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
 只读一次事件 更多...
 
LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce (PEVENT_CB_S eventCB, UINT32 events)
 只写一次事件 更多...
 
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy (PEVENT_CB_S eventCB)
 销毁指定的事件控制块 更多...
 
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear (PEVENT_CB_S eventCB, UINT32 eventMask)
 清除指定的事件类型 更多...
 
LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond (const EventCond *cond, PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
 有条件式读事件 更多...
 

详细描述

 事件(Event)是一种任务间通信的机制,可用于任务间的同步。
     多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。
     一对多同步模型:一个任务等待多个事件的触发。可以是任意一个事件发生时唤醒任务处理事件,也可以是几个事件都发生后才唤醒任务处理事件。
     多对多同步模型:多个任务等待多个事件的触发。

 事件特点
     任务通过创建事件控制块来触发事件或等待事件。
     事件间相互独立,内部实现为一个32位无符号整型,每一位标识一种事件类型。第25位不可用,因此最多可支持31种事件类型。
     事件仅用于任务间的同步,不提供数据传输功能。
     多次向事件控制块写入同一事件类型,在被清零前等效于只写入一次。
     多个任务可以对同一事件进行读写操作。
     支持事件读写超时机制。

 事件读取模式
     在读事件时,可以选择读取模式。读取模式如下:
     所有事件(LOS_WAITMODE_AND):逻辑与,基于接口传入的事件类型掩码eventMask,
         只有这些事件都已经发生才能读取成功,否则该任务将阻塞等待或者返回错误码。
     任一事件(LOS_WAITMODE_OR):逻辑或,基于接口传入的事件类型掩码eventMask,
         只要这些事件中有任一种事件发生就可以读取成功,否则该任务将阻塞等待或者返回错误码。
     清除事件(LOS_WAITMODE_CLR):这是一种附加读取模式,需要与所有事件模式或任一事件模式结合
         使用(LOS_WAITMODE_AND | LOS_WAITMODE_CLR或 LOS_WAITMODE_OR | LOS_WAITMODE_CLR)。在这种模式下,
         当设置的所有事件模式或任一事件模式读取成功后,会自动清除事件控制块中对应的事件类型位。

 运作机制
     任务在调用LOS_EventRead接口读事件时,可以根据入参事件掩码类型eventMask读取事件的单个或者多个事件类型。
         事件读取成功后,如果设置LOS_WAITMODE_CLR会清除已读取到的事件类型,反之不会清除已读到的事件类型,需显式清除。
         可以通过入参选择读取模式,读取事件掩码类型中所有事件还是读取事件掩码类型中任意事件。
     任务在调用LOS_EventWrite接口写事件时,对指定事件控制块写入指定的事件类型,
         可以一次同时写多个事件类型。写事件会触发任务调度。
     任务在调用LOS_EventClear接口清除事件时,根据入参事件和待清除的事件类型,
         对事件对应位进行清0操作。      
         
 使用场景
     事件可应用于多种任务同步场景,在某些同步场景下可替代信号量。

 注意事项
     在系统初始化之前不能调用读写事件接口。如果调用,系统运行会不正常。
     在中断中,可以对事件对象进行写操作,但不能进行读操作。
     在锁任务调度状态下,禁止任务阻塞于读事件。
     LOS_EventClear 入参值是:要清除的指定事件类型的反码(~events)。
     为了区别LOS_EventRead接口返回的是事件还是错误码,事件掩码的第25位不能使用。
版本
作者
weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
日期
2022-1-15

在文件 los_event.c 中定义.

函数说明

◆ OsEventParamCheck()

LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck ( const VOID *  ptr,
UINT32  eventMask,
UINT32  mode 
)

事件参数检查

在文件 los_event.c111 行定义.

112{
113 if (ptr == NULL) {
114 return LOS_ERRNO_EVENT_PTR_NULL;
115 }
116
117 if (eventMask == 0) {
118 return LOS_ERRNO_EVENT_EVENTMASK_INVALID;
119 }
120
121 if (eventMask & LOS_ERRTYPE_ERROR) {
122 return LOS_ERRNO_EVENT_SETBIT_INVALID;
123 }
124
125 if (((mode & LOS_WAITMODE_OR) && (mode & LOS_WAITMODE_AND)) ||
126 (mode & ~(LOS_WAITMODE_OR | LOS_WAITMODE_AND | LOS_WAITMODE_CLR)) ||
127 !(mode & (LOS_WAITMODE_OR | LOS_WAITMODE_AND))) {
128 return LOS_ERRNO_EVENT_FLAGS_INVALID;
129 }
130 return LOS_OK;
131}
这是这个函数的调用关系图:

◆ OsEventPoll()

LITE_OS_SEC_TEXT UINT32 OsEventPoll ( UINT32 eventID,
UINT32  eventMask,
UINT32  mode 
)

根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期

在文件 los_event.c133 行定义.

134{
135 UINT32 ret = 0;
136
137 LOS_ASSERT(OsIntLocked());//断言不允许中断了
138 LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));//任务自旋锁
139
140 if (mode & LOS_WAITMODE_OR) {//如果模式是读取掩码中任意事件
141 if ((*eventID & eventMask) != 0) {
142 ret = *eventID & eventMask;
143 }
144 } else {//等待全部事件发生
145 if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {//必须满足全部事件发生
146 ret = *eventID & eventMask;
147 }
148 }
149
150 if (ret && (mode & LOS_WAITMODE_CLR)) {//读取完成后清除事件
151 *eventID = *eventID & ~ret;
152 }
153
154 return ret;
155}
STATIC INLINE UINT32 OsIntLocked(VOID)
关闭当前处理器所有中断响应
Definition: los_hw_cpu.h:271
BOOL LOS_SpinHeld(const SPIN_LOCK_S *lock)
Definition: los_spinlock.c:45
SPIN_LOCK_S g_taskSpin
unsigned int UINT32
Definition: los_typedef.h:57
函数调用图:
这是这个函数的调用关系图:

◆ OsEventRead()

LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead ( PEVENT_CB_S  eventCB,
UINT32  eventMask,
UINT32  mode,
UINT32  timeout,
BOOL  once 
)

读取指定事件类型,超时时间为相对时间:单位为Tick

在文件 los_event.c213 行定义.

215{
216 UINT32 ret;
217 UINT32 intSave;
218
219 ret = OsEventReadCheck(eventCB, eventMask, mode);//读取事件检查
220 if (ret != LOS_OK) {
221 return ret;
222 }
223
224 SCHEDULER_LOCK(intSave);
225 ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once);//读事件实现函数
226 SCHEDULER_UNLOCK(intSave);
227 return ret;
228}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once)
读取指定事件类型的实现函数,超时时间为相对时间:单位为Tick
Definition: los_event.c:179
LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode)
检查读事件
Definition: los_event.c:157
函数调用图:
这是这个函数的调用关系图:

◆ OsEventReadCheck()

LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck ( const PEVENT_CB_S  eventCB,
UINT32  eventMask,
UINT32  mode 
)

检查读事件

在文件 los_event.c157 行定义.

158{
159 UINT32 ret;
160 LosTaskCB *runTask = NULL;
161
162 ret = OsEventParamCheck(eventCB, eventMask, mode);//事件参数检查
163 if (ret != LOS_OK) {
164 return ret;
165 }
166
167 if (OS_INT_ACTIVE) {//中断正在进行
168 return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;//不能在中断发送时读事件
169 }
170
171 runTask = OsCurrTaskGet();//获取当前任务
172 if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {//任务属于系统任务
173 OsBackTrace();
174 return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK;//不能在系统任务中读取事件
175 }
176 return LOS_OK;
177}
VOID OsBackTrace(VOID)
Kernel backtrace function.
Definition: los_exc.c:1025
LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode)
事件参数检查
Definition: los_event.c:111
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
UINT16 taskStatus
函数调用图:
这是这个函数的调用关系图:

◆ OsEventReadImp()

LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp ( PEVENT_CB_S  eventCB,
UINT32  eventMask,
UINT32  mode,
UINT32  timeout,
BOOL  once 
)

读取指定事件类型的实现函数,超时时间为相对时间:单位为Tick

在文件 los_event.c179 行定义.

181{
182 UINT32 ret = 0;
183 LosTaskCB *runTask = OsCurrTaskGet();
184 OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode, timeout);
185
186 if (once == FALSE) {
187 ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);//检测事件是否符合预期
188 }
189
190 if (ret == 0) {//不符合预期时
191 if (timeout == 0) {//不等待的情况
192 return ret;
193 }
194
195 if (!OsPreemptableInSched()) {//不能抢占式调度
196 return LOS_ERRNO_EVENT_READ_IN_LOCK;
197 }
198
199 runTask->eventMask = eventMask; //等待事件
200 runTask->eventMode = mode; //事件模式
201 runTask->taskEvent = eventCB; //事件控制块
202 OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout);//任务进入等待状态,等待事件的到来并设置时长和掩码
203 ret = runTask->ops->wait(runTask, &eventCB->stEventList, timeout);
204 if (ret == LOS_ERRNO_TSK_TIMEOUT) {
205 return LOS_ERRNO_EVENT_READ_TIMEOUT;
206 }
207
208 ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);//检测事件是否符合预期
209 }
210 return ret;
211}
LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode)
根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期
Definition: los_event.c:133
STATIC INLINE BOOL OsPreemptableInSched(VOID)
STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 timeout)
设置事件阻塞掩码,即设置任务的等待事件.
Definition: los_task_pri.h:289
UINT32(* wait)(LosTaskCB *runTask, LOS_DL_LIST *list, UINT32 timeout)
任务等待
UINT32 eventMask
VOID * taskEvent
const SchedOps * ops
UINT32 eventMode
UINT32 uwEventID
Definition: los_event.h:165
LOS_DL_LIST stEventList
Definition: los_event.h:167
函数调用图:
这是这个函数的调用关系图:

◆ OsEventReadOnce()

LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce ( PEVENT_CB_S  eventCB,
UINT32  eventMask,
UINT32  mode,
UINT32  timeout 
)

只读一次事件

在文件 los_event.c323 行定义.

325{
326 return OsEventRead(eventCB, eventMask, mode, timeout, TRUE);
327}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once)
读取指定事件类型,超时时间为相对时间:单位为Tick
Definition: los_event.c:213
函数调用图:

◆ OsEventReadWithCond()

LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond ( const EventCond cond,
PEVENT_CB_S  eventCB,
UINT32  eventMask,
UINT32  mode,
UINT32  timeout 
)

有条件式读事件

在文件 los_event.c371 行定义.

373{
374 UINT32 ret;
375 UINT32 intSave;
376
377 ret = OsEventReadCheck(eventCB, eventMask, mode);
378 if (ret != LOS_OK) {
379 return ret;
380 }
381
382 SCHEDULER_LOCK(intSave);
383
384 if (*cond->realValue != cond->value) {
385 eventCB->uwEventID &= cond->clearEvent;
386 goto OUT;
387 }
388
389 ret = OsEventReadImp(eventCB, eventMask, mode, timeout, FALSE);
390OUT:
391 SCHEDULER_UNLOCK(intSave);
392 return ret;
393}
UINT32 clearEvent
Definition: los_event_pri.h:47
volatile INT32 * realValue
Definition: los_event_pri.h:45
INT32 value
Definition: los_event_pri.h:46
函数调用图:
这是这个函数的调用关系图:

◆ OsEventResume()

LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume ( LosTaskCB resumedTask,
const PEVENT_CB_S  eventCB,
UINT32  events 
)

事件恢复操作

在文件 los_event.c230 行定义.

231{
232 UINT8 exitFlag = 0;//是否唤醒
233
234 if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) ||
235 ((resumedTask->eventMode & LOS_WAITMODE_AND) &&
236 ((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {//逻辑与 和 逻辑或 的处理
237 exitFlag = 1;
238
239 resumedTask->taskEvent = NULL;
240 OsTaskWakeClearPendMask(resumedTask);
241 resumedTask->ops->wake(resumedTask);
242 }
243
244 return exitFlag;
245}
STATIC INLINE VOID OsTaskWakeClearPendMask(LosTaskCB *resumeTask)
清除事件阻塞掩码,即任务不再等待任何事件.
Definition: los_task_pri.h:298
unsigned char UINT8
Definition: los_typedef.h:55
VOID(* wake)(LosTaskCB *taskCB)
任务唤醒
函数调用图:
这是这个函数的调用关系图:

◆ OsEventWrite()

LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite ( PEVENT_CB_S  eventCB,
UINT32  events,
BOOL  once 
)

写入事件

在文件 los_event.c273 行定义.

274{
275 UINT32 intSave;
276 UINT8 exitFlag = 0;
277
278 if (eventCB == NULL) {
279 return LOS_ERRNO_EVENT_PTR_NULL;
280 }
281
282 if (events & LOS_ERRTYPE_ERROR) {
283 return LOS_ERRNO_EVENT_SETBIT_INVALID;
284 }
285
286 SCHEDULER_LOCK(intSave); //禁止调度
287 OsEventWriteUnsafe(eventCB, events, once, &exitFlag);//写入事件
288 SCHEDULER_UNLOCK(intSave); //允许调度
289
290 if (exitFlag == 1) { //需要发生调度
291 LOS_MpSchedule(OS_MP_CPU_ALL);//通知所有CPU调度
292 LOS_Schedule();//执行调度
293 }
294 return LOS_OK;
295}
VOID LOS_Schedule(VOID)
Trigger active task scheduling.
Definition: los_sched.c:469
LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag)
以不安全的方式写事件
Definition: los_event.c:247
VOID LOS_MpSchedule(UINT32 target)
Definition: los_mp.c:76
函数调用图:
这是这个函数的调用关系图:

◆ OsEventWriteOnce()

LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce ( PEVENT_CB_S  eventCB,
UINT32  events 
)

只写一次事件

在文件 los_event.c329 行定义.

330{
331 return OsEventWrite(eventCB, events, TRUE);
332}
LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once)
写入事件
Definition: los_event.c:273
函数调用图:
这是这个函数的调用关系图:

◆ OsEventWriteUnsafe()

LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe ( PEVENT_CB_S  eventCB,
UINT32  events,
BOOL  once,
UINT8 exitFlag 
)

以不安全的方式写事件

在文件 los_event.c247 行定义.

248{
249 LosTaskCB *resumedTask = NULL;
250 LosTaskCB *nextTask = NULL;
251 BOOL schedFlag = FALSE;
252 OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB, events);
253 eventCB->uwEventID |= events;//对应位贴上标签
254 if (!LOS_ListEmpty(&eventCB->stEventList)) {//等待事件链表判断,处理等待事件的任务
255 for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList);
256 &resumedTask->pendList != &eventCB->stEventList;) {//循环获取任务链表
257 nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);//获取任务实体
258 if (OsEventResume(resumedTask, eventCB, events)) {//是否恢复任务
259 schedFlag = TRUE;//任务已加至就绪队列,申请发生一次调度
260 }
261 if (once == TRUE) {//是否只处理一次任务
262 break;//退出循环
263 }
264 resumedTask = nextTask;//检查链表中下一个任务
265 }
266 }
267
268 if ((exitFlag != NULL) && (schedFlag == TRUE)) {//是否让外面调度
269 *exitFlag = 1;
270 }
271}
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events)
事件恢复操作
Definition: los_event.c:230
size_t BOOL
Definition: los_typedef.h:88
struct LOS_DL_LIST * pstNext
Definition: los_list.h:84
LOS_DL_LIST pendList
函数调用图:
这是这个函数的调用关系图: