读了鸿蒙 OS 的代码后,我发现优秀项目都有这个共性!
作者 | 馬超
責(zé)編 | 胡巍巍
出品 | 程序人生(ID:coder_life)
兩個(gè)項(xiàng)目對于任務(wù)調(diào)度模塊的實(shí)現(xiàn)對比1.鴻蒙OS的調(diào)度模塊與一般操作系統(tǒng)一樣,鴻蒙也將任務(wù)狀態(tài)通常分為以下三種:
就緒(Ready):該任務(wù)在就緒列表中,只等待CPU。
運(yùn)行(Running):該任務(wù)正在執(zhí)行。
阻塞(Blocked):該任務(wù)不在就緒列表中。包含任務(wù)被掛起、任務(wù)被延時(shí)、任務(wù)正在等待信號量、讀寫隊(duì)列或者等待讀寫事件等。
{
????UINTPTR?uvIntSave;
????LOS_TASK_CB?*pstTaskCB;
????UINT16?usTempStatus;
????UINT32?uwErrRet?=?OS_ERROR;
????if?(uwTaskID?>?LOSCFG_BASE_CORE_TSK_LIMIT)
????{
????????return?LOS_ERRNO_TSK_ID_INVALID;
????}
????pstTaskCB?=?OS_TCB_FROM_TID(uwTaskID);
????uvIntSave?=?LOS_IntLock();
????usTempStatus?=?pstTaskCB->usTaskStatus;
????if?(OS_TASK_STATUS_UNUSED?&?usTempStatus)
????{
????????uwErrRet?=?LOS_ERRNO_TSK_NOT_CREATED;
????????OS_GOTO_ERREND();
????}
????else?if?(!(OS_TASK_STATUS_SUSPEND?&?usTempStatus))
????{
????????uwErrRet?=?LOS_ERRNO_TSK_NOT_SUSPENDED;
????????OS_GOTO_ERREND();
????}
????//以上為任務(wù)狀態(tài)檢查
????pstTaskCB->usTaskStatus?&=?(~OS_TASK_STATUS_SUSPEND);//清除任務(wù)的suspend標(biāo)志位置
????if?(!(OS_CHECK_TASK_BLOCK?&?pstTaskCB->usTaskStatus)?)//若任務(wù)的還自在阻塞狀態(tài)則變?yōu)榫途w狀態(tài)?,并調(diào)用?LOS_Schedule()進(jìn)行調(diào)度
????{
????????pstTaskCB->usTaskStatus?|=?OS_TASK_STATUS_READY;
????????LOS_PriqueueEnqueue(&pstTaskCB->stPendList,?pstTaskCB->usPriority);
????????if?(g_bTaskScheduled)
????????{
????????????(VOID)LOS_IntRestore(uvIntSave);
????????????LOS_Schedule();
????????????return?LOS_OK;
????????}
????????g_stLosTask.pstNewTask?=?LOS_DL_LIST_ENTRY(LOS_PriqueueTop(),?LOS_TASK_CB,?stPendList);?/*lint?!e413*/
????}
????(VOID)LOS_IntRestore(uvIntSave);
????return?LOS_OK;
LOS_ERREND:
????(VOID)LOS_IntRestore(uvIntSave);
????return?uwErrRet;
}
我們看到這個(gè)函數(shù)的處理過程基本分為三步:
任務(wù)合法性(TaskId)及任務(wù)狀態(tài)校驗(yàn):判斷任務(wù)序號以及任務(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ì)列
??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\n",?pSched->label,?strerror(errno));
????if?(sem_post(&pSched->emptySem)?!=?0)
??????pError("post?%s?emptySem?failed,?reason:%s\n",?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í)間長的靠近隊(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中斷到來時(shí),在Tick中斷處理函數(shù)中掃描軟件定時(shí)器的計(jì)時(shí)全局鏈表,看是否有定時(shí)器超時(shí),若有則將超時(shí)的定時(shí)器記錄下來。
Tick處理結(jié)束后,軟件定時(shí)器任務(wù)(優(yōu)先級為最高)被喚醒,在該任務(wù)中調(diào)用之前記錄下來的超時(shí)定時(shí)器的處理函數(shù)。
首先明確鴻蒙的定時(shí)器是為了節(jié)省硬件定時(shí)器資源而設(shè)計(jì)的。
由于硬件定時(shí)器往往數(shù)量有限而系統(tǒng)實(shí)際運(yùn)行中,對于定時(shí)器的需求往往高于硬件定時(shí)器的數(shù)量,所以操作系統(tǒng)都會(huì)實(shí)現(xiàn)軟件定時(shí)器以滿足用戶需求。
先啟動(dòng)硬件定時(shí)器,注冊硬件定時(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ù)。
{
????SWTMR_HANDLER_ITEM_P?pstSwtmrHandle?=?(SWTMR_HANDLER_ITEM_P)NULL;
????SWTMR_HANDLER_ITEM_S?stSwtmrHandle;
????UINT32?uwRet;
????for?(?;?;?)
????{
????????uwRet?=?LOS_QueueRead(m_uwSwTmrHandlerQueue,?&pstSwtmrHandle,?sizeof(SWTMR_HANDLER_ITEM_P),?LOS_WAIT_FOREVER);
????????if?(uwRet?==?LOS_OK)
????????{
????????????if?(pstSwtmrHandle?!=?NULL)
????????????{
????????????????stSwtmrHandle.pfnHandler?=?pstSwtmrHandle->pfnHandler;
????????????????stSwtmrHandle.uwArg?=?pstSwtmrHandle->uwArg;
????????????????(VOID)LOS_MemboxFree(m_aucSwTmrHandlerPool,?pstSwtmrHandle);
????????????????if?(stSwtmrHandle.pfnHandler?!=?NULL)
????????????????{
????????????????????stSwtmrHandle.pfnHandler(stSwtmrHandle.uwArg);
????????????????}
????????????}
????????}
????}//end?of?for
}
以上函數(shù)的運(yùn)行原理動(dòng)畫解析如下:
結(jié)語從上面這兩個(gè)簡單的模塊中我們也看到這些優(yōu)秀的項(xiàng)目都使用最精簡的設(shè)計(jì),緊貼需求、甩掉包袱、輕裝上陣才能回歸本質(zhì)取得成功。無論是TdEngine取消任務(wù)調(diào)度的優(yōu)先級排序,還是鴻蒙放棄對定時(shí)器精度的支持,都是看來出乎意料,實(shí)則頗具內(nèi)涵的減法操作。真正優(yōu)秀的項(xiàng)目都是敢于做減法的,只有減掉那些看似高大上的設(shè)計(jì),才能向著有取有舍,大道至簡的境界邁進(jìn)。原文:https://blog.csdn.net/BEYONDMA/article/details/100049796?utm_source=app
在 GitHub 更新中,歡迎關(guān)注,歡迎star。
直面Java第262期:volatile是如何解決有序性問題的?
深入并發(fā)第009期:到底什么是Java內(nèi)存模型?
- MORE | 更多精彩文章 -
如果你喜歡本文,
請長按二維碼,關(guān)注?Hollis.
轉(zhuǎn)發(fā)至朋友圈,是對我最大的支持。
好文章,我在看??
總結(jié)
以上是生活随笔為你收集整理的读了鸿蒙 OS 的代码后,我发现优秀项目都有这个共性!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot 2.x Shard
- 下一篇: CodeForces 321A Ciel