Abstract:This article through the analysis of HongMeng light kernel event module source code, in-depth grasp of the use of events.

This article is shared from Huawei cloud community “Hongmeng light kernel M kernel source analysis series 12 events”, the original author: Zhushy.

An Event is a mechanism for communication between tasks and can be used for synchronization between tasks. In the multi-tasking environment, tasks often need to be synchronized, and a wait is a synchronization. Events can provide one-to-many, many-to-many synchronous operations. This article through the analysis of HongMeng light kernel event module source code, in-depth grasp of the use of events. In this article the source involved in OpenHarmony LiteOS -m kernel, for example, can be in the open source site https://gitee.com/openharmony… To obtain.

Next, let’s look at the event structure, event initialization, and source code for the commonly used actions of the event.

1. Event structure definition and common macro definition

1.1 Event structure definition

The event control block structure defined in the file kernel\include\los_event.h is Event_CB_S. The source code of the structure is as follows. The explanation of the structure members is in the comments section.

typedef struct tagEvent { UINT32 uwEventID; LOS_DL_LIST stEventList; LOS_DL_LIST stEventList; LOS_DL_LIST stEventList; LOS_DL_LIST stEventList; /**< list of tasks to read event */} EVENT_CB_S, *PEVENT_CB_S;

1.2 Common macro definitions for events

When reading an event, you can select the read mode. The read mode is defined by the following macros:

  • All events (LOS_WAITMODE_AND) :

Logic and, based on the eventMask passed by the interface, can only be read successfully if all these events have occurred, otherwise the task will block waiting or return an error code.

  • Any event (LOS_WAITMODE_OR) :

Logic or, based on the event-type mask passed by the interface, the read can be successful as long as any of these events occur, otherwise the task will block waiting or return an error code.

  • Clear event (LOS_WAITMODE_CLR) :

This is a additional read mode, with all events or any event model used in combination (LOS_WAITMODE_AND | LOS_WAITMODE_CLR or LOS_WAITMODE_OR | LOS_WAITMODE_CLR). In this mode, when all or any of the event modes set are read successfully, the corresponding event type bits in the event control block are automatically cleared.

#define LOS_WAITMODE_AND                   (4)

   #define LOS_WAITMODE_OR                    (2)

   #define LOS_WAITMODE_CLR                   (1)

3, Event common operation

3.1 Initialize the event

Before using the event, the function uint32los_eventinit (PEVENT_CB_S eventCB) must be used to initialize the event. The required parameter is the structure pointer variable PEVENT_CB_S eventCB. After analyzing the code, the parameter passed in (1) cannot be empty, otherwise the error code will be returned. (2) initialize the event code. UWAVentid to 0, and initialize the bivariate looped list. StEventList, which is used to mount the task of reading the event.

LITE_OS_SEC_TEXT_INIT uint32los_eventInit (PEVENT_CB_S eventCB) {⑴ if (eventCB == NULL) {return LOS_ERRNO_EVENT_PTR_NULL; } ⑵ eventCb-> uWeventid = 0; LOS_ListInit(&eventCB->stEventList); OsHookCall(LOS_HOOK_TYPE_EVENT_INIT); return LOS_OK; }

3.2 Verify event mask

We can use the function uint32los_eventpoll (UINT32 *eventId, UINT32 eventMask, UINT32 mode) to verify the eventMask. The required parameters are the event encoding eventId of the event structure, eventMask passed by the user to be verified, and mode to return whether the event passed by the user has occurred: if the return value is 0, it means that the event expected by the user has not occurred; otherwise, it means that the event expected by the user has occurred.

We look at the source code, ⑴ first check the legitimacy of the incoming parameters, the event code can not be empty. Then execute the code at the end of the line to verify it. If it is any event read mode, the following judgment does not mean that at least one event occurred, and the return value ret indicates which events occurred. (3) If it is all things read mode, when the logic and operation * Eventid & EventMask is equal to EventMask, it means that all the expected events have occurred, and the return value ret indicates which events have occurred. (4) When ret is not 0, the expected event occurs and it is in the clear event reading mode, the things that have happened need to be cleared. It appears that this function does not only check if the event has occurred, but also has the action of updating the event code.

LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode) { UINT32 ret = 0; UINT32 intSave; ⑴ if (eventID == NULL) {return LOS_ERRNO_EVENT_PTR_NULL; } intSave = LOS_IntLock(); ⑵ if (mode &los_waitMode_or) {if ((*eventID &eventMask)! = 0) { ret = *eventID & eventMask; }} else {⑶ if ((eventMask! = 0) && (eventMask == (*eventID & eventMask))) { ret = *eventID & eventMask; ⑷ if (ret && (mode & LOS_WAITMODE_CLR)) {*eventID = *eventID & ~(ret); } LOS_IntRestore(intSave); return ret; }

3.3 Read/write events

3.3.1 Read the specified event type

We can read the event using the LOS_EventRead() function, which takes four parameters. EventCB is the initialized event structure, EventMask represents the eventMask that needs to be read, Mode is the read mode described above, Timeout is the read timeout (Tick). When the function returns 0, the expected event did not occur, and the read event failed, blocking. A non-0 return indicates that the expected event occurred, and the event was read successfully. Let’s examine the source code of the function to see how to read the event.

⑴ call the function osEventReadParamCheck () to perform basic checks, such as the 25th bit reserved cannot be used, the eventMask cannot be zero, and whether the read pattern combination is valid. ⑵ indicates that the read event cannot be interrupted. (3) call the validation function osEventPoll () to check whether the event EventMask occurred. If the event occurs and ret is not 0, a successful read will be returned directly. If ret is 0 and the event does not occur, execute ⑷. If timeout is 0 and the caller cannot wait, return directly. ⑸ If the event cannot be read when the lock task is scheduled, the error code is returned.

It will update the blocking eventMask. EventMask and eventRead Mode of the current task. The function osschedTaskWait is called, which changes the state of the current task to a blocking state, mounted on the event’s task-blocking list. If timeout is not a permanent wait, the task is also set to the OS_TASK_STATUS_PEND_TIME state and the wait time is set. The ⑻ place triggers the task scheduling, and the subsequent program will not proceed until the event is read.

When the waiting time expires and the event is unreadable, the task returns an error code if the specified event cannot be read. If the specified event can be read when executed, check whether the event EventMask occurred and then return the result value.

LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeOut) { UINT32 ret; UINT32 intSave; LosTaskCB *runTsk = NULL; ⑴ ret = osEventReadParamCheck (eventCB, eventMask, mode); if (ret ! = LOS_OK) { return ret; } ⑵ if (OS_INT_ACTIVE) {LOS_ERRNO_EVENT_READ_IN_INTERRUPT; ⑵ if (OS_INT_ACTIVE) {LOS_ERRNO_EVENT_READ_IN_INTERRUPT; } intSave = LOS_IntLock(); ⑶ ret = los_eventPoll (&(eventCb-> uwEventID), eventMask, mode); OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode); If (timeOut == 0) {⑷ if (timeOut == 0) {LOS_IntRestore(intSave); return ret; } ⑸ if (g_lostAskLock) {LOS_IntRestore(intSave); return LOS_ERRNO_EVENT_READ_IN_LOCK; } runTsk = g_losTask.runTask; [6] runTsk - > eventMask = eventMask; runTsk->eventMode = mode; Once OsSchedTaskWait (& eventCB - > stEventList, timeOut); LOS_IntRestore(intSave); Being LOS_Schedule (); 'levies intSave = LOS_IntLock (); if (runTsk->taskStatus & OS_TASK_STATUS_TIMEOUT) { runTsk->taskStatus &= ~OS_TASK_STATUS_TIMEOUT; LOS_IntRestore(intSave); return LOS_ERRNO_EVENT_READ_TIMEOUT; } will = LOS_EventPoll(&eventCb-> uwEventID, eventMask, mode); } LOS_IntRestore(intSave); return ret; }

3.3.2 Writes the specified event type

We can use the function uint32los_eventwrite (PEVENT_CB_S eventCB, UINT32 events) to write to the specified event type. The code is as follows:

Let’s look at the source code to see how the event type is written. (1) The code performs logic or calculation on the event mask of the event structure and the event type to be written to Events to complete the event writing. ⑵ If the list of tasks waiting for the event is not empty, it needs to handle whether any task can read the corresponding event after writing the event. ⑶ For loop iterates through the tasks on the event blocking list in turn, then get the nextTask nextTask. (⑸) determine whether the event meets the requirement of task ResumedTask reading event in different read modes. If it meets the requirement of task reading event, ⑹ set the exitFlag exitFlag, and then call the function osschedTaskWake () to change the state of task reading event and put it into the ready queue, continue executing ⑺, Each task in the linked list of blocking tasks that traverses events. ⑻ if a task reads the event, it needs to trigger the task scheduling.

LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events) { LosTaskCB *resumedTask = NULL; LosTaskCB *nextTask = (LosTaskCB *)NULL; UINT32 intSave; UINT8 exitFlag = 0; if (eventCB == NULL) { return LOS_ERRNO_EVENT_PTR_NULL; } if ((eventCB->stEventList.pstNext == NULL) || (eventCB->stEventList.pstPrev == NULL)) { return LOS_ERRNO_EVENT_NOT_INITIALIZED; } if (events & LOS_ERRTYPE_ERROR) { return LOS_ERRNO_EVENT_SETBIT_INVALID; } intSave = LOS_IntLock(); (1) eventCB - > uwEventID | = events; OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB); 2 the if (! Los_listEmpty (&eventCb-> stEventList)) {⑶ for (resumedTask = LOS_DL_LIST_ENTRY((&eventCb-> stEventList)->pstNext, LosTaskCB, pendList); &resumedTask->pendList ! = (&eventCB->stEventList);) {⑷ nextTask = LOS_DL_LIST_ENTRY(nextTask -> pendlist.pstnext, lostAskCb, pendList); ⑸ ⑸ if (((ResumedTask-> EventMode & Los_WaitMode_Or) &&(ResumedTask-> EventMask & Events)! = 0) || ((resumedTask->eventMode & LOS_WAITMODE_AND) && ((resumedTask->eventMask & eventCB->uwEventID) == ResumedTask-> EventMask))) {⑹ ExitFlag = 1; OsSchedTaskWake(resumedTask); } ⑺ ResumedTask = nextTask; } if (exitFlag == 1) { LOS_IntRestore(intSave); Being LOS_Schedule (); return LOS_OK; } } LOS_IntRestore(intSave); return LOS_OK; }

3.4 Clearing Event

We can use the function uint32los_eventclear (PEVENT_CB_S eventCB, uint32eventmask) to clear the specified event type. Let’s look at the source code to see how to clear the event type.

The function takes the event structure EventCB and the event type to clear EventMask. Clearing an event starts with checking if the structure parameters are empty, which is relatively simple. (1) The eventMask of the event structure and the event type to be cleared EventMask are logic and calculation to complete the event cleaning.

LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask) { UINT32 intSave; if (eventCB == NULL) { return LOS_ERRNO_EVENT_PTR_NULL; } intSave = LOS_IntLock(); (1) eventCB - > uwEventID & = eventMask; LOS_IntRestore(intSave); OsHookCall(LOS_HOOK_TYPE_EVENT_CLEAR, eventCB); return LOS_OK; }

3.5 Destruction Event

We can use the function uint32los_eventDestroy (PEVENT_CB_S eventCB) to destroy the specified event control block. Let’s look at the source code to see how the event is destroyed.

The function parameter is the event structure, and the destruction of the event first checks whether the structure parameter is empty. This is relatively simple. (1) You cannot destroy an event if its task-blocking list is not empty. ⑵ Set the task list of reading events in the event structure to empty to complete the destruction of events.

LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) { UINT32 intSave; if (eventCB == NULL) { return LOS_ERRNO_EVENT_PTR_NULL; } intSave = LOS_IntLock(); (1) if (! LOS_ListEmpty(&eventCB->stEventList)) { LOS_IntRestore(intSave); return LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY; } ⑵ eventCb-> stEventList.pstNext = (LOS_DL_LIST *)NULL; eventCB->stEventList.pstPrev = (LOS_DL_LIST *)NULL; LOS_IntRestore(intSave); OsHookCall(LOS_HOOK_TYPE_EVENT_DESTROY); return LOS_OK; }

summary

This article led us to analyze the source code of the event module of the HongMeng light kernel, including the structure of the event, the event initialization, the event creation and deletion, the application for release and so on. Thanks for reading, if you have any question, advice, can leave a message to us: https://gitee.com/openharmony… . In order to more easily find HongMeng kernel code warehouse, suggest to https://gitee.com/openharmony… , follow Watch, thumb up Star, and Fork to your account, thank you.

Click on the attention, the first time to understand Huawei cloud fresh technology ~