女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

rt-thread 優(yōu)化系列(二) 之 同步和消息關(guān)中斷分析

出出 ? 來源:出出 ? 作者:出出 ? 2022-06-21 09:47 ? 次閱讀

前言

書接前文,上篇優(yōu)化聊的是關(guān)中斷操作,在很多地方過保護(hù),導(dǎo)致關(guān)中斷時間太久,可能引起其它中斷不能及時響應(yīng)。今天特意說說線程間同步和通信,分析一下它們是怎么影響關(guān)中斷時間的,比起前文會有些深入分析。

從 rt_mq_send_wait 說起

為了方便談問題先貼一段代碼,這段代碼是從 4.0.4 版本的 `rt_mq_send_wait` 函數(shù)中摘取的部分。

   /* disable interrupt */
   temp = rt_hw_interrupt_disable();
   /* get a free list, there must be an empty item */
   msg = (struct rt_mq_message *)mq->msg_queue_free;
   /* for non-blocking call */
   if (msg == RT_NULL && timeout == 0)
   {
       /* enable interrupt */
       rt_hw_interrupt_enable(temp);

       return -RT_EFULL;
   }

   /* message queue is full */
   while ((msg = (struct rt_mq_message *)mq->msg_queue_free) == RT_NULL)
   {
       /* reset error number in thread */
       thread->error = RT_EOK;

       /* no waiting, return timeout */
       if (timeout == 0)
       {
           /* enable interrupt */
           rt_hw_interrupt_enable(temp);

           return -RT_EFULL;
       }

       RT_DEBUG_IN_THREAD_CONTEXT;
       /* suspend current thread */
       rt_ipc_list_suspend(&(mq->suspend_sender_thread),
                           thread,
                           mq->parent.parent.flag);

       /* has waiting time, start thread timer */
       if (timeout > 0)
       {
           /* get the start tick of timer */
           tick_delta = rt_tick_get();

           RT_DEBUG_LOG(RT_DEBUG_IPC, ("mq_send_wait: start timer of thread:%s\n",
                                       thread->name));

           /* reset the timeout of thread timer and start it */
           rt_timer_control(&(thread->thread_timer),
                            RT_TIMER_CTRL_SET_TIME,
                            &timeout);
           rt_timer_start(&(thread->thread_timer));
       }

       /* enable interrupt */
       rt_hw_interrupt_enable(temp);

       /* re-schedule */
       rt_schedule();

       /* resume from suspend state */
       if (thread->error != RT_EOK)
       {
           /* return error */
           return thread->error;
       }

       /* disable interrupt */
       temp = rt_hw_interrupt_disable();

       /* if it's not waiting forever and then re-calculate timeout tick */
       if (timeout > 0)
       {
           tick_delta = rt_tick_get() - tick_delta;
           timeout -= tick_delta;
           if (timeout < 0)
               timeout = 0;
       }
   }

這段代碼的大致流程是:關(guān)全局中斷,取消息隊列,如果沒有空閑消息進(jìn)入等待,將當(dāng)前線程注冊到消息隊列等待線程列表,啟動當(dāng)前線程內(nèi)置硬定時器(等待超時機(jī)制),開全局中斷,執(zhí)行任務(wù)調(diào)度,被喚醒后進(jìn)行是超時喚醒還是消息隊列空喚醒處理。

> 首先申明,這段代碼在設(shè)置等待超時時間的情況下才有效,當(dāng)?shù)谒膫€參數(shù) timeout 為 0 的時候?qū)Ρ敬畏治鰺o效。鑒于在中斷回調(diào)函數(shù)中要求不能設(shè)置 timeout 值,也就是不能進(jìn)行阻塞調(diào)用,但是本文章仍然討論在中斷回調(diào)函數(shù)中的阻塞調(diào)用情況,權(quán)作參考。下面就分兩種情況分別分析。

非中斷,線程中阻塞調(diào)用 `rt_mq_send_wait`

假設(shè)線程中調(diào)用執(zhí)行了函數(shù) `rt_mq_send_wait` 第四個參數(shù) `timeout` 不為 0 。那么上面的代碼一定執(zhí)行 while 循環(huán)體。這個 while 循環(huán)暴露的多個問題不提,讓我們把目光聚焦到啟動線程定時器和開全局中斷部分。
前言部分預(yù)先提醒了今天的主題是:啟動超時等待定時器的操作有必要在關(guān)中斷中嗎?可不可以先開中斷,然后啟動定時器?

為了說明這個問題,讓我們再設(shè)想一種使用情況,假設(shè)在線程中單純的啟動一個定時器,如下:

   rt_timer_t timer;
   timer = rt_timer_create("tim1", timer_timeout,
                           RT_NULL,  1000,
                           RT_TIMER_FLAG_PERIODIC);
   rt_timer_start(timer);

或者,

   int timeout = 1000;
   struct rt_thread *thread = rt_thread_self();
   rt_timer_control(&(thread->thread_timer),
                   RT_TIMER_CTRL_SET_TIME,
                   &timeout);
   rt_timer_start(&(thread->thread_timer));

如上用法我們會把它放到關(guān)中斷里面嗎?答案是不需要!
那么,`rt_mq_send_wait` 中的關(guān)中斷是為了保護(hù)什么?同樣是在線程中執(zhí)行,同樣的兩句代碼,同樣的使用為什么被 rt_mq_send_wait 執(zhí)行時就需要被關(guān)中斷保護(hù)了?
執(zhí)行這兩句代碼時,無論是發(fā)生普通中斷,或者有任務(wù)調(diào)度切換到了其它線程,都不應(yīng)該會影響到這個定時器被正常啟動。至于說這個 `thread` 指針,在當(dāng)前這個線程不會被強(qiáng)制刪除的前提下, `thread` 指針一直有效。

所以說,啟動超時等待定時器的操作**沒**必要在關(guān)中斷中。可以**先開中斷,然后啟動定時器**

中斷,阻塞調(diào)用 rt_mq_send_wait

> 再次申明,實際使用中避免這種用法,這里僅僅做交流,并非使用建議。

和在線程中不一樣的地方在于,線程中調(diào)用 `rt_mq_send_wait` 時 `thread` 指針*肯定*是當(dāng)前線程;在中斷中調(diào)用 rt_mq_send_wait ,因中斷不定什么時候出現(xiàn), `thread` 指針可能是任意被創(chuàng)建的(有機(jī)會進(jìn)入運行態(tài)的)線程。

為了不失一般性,我們再次假設(shè),這個中斷優(yōu)先級比較低,可能被另外一個中斷嵌套。而且假設(shè)在執(zhí)行 `rt_timer_control` 和 `rt_timer_start` 時被其它中斷打斷。這種極端情況下會出現(xiàn)什么結(jié)果以及影響?
1. 中斷中再次被中斷,同時有阻塞操作。這個定時器會被兩個地方同時使用,鑒于 `rt_timer_control` 和 `rt_timer_start` 內(nèi)部也有中斷,即便在兩個函數(shù)中間出現(xiàn)新中斷,在新中斷中這個定時器也可以被正常配置而不影響在新中斷中的定時任務(wù)!
2. 中斷中出現(xiàn) SysTick 中斷,然后有任務(wù)調(diào)度。因為前邊中斷中使用的定時器是某個不確定線程的,這時候出現(xiàn)任務(wù)調(diào)度,新線程是另外一個不確定線程,而且可以保證的是肯定是另一個不同的線程。這個新的進(jìn)程會有可能強(qiáng)制刪除前一個線程嗎?

說到這里,我們會發(fā)現(xiàn),***即便是在中斷里阻塞調(diào)用 `rt_mq_send_wait` 函數(shù), `rt_timer_control` 和 `rt_timer_start` 操作不需要被關(guān)中斷保護(hù)!***

小結(jié)

綜上分析,可以*先開中斷,然后啟動定時器,最后進(jìn)行任務(wù)調(diào)度*。而不用擔(dān)心數(shù)據(jù)共享的問題。
類似用法的函數(shù)很多,ipc.c 中每一個 rt_xxx_send 和 rt_xxx_recv rt_xxx_take 都是一個模式。

timeout 的一些討論(無關(guān)中斷)

開篇貼的代碼,考慮到了被其它線程喚醒的情況,假如等待阻塞中,等待時間還沒到但是其它線程特意喚醒了它,會執(zhí)行下面這段代碼

       /* if it's not waiting forever and then re-calculate timeout tick */
       if (timeout > 0)
       {
           tick_delta = rt_tick_get() - tick_delta;
           timeout -= tick_delta;
           if (timeout < 0)
               timeout = 0;
       }

這段代碼本身沒多少問題,有問題的是接下來判斷消息隊列是否有空閑消息,如果沒有進(jìn)入下一次阻塞中。
判斷是否有空閑消息后,判斷 timeout 是否為 0 ,為 0 說明等待時間已經(jīng)超時,開中斷退出返回。這里判斷 timeout == 0 是可以和上面這段代碼合并的。

   while (msg == RT_NULL)
   {
      ...
       /* if it's not waiting forever and then re-calculate timeout tick */
       tick_delta = rt_tick_get() - tick_delta;
       timeout -= tick_delta;
       if (timeout < 0)
           timeout = 0;
       /* no waiting, return timeout */
       if (timeout == 0)
       {
           /* enable interrupt */
           rt_hw_interrupt_enable(temp);

           return -RT_EFULL;
       }
       msg = (struct rt_mq_message *)mq->msg_queue_free;
   }

結(jié)尾

我們知道,關(guān)中斷后總需要在最短的時間內(nèi)盡快打開中斷,在【關(guān)中斷/開中斷】操作對總數(shù)無法改變的前提下。【關(guān)開/關(guān)開/關(guān)開】與【關(guān)關(guān)關(guān)/開開開】兩種框架模式是有本質(zhì)區(qū)別的:第一種模式把關(guān)中斷時間分化,每次開中斷間隙可以有機(jī)會處理中斷異常;第二種總關(guān)中斷時間可能是第一種的三倍!極大提高了丟中斷的可能性。
作為上一篇的延續(xù)和總結(jié),關(guān)中斷的話題就聊到這兒,歡迎各位一起討論。

> 本優(yōu)化系列所有提到的更改已經(jīng)提交到 gitee ,歡迎大家測試
https://gitee.com/thewon/rt_thread_repo

相關(guān)文章:
[rt-thread 系統(tǒng)優(yōu)化系列(一) 之 關(guān)中斷]( https://club.rt-thread.org/ask/article/2931.html )
[rt-thread 系統(tǒng)優(yōu)化系列(二) 之 線程間同步和通信對中斷的影響]( https://club.rt-thread.org/ask/article/2939.html )
[rt-thread 系統(tǒng)優(yōu)化系列(三) 之 軟定時器]( https://club.rt-thread.org/ask/article/2967.html )
[ rt-thread 系統(tǒng)優(yōu)化系列(四) 之 再談 ipc 中的 bug]( https://club.rt-thread.org/ask/article/3044.html )

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    904

    瀏覽量

    42510
  • 優(yōu)化
    +關(guān)注

    關(guān)注

    0

    文章

    220

    瀏覽量

    24225
  • RT-Thread
    +關(guān)注

    關(guān)注

    32

    文章

    1368

    瀏覽量

    41499
收藏 人收藏

    評論

    相關(guān)推薦
    熱點推薦

    RT-Thread記錄(九、RTT中斷處理與階段小結(jié))

    RT-Thread 內(nèi)核部分最后一個點 中斷管理,順帶著對前面所學(xué)知識做個小結(jié)。
    的頭像 發(fā)表于 06-24 10:25 ?6693次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(九、RTT<b class='flag-5'>中斷</b>處理與階段小結(jié))

    RT-Thread記錄(RT-Thread內(nèi)核啟動流程)

    在前面我們RT-Thread Studio工程基礎(chǔ)之上講一講RT-Thread內(nèi)核啟動流程.
    的頭像 發(fā)表于 06-20 00:30 ?5473次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(<b class='flag-5'>二</b>、<b class='flag-5'>RT-Thread</b>內(nèi)核啟動流程)

    RT-Thread記錄(六、IPC機(jī)制信號量互斥量事件集)

    上文說到 RT-Thread 對臨界區(qū)的處理方式有多種,其中已經(jīng)分析了關(guān)閉調(diào)度器和屏蔽中斷的方式, 本文就來學(xué)學(xué)另外的線程同步方式。
    的頭像 發(fā)表于 06-21 10:40 ?5754次閱讀
    <b class='flag-5'>RT-Thread</b>記錄(六、IPC機(jī)制<b class='flag-5'>之</b>信號量互斥量事件集)

    【原創(chuàng)精選】RT-Thread征文精選技術(shù)文章合集

    優(yōu)化系列(零) SysTick 優(yōu)化分析rt-thread 優(yōu)化系列(一)
    發(fā)表于 07-26 14:56

    RT-Thread編程指南

    RT-Thread編程指南——RT-Thread開發(fā)組(2015-03-31)。RT-Thread做為國內(nèi)有較大影響力的開源實時操作系統(tǒng),本文是RT-Thread實時操作系統(tǒng)的編程指南
    發(fā)表于 11-26 16:06 ?0次下載

    RT-Thread學(xué)習(xí)筆記系列OTA升級(1)

    RT-Thread學(xué)習(xí)筆記系列OTA升級前言硬件介紹和Bootloader配置需求與功能設(shè)計功能實現(xiàn)過程前言做一個產(chǎn)品,首先是需要設(shè)計后期可升級更新功能,否則沒有升級功能則每次出現(xiàn)問題則需要寄回
    發(fā)表于 12-14 18:50 ?1次下載
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記<b class='flag-5'>系列</b><b class='flag-5'>之</b>OTA升級(1)

    RT-Thread Studio驅(qū)動SD卡

    RT-Thread Studio驅(qū)動SD卡前言一、創(chuàng)建基本工程1、創(chuàng)建Bootloader2、創(chuàng)建項目工程、配置RT-Thread Settings三、代碼分析1.引入庫2.讀入數(shù)據(jù)
    發(fā)表于 12-27 19:13 ?20次下載
    <b class='flag-5'>RT-Thread</b> Studio驅(qū)動SD卡

    RT-Thread學(xué)習(xí)筆記 RT-Thread的架構(gòu)概述

    RT-Thread 簡介 作為一名 RTOS 的初學(xué)者,也許你對 RT-Thread 還比較陌生。然而,隨著你的深入接觸,你會逐漸發(fā)現(xiàn) RT-Thread 的魅力和它相較于其他同類型 RTOS
    的頭像 發(fā)表于 07-09 11:27 ?4895次閱讀
    <b class='flag-5'>RT-Thread</b>學(xué)習(xí)筆記 <b class='flag-5'>RT-Thread</b>的架構(gòu)概述

    RT-Thread文檔_RT-Thread 簡介

    RT-Thread文檔_RT-Thread 簡介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡介

    RT-Thread文檔_線程間同步

    RT-Thread文檔_線程間同步
    發(fā)表于 02-22 18:29 ?1次下載
    <b class='flag-5'>RT-Thread</b>文檔_線程間<b class='flag-5'>同步</b>

    RT-Thread文檔_中斷管理

    RT-Thread文檔_中斷管理
    發(fā)表于 02-22 18:30 ?2次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>中斷</b>管理

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    基于RT-Thread Studio學(xué)習(xí)

    前期準(zhǔn)備:從官網(wǎng)下載 RT-Thread Studio,弄個賬號登陸,開啟rt-thread學(xué)習(xí)之旅。
    的頭像 發(fā)表于 05-15 11:00 ?4989次閱讀
    基于<b class='flag-5'>RT-Thread</b> Studio學(xué)習(xí)

    RT-Thread入門學(xué)習(xí)筆記-熟悉全局中斷的操作

    RT-Thread中,全局中斷的操作很多,大家都知道全局中斷的【disable】與【enable】
    的頭像 發(fā)表于 06-07 14:58 ?2645次閱讀
    <b class='flag-5'>RT-Thread</b>入門學(xué)習(xí)筆記-熟悉全局<b class='flag-5'>中斷</b>的操作

    RT-Thread v5.0.2 發(fā)布

    RT-Thread 代碼倉庫地址: ●? https://github.com/RT-Thread/rt-thread RT-Thread 5.0.2 版本發(fā)布日志詳情: ●? htt
    的頭像 發(fā)表于 10-10 18:45 ?1819次閱讀
    <b class='flag-5'>RT-Thread</b> v5.0.2 發(fā)布