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

This article is shared by Huawei cloud community “LiteOS kernel source code analysis series nine events”, original author: zhushy.

Events are a communication mechanism between tasks and can be used for synchronization between tasks. In a multi-task environment, tasks often need to be synchronized. A wait is a synchronization. Events can provide one-to-many, many-to-many synchronization operations. This article through the analysis of LiteOS event module source code, in-depth grasp of the use of events.

LiteOS event module source code, all available at LiteOS open source site gitee.com/LiteOS/Lite… To obtain. Event source code, development document, sample program code is as follows:

  • LiteOS kernel event source code

Include the event private header file kernel\base\include\los_event_pri.h, header file kernel\include\los_event.h, and C source file kernel\base\los_event.c.

  • Development guide documentation – Events

Online documentation

Gitee.com/LiteOS/Lite… .

Next, let’s take a look at the event structure, event initialization, and the source code for common events.

1. Event structure definition and common macro definition

1.1 Event structure definition

The event control block structure defined in kernel\base\include\los_event.h is EVENT_CB_S. The source code of the structure is as follows.

typedef struct tagEvent { UINT32 uwEventID; /**< event ID, each bit identifies an event type */ LOS_DL_LIST stEventList; EVENT_CB_S, *PEVENT_CB_S;Copy the code

To enable POSIX-compatible macros LOSCFG_COMPAT_POSIX, the kernel\base\include\los_event_pri.h file also defines the EventCond structure as follows:

#ifdef LOSCFG_COMPAT_POSIX
typedef struct {
    volatile INT32 *realValue;
    INT32 value;
    UINT32 clearEvent;
} EventCond;
Copy the code

1.2 Common macro definitions for events

You can configure whether the system supports events by using the macro LOSCFG_BASE_IPC_EVENT. This function is enabled by default. When reading an event, you can choose the read mode. Read mode is defined by the following macros:

  • All events (LOS_WAITMODE_AND) :

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

  • Any event (LOS_WAITMODE_OR) :

Logic or eventMask based on the event type passed in by the interface. If any of these events occur, the task will block and wait 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 event modes are read successfully, the corresponding event type bits in the event control block are automatically cleared.

 #define LOS_WAITMODE_AND                    4U

   #define LOS_WAITMODE_OR                     2U

   #define LOS_WAITMODE_CLR                    1U
Copy the code

3. Common operations of events

3.1 Initialization Events

Before using an event, you must use the function UINT32 LOS_EventInit(PEVENT_CB_S eventCB) to initialize the event. The structure PEVENT_CB_S eventCB is required. The parameter passed in (1) cannot be empty, otherwise an error code will be returned. UwEventID is initialized to 0 after the shutdown, and then it initializes the two-way circular list. StEventList, which is used to hang on tasks that read events.

LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB) { UINT32 intSave; LOS_TRACE(EVENT_CREATE, (UINTPTR)eventCB); ⑴ if (eventCB == NULL) {return LOS_ERRNO_EVENT_PTR_NULL; } intSave = LOS_IntLock(); 2 eventCB - > uwEventID = 0; LOS_ListInit(&eventCB->stEventList); LOS_IntRestore(intSave); return LOS_OK; }Copy the code

3.2 Verifying the Event Mask

We can use the function UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask,UINT32 mode) to verify the eventMask. The required parameters are the event code eventId of the event structure, the eventMask passed by the user to be verified, and the reading mode mode to return whether the event passed by the user occurs. If the return value is 0, the expected event does not occur; otherwise, the expected event occurs. Look at the source code. ⑴ checks the validity of the parameters passed in, and then executes OsEventPoll() on ⑵.

LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode) { UINT32 ret; UINT32 intSave; ⑴ ret = OsEventParamCheck((VOID *)eventId, eventMask, mode); if (ret ! = LOS_OK) { return ret; } SCHEDULER_LOCK(intSave); ⑵ RET = OsEventPoll(eventId, eventMask, mode); SCHEDULER_UNLOCK(intSave); return ret; }Copy the code

Let’s move on to the function OsEventPoll(). In the case of any event-read mode, the following judgment is not equal to indicating that at least one event occurred, and the return value RET indicates which events occurred. (2) If it is all things read mode, when the logic and operation *eventId & eventMask is also equal to eventMask, it means that all the expected events have occurred, and the return value RET indicates which events have occurred. (3) When ret is not zero, the expected event occurs, and the event is read in clear mode, the event that has already occurred needs to be cleared. It seems that this function does not just check whether an event has occurred, but also update the event code.

LITE_OS_SEC_TEXT STATIC UINT32 OsEventPoll(UINT32 *eventId, UINT32 eventMask, UINT32 mode) { UINT32 ret = 0; LOS_ASSERT(ArchIntLocked()); LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); ⑴ 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; } return ret; }Copy the code

3.3 Read/write Events

3.3.1 Reading the Specified Event Type

We can use the function LOS_EventRead() to read the event, which takes four parameters. EventCB is the initialized event structure, eventMask is the eventMask to be read, mode is the read mode described above, and timeout is the read timeout, in Tick. This function further calls OsEventRead() to read the event as follows:

LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
{
    return OsEventRead(eventCB, eventMask, mode, timeout, FALSE);
}
Copy the code

Let’s examine the source code of the function OsEventRead() to see how the event is read. BOOL once (LOS_EventRead()) BOOL once (FALSE)

The function OsEventReadCheck() is called at ⑴ to perform basic verification, such as the 25th bit reserved cannot be used, the eventMask eventMask cannot be zero, the combination of read modes is legal, and the event cannot be read in the interrupt. If a system task reads an event, a warning message is displayed. The ⑵ then proceeds to call the function OsEventReadImp() to read the event.

LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once) { UINT32 ret; UINT32 intSave; ⑴ ret = OsEventReadCheck(eventCB, eventMask, mode); if (ret ! = LOS_OK) { return ret; } LOS_TRACE(EVENT_READ, (UINTPTR)eventCB, eventCB->uwEventID, eventMask, mode, timeout); SCHEDULER_LOCK(intSave); ⑵ ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once, &intSave); SCHEDULER_UNLOCK(intSave); return ret; }Copy the code

Let’s move on to the function OsEventReadImp(). When once at ⑴ is false, the verification function OsEventPoll() is called to check whether the event eventMask occurs. If the ret is not 0, the event is returned. When ret is 0 and the event does not occur, execute ⑵. If timeout is 0 and the caller cannot wait, return directly. (3) If the event cannot be read when the lock task is scheduled, return an error code.

* update the blocking eventMask. EventMask and eventread mode. EventMode. Execute ⑸, change the state of the current task is no longer ready state, set it to blocked state, hang on the task blocking list of the event. If timeout is not permanent, the task is also hung in the timer sort list. ⑹ triggered the task scheduling, the subsequent program needs to wait until the event will continue to execute.

⑺ If the waiting time expires and the event is still unreadable, an error code is returned if the specified event cannot be read. If the specified event can be read, execute the ⑻ to check whether the event eventMask occurred and return the result value.

LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once, UINT32 *intSave) { UINT32 ret = 0; LosTaskCB *runTask = OsCurrTaskGet(); ⑴ if (once == FALSE) {ret = OsEventPoll(&eventcb ->uwEventID, eventMask, mode); } ⑵ if (ret == 0) {if (timeout == 0) {return ret; } (3) if (! OsPreemptableInSched()) { return LOS_ERRNO_EVENT_READ_IN_LOCK; } * * * * * * * * * * * * * * * * * runTask->eventMode = mode; 5] OsTaskWait (& eventCB - > stEventList, OS_TASK_STATUS_PEND, timeout); [6] OsSchedResched (); SCHEDULER_UNLOCK(*intSave); SCHEDULER_LOCK(*intSave); ⑺ if (runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT) {runTask->taskStatus &= ~OS_TASK_STATUS_TIMEOUT; return LOS_ERRNO_EVENT_READ_TIMEOUT; } ⑻ ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode); } return ret; }Copy the code

3.3.2 Write the specified event type

We can use the function UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 Events) to write the specified event type. This function further calls the function OsEventWrite() to write the event, as follows:

LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
{
    return OsEventWrite(eventCB, events, FALSE);
}
Copy the code

Let’s examine the source code for OsEventWrite() to see how to write event types. BOOL once indicates whether to read only once. For LOS_EventWrite(), once is FALSE. The code in ⑴ carries out logic or calculation of the event mask of the event structure and the event type events to be written to complete the writing of the event. (2) If the list of tasks waiting for the event is not empty, it is necessary to deal with whether any task can read the corresponding event after writing the event. (3) the for loop iterates through the tasks on the event blocking list, and (4) fetches the nextTask, nextTask. ⑸ dispose of different reading modes to determine whether the event meets the requirements of task resumedTask to read the event. If it meets the requirements of task resumedTask to read the event, execute ⑹ setting the exitFlag exitFlag, and then call function OsTaskWake() to change the state of the task to read the event and put it into the ready queue. ⑺ If once is true, only the first task in the list of blocking tasks for the event is processed. If false, go ahead and dust every task in the event’s blocking task list. Description If a task receives an event, task scheduling needs to be triggered.

LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once) { LosTaskCB *resumedTask = NULL; LosTaskCB *nextTask = NULL; UINT32 intSave; UINT8 exitFlag = 0; if (eventCB == NULL) { return LOS_ERRNO_EVENT_PTR_NULL; } if (events & LOS_ERRTYPE_ERROR) { return LOS_ERRNO_EVENT_SETBIT_INVALID; } LOS_TRACE(EVENT_WRITE, (UINTPTR)eventCB, eventCB->uwEventID, events); SCHEDULER_LOCK(intSave); (1) eventCB - > uwEventID | = events; 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(* * * * task ->pendList. ⑸ ⑸ if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & eventMask)! = 0)) || ((resumedTask->eventMode & LOS_WAITMODE_AND) && ((resumedTask->eventMask & eventCB->uwEventID) == ResumedTask ->eventMask))) {⑹ exitFlag = 1; OsTaskWake(resumedTask, OS_TASK_STATUS_PEND); } ⑺ if (once == TRUE) {break; } ⑻ resumedTask = nextTask; } } SCHEDULER_UNLOCK(intSave); If (exitFlag == 1) {⑼ MPS_DETAIL (OS_MP_CPU_ALL); LOS_Schedule(); } return LOS_OK; }Copy the code

3.4 Clearing Events

You can use the function UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 EVENTS) to clear the specified event type.

The function takes the event structure eventCB and the event type to be cleared events. The clearing event is first checked to see if the structure parameter is null, which is simpler. (1) The event mask of the event structure and the event type events to be cleared are logically and calculated to complete the event cleaning.

LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 events) { UINT32 intSave; if (eventCB == NULL) { return LOS_ERRNO_EVENT_PTR_NULL; } LOS_TRACE(EVENT_CLEAR, (UINTPTR)eventCB, eventCB->uwEventID, events); SCHEDULER_LOCK(intSave); (1) eventCB - > uwEventID & = events; SCHEDULER_UNLOCK(intSave); return LOS_OK; }Copy the code

3.5 Destruction Event

You can use the function UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) to destroy the specified event control block.

The function takes an event structure as an argument, and the destruction of the event first checks whether the structure parameter is null. The event cannot be destroyed if the task blocking list of the event is not empty. 2. Set the event mask of the event structure to 0 to complete the destruction of the event.

LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) { UINT32 intSave; UINT32 ret = LOS_OK; if (eventCB == NULL) { return LOS_ERRNO_EVENT_PTR_NULL; } SCHEDULER_LOCK(intSave); (1) if (! LOS_ListEmpty(&eventCB->stEventList)) { ret = LOS_ERRNO_EVENT_SHOULD_NOT_DESTORY; goto OUT; } ⑵ eventCB-> ventid = 0; OUT: SCHEDULER_UNLOCK(intSave); LOS_TRACE(EVENT_DELETE, (UINTPTR)eventCB, ret); return ret; }Copy the code

summary

This article leads us to analyze the source code of LiteOS event module, including event structure, event initialization, event creation and deletion, application release, etc. Thanks for reading. If you have any questions or suggestions, please leave a comment at gitee.com/LiteOS/Lite… .

Click to follow, the first time to learn about Huawei cloud fresh technology ~