前语

软件世界里边,超时是一个非常重要的概念。比方

● 当时线程暂时休眠1秒钟,休眠完毕后持续履行

● 每5秒钟收集一下CPU利用率

● 数据发送失利,2秒钟以后再试一试

● 等候某种数据,但最多等候50毫秒

运用

//将当时任务休眠若干tick数,tick为时刻单位,常见值为10毫秒

LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)

//获取信号量semHandle, 假如当时信号量不可用且timeout不为0,则最多等候timeout所指定的时刻,在这段时刻内假如信号量可用,则获取成功,不然获取失利。

LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)

//从空的音讯队列读取音讯,或者向满的音讯队列写音讯时,假如timeout不为0,则最多等候timeout指定的时刻,在这段时刻内音讯队列可读或可写,则进行对应的读写并回来成功,不然回来失利。

LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)

LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut)

//获取互斥锁,假如当时互斥锁被其它线程占用,则最多等候timeout指定的时刻,此时刻内其它线程释放了互斥锁并被本线程抢到则回来成功,不然回来失利。

LITE_OS_SEC_TEXT UINT32 LOS_MuxPend(UINT32 muxHandle, UINT32 timeout)

//等候其它线程向本线程发送事情,最多等候timout指定的时刻

LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeOut)

上述这些函数都是超时概念在OpenHarmony中liteos_m内核里的详细运用。

详细而言,liteos_m内核如何完成这个超时逻辑的呢,我们接着看下一个章节

原理

对OpenHarmony中LiteOS的内核分析——超时原理和应用

如上图所示。在时刻轴上,黄色圆点代表需求进行某种操作的时刻点,而绿色圆点为查看体系是否有超时事情需求处理的查看时刻点。体系周期性的进行查看(周期单位为tick)。在2个查看点之间或许有超时事情,也或许无超时事情。

例如,根据上图展示的状况。当时在第一个查看点,发现了2个超时事情,那么这次处理这2个超时事情;随着时刻流逝,箭头来到第2个查看点,又发现2个超时事情,持续处理;在第3个查看点时,本段时刻内无超时事情,所以是空操作。后续的查看以此类推。

代码完成

为了准确性以及时效性,本文选取了最新的版本的代码来描述。上述查看点和时刻点由链表结构进行界说。详细在kernel/liteos_m/include/los_sortlink.h文件中。

对OpenHarmony中LiteOS的内核分析——超时原理和应用

因为原理图中的超时事情发生是非均匀的,且存在有序依次发生的逻辑,所以,这些信息被维护在双向链表中(对删去操作更友好)。

SortLinkList代表了链表中的每一个需求处理事情的时刻点,responseTime代表详细的时刻值(从启机开端的cpu cycle数目)。SortLinkAttribute代表链表的头部(哑头)。从名称也能看出,这个是一个排序的双向链表,排序的依据即responseTime这个数值。

需求留意的一个细节是:体系支持2个链表,其中一个是TASK链表,另一个是SWTMR链表。这2个链表完成方法共同,主要区别是,SWTMR链表超时处理是唤醒swtmr线程来处理超时事情,而task链表唤醒的是每个详细的task(sleep,ipc超时等场景)。运用swtmr线程来处理若干超时的机制,能够有用减少体系需求的线程数目,从而节约体系资源的占用。

总结

本文描述了超时逻辑在OpenHarmony中的完成,从原理,运用以及详细完成细节进步行了详尽评论,并概括收拾了当时这种完成方法所带来的好处。