就緒(Ready):
該任務(wù)在就緒列表中,只等待CPU。
運(yùn)行(Running):
該任務(wù)正在執(zhí)行。
阻塞(Blocked):
該任務(wù)不在就緒列表中。
包含任務(wù)被掛起、任務(wù)被延時(shí)、任務(wù)正在等待信號(hào)量、讀寫隊(duì)列或者等待讀寫事件等。
任務(wù)合法性(TaskId)及任務(wù)狀態(tài)校驗(yàn):判斷任務(wù)序號(hào)以及任務(wù)當(dāng)前狀態(tài)是否確實(shí)為掛起。
改變?nèi)蝿?wù)狀態(tài):將任務(wù)的suspend狀態(tài)位清掉
起用任務(wù)調(diào)度:如果任務(wù)被阻塞,則調(diào)起LOS_Schedule進(jìn)行調(diào)度。
初始化任務(wù)隊(duì)列
加入任務(wù)
循環(huán)處理任務(wù)
銷毀任務(wù)隊(duì)列
void *taosProcessSchedQueue(void *param) {
SSchedMsg msg;
SSchedQueue *pSched = (SSchedQueue *)param;
while (1) {
if (sem_wait(&pSched->fullSem) != 0) {
pError('wait %s fullSem failed, errno:%d, reason:%s', pSched->label, errno, strerror(errno));
if (errno == EINTR) {
/* sem_wait is interrupted by interrupt, ignore and continue */
continue;
}
}
if (pthread_mutex_lock(&pSched->queueMutex) != 0)
pError('lock %s queueMutex failed, reason:%s', pSched->label, strerror(errno));
msg = pSched->queue[pSched->fullSlot];
memset(pSched->queue pSched->fullSlot, 0, sizeof(SSchedMsg));
pSched->fullSlot = (pSched->fullSlot 1) % pSched->queueSize;//從隊(duì)尾取出消息不斷處理
if (pthread_mutex_unlock(&pSched->queueMutex) != 0)
pError('unlock %s queueMutex failed, reason:%s
', pSched->label, strerror(errno));
if (sem_post(&pSched->emptySem) != 0)
pError('post %s emptySem failed, reason:%s
', pSched->label, strerror(errno));
if (msg.fp)
(*(msg.fp))(&msg);
else if (msg.tfp)
(*(msg.tfp))(msg.ahandle, msg.thandle);
}
}
int taosScheduleTask(void *qhandle, SSchedMsg *pMsg) {
SSchedQueue *pSched = (SSchedQueue *)qhandle;
if (pSched == NULL) {
pError('sched is not ready, msg:%p is dropped', pMsg);
return 0;
}
if (sem_wait(&pSched->emptySem) != 0) pError('wait %s emptySem failed, reason:%s', pSched->label, strerror(errno));
if (pthread_mutex_lock(&pSched->queueMutex) != 0)
pError('lock %s queueMutex failed, reason:%s', pSched->label, strerror(errno));
pSched->queue[pSched->emptySlot] = *pMsg;
pSched->emptySlot = (pSched->emptySlot 1) % pSched->queueSize;
if (pthread_mutex_unlock(&pSched->queueMutex) != 0)
pError('unlock %s queueMutex failed, reason:%s', pSched->label, strerror(errno));
if (sem_post(&pSched->fullSem) != 0) pError('post %s fullSem failed, reason:%s', pSched->label, strerror(errno));
return 0;
}
軟件定時(shí)器是系統(tǒng)資源,在模塊初始化的時(shí)候已經(jīng)分配了一塊連續(xù)的內(nèi)存,系統(tǒng)支持的最大定時(shí)器個(gè)數(shù)可以在los_config.h文件中配置。
軟件定時(shí)器使用了系統(tǒng)的一個(gè)隊(duì)列和任務(wù)資源,軟件定時(shí)器的觸發(fā)遵循隊(duì)列規(guī)則,先進(jìn)先出。
定時(shí)時(shí)間短的定時(shí)器總是比定時(shí)時(shí)間長(zhǎng)的靠近隊(duì)列頭,滿足優(yōu)先被觸發(fā)的準(zhǔn)則。
軟件定時(shí)器以Tick為基本計(jì)時(shí)單位,當(dāng)用戶創(chuàng)建并啟動(dòng)一個(gè)軟件定時(shí)器時(shí),Huawei LiteOS會(huì)根據(jù)當(dāng)前系統(tǒng)Tick時(shí)間及用戶設(shè)置的定時(shí)間隔確定該定時(shí)器的到期Tick時(shí)間,并將該定時(shí)器控制結(jié)構(gòu)掛入計(jì)時(shí)全局鏈表。
當(dāng)Tick中斷到來(lái)時(shí),在Tick中斷處理函數(shù)中掃描軟件定時(shí)器的計(jì)時(shí)全局鏈表,看是否有定時(shí)器超時(shí),若有則將超時(shí)的定時(shí)器記錄下來(lái)。
Tick處理結(jié)束后,軟件定時(shí)器任務(wù)(優(yōu)先級(jí)為最高)被喚醒,在該任務(wù)中調(diào)用之前記錄下來(lái)的超時(shí)定時(shí)器的處理函數(shù)。
首先明確鴻蒙的定時(shí)器是為了節(jié)省硬件定時(shí)器資源而設(shè)計(jì)的。
由于硬件定時(shí)器往往數(shù)量有限而系統(tǒng)實(shí)際運(yùn)行中,對(duì)于定時(shí)器的需求往往高于硬件定時(shí)器的數(shù)量,所以操作系統(tǒng)都會(huì)實(shí)現(xiàn)軟件定時(shí)器以滿足用戶需求。
先啟動(dòng)硬件定時(shí)器,注冊(cè)硬件定時(shí)器的tick事件,也就是硬件定時(shí)器到時(shí)發(fā)生tick時(shí)會(huì)調(diào)用軟件定時(shí)器的處理函數(shù)。
將在同一時(shí)刻到期的timer放在同一鏈表中。
在硬件產(chǎn)生tick事件時(shí),取出當(dāng)時(shí)到期的定時(shí)器列表,并順序調(diào)起鏈表內(nèi)所有到時(shí)定時(shí)器的處理函數(shù)。
以上函數(shù)的運(yùn)行原理動(dòng)畫解析如下:
聯(lián)系客服