前言

在软件世界外面,超时是一个十分重要的概念。比方
● 以后线程临时休眠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内核如何实现这个超时逻辑的呢,咱们接着看下一个章节

原理


如上图所示。在时间轴上,黄色圆点代表须要进行某种操作的工夫点,而绿色圆点为查看零碎是否有超时事件须要解决的查看工夫点。零碎周期性的进行查看(周期单位为tick)。在2个检查点之间可能有超时事件,也可能无超时事件。
例如,依据上图展现的状况。以后在第一个检查点,发现了2个超时事件,那么这次解决这2个超时事件;随着工夫流逝,箭头来到第2个检查点,又发现2个超时事件,持续解决;在第3个检查点时,本段时间内无超时事件,所以是空操作。后续的查看以此类推。

代码实现

为了准确性以及时效性,本文选取了最新的版本的代码来形容。上述检查点和工夫点由链表构造进行定义。具体在kernel/liteos_m/include/los_sortlink.h文件中。

因为原理图中的超时事件产生是非平均的,且存在有序顺次产生的逻辑,所以,这些信息被保护在双向链表中(对删除操作更敌对)。
SortLinkList代表了链表中的每一个须要处理事件的工夫点,responseTime代表具体的工夫值(从启机开始的cpu cycle数目)。SortLinkAttribute代表链表的头部(哑头)。从名称也能看出,这个是一个排序的双向链表,排序的根据即responseTime这个数值。
须要留神的一个细节是:零碎反对2个链表,其中一个是TASK链表,另一个是SWTMR链表。这2个链表实现形式统一,次要区别是,SWTMR链表超时解决是唤醒swtmr线程来解决超时事件,而task链表唤醒的是每个具体的task(sleep,ipc超时等场景)。应用swtmr线程来解决若干超时的机制,能够无效缩小零碎须要的线程数目,从而节俭系统资源的占用。

总结

本文形容了超时逻辑在OpenHarmony中的实现,从原理,应用以及具体实现细节上进行了详尽探讨,并演绎整顿了以后这种实现形式所带来的好处。