uC OS II原始碼分析(六)

2021-09-20 14:52:12 字數 2872 閱讀 5587

μc/os-ⅱ總是執行進入就緒態任務中優先順序最高的那乙個。確定哪個任務優先順序最高,

下面該哪個任務執行了的工作是由排程器(scheduler)完成的。任務級的排程是由函式

ossched()完成的。中斷級的排程是由另乙個函式osintext() 完成的,這個函式將在以後描

述。ossched() 的**如下:

void os_sched (void)

}os_exit_critical();

}#define ucos 0x80 /*用於任務切換的中斷向量*/

#define os_task_sw() asm int ucos

μc/os-ⅱ任務排程所花的時間是常數,與應用程式中建立的任務數無關。任務切換很簡單,由以下兩步完成,將被掛起任務的微處理器暫存器推入堆疊,然後將較高優先順序的任務的暫存器值從棧中恢復到暫存器中。在μc/os-ⅱ中,就緒任務的棧結構總是看起來跟剛剛發生過中斷一樣,所有微處理器的暫存器都儲存在棧中。換句話說,μc/os-ⅱ執行就緒態的任務所要做的一切,只是恢復所有的cpu 暫存器並執行中斷返回指令。為了做任務切換,執行os_task_sw(), 人為模仿了一次中斷。多數微處理器有軟中斷指令或者陷阱指令trap 來實現上述操作。中斷服務子程式或陷阱處理(trap hardler),也稱作事故處理(exception handler),必須提供中斷向量給組合語言函式osctxsw() 。osctxsw() 除了需要os_tcbhighrdy 指向即將被掛起的任務,還需要讓當前任務控制塊ostcbcur 指向即將被掛起的任務,

ossched()的所有**都屬臨界段**。在尋找進入就緒態的優先順序最高的任務過程中,

為防止中斷服務子程式把乙個或幾個任務的就緒位置位,中斷是被關掉的。為縮短切換時間,

ossched()全部**都可以用組合語言寫。為增加可讀性,可移植性和將組合語言**最少

化,ossched() 是用c 寫的。

osctxsw**:

_osctxsw proc far

pusha ; 儲存當前任務的上下文

push es ;

push ds ;

mov ax, seg _ostcbcur ; reload ds in case it was altered

mov ds, ax ;

les bx, dword ptr ds:_ostcbcur ; ostcbcur->ostcbstkptr = ss:sp

mov es:[bx+2], ss ;

mov es:[bx+0], sp ;

call far ptr _ostaskswhook ; call user defined task switch hook

mov ax, word ptr ds:_ostcbhighrdy+2 ; ostcbcur = ostcbhighrdy

mov dx, word ptr ds:_ostcbhighrdy ;

mov word ptr ds:_ostcbcur+2, ax ;

mov word ptr ds:_ostcbcur, dx ;

mov al, byte ptr ds:_ospriohighrdy ; ospriocur = ospriohighrdy

mov byte ptr ds:_ospriocur, al ;

les bx, dword ptr ds:_ostcbhighrdy ; ss:sp = ostcbhighrdy->ostcbstkptr

mov ss, es:[bx+2] ;

mov sp, es:[bx] ;

pop ds ; 載入新任務的上下文

pop es ;

popa ;

iret ; 返回到新任務中

_osctxsw endp

3. 給排程器上鎖和開鎖(locking and unlocking the scheduler)

給排程器上鎖函式osschedlock()用於禁止任務排程,直到任務完成後呼叫給排程器開鎖函式osschedunlock() 為止。呼叫osschedlock() 的任務保持對cpu 的控制權,儘管有個優先順序更高的任務進入了就緒態。然而,此時中斷是可以被識別的,中斷服務也能得到(假設中斷是開著的)。osschedlock() 和osschedunlock() 必須成對使用。變數oslocknesting 跟蹤osschedlock() 函式被呼叫的次數,以允許巢狀的函式包含臨界段**,這段**其它任務不得干預。μc/os-ⅱ允許巢狀深度達255 層。當oslocknesting 等於零時,排程重新得到允許。函式osschedlock() 和osschedunlock() 的使用要非常謹慎,因為它們影響μc/os-ⅱ對任務的正常管理。

當oslocknesting 減到零的時候, osschedunlock() 呼叫ossched[l3.10(2)] 。

osschedunlock() 是被某任務呼叫的,在排程器上鎖的期間,可能有什麼事件發生了並使一

個更高優先順序的任務進入就緒態。

呼叫osschedlock() 以後,使用者的應用程式不得使用任何能將現行任務掛起的系統調

用。也就是說,使用者程式不得呼叫osmboxpend() 、osqpend() 、ossempend() 、

ostasksuspend(os_pr1o_self) 、ostimedly() 或ostimedlyhmsm(), 直到oslocknesting 回零為止。因為排程器上了鎖,使用者就鎖住了系統,任何其它任務都不能執行。

當低優先順序的任務要發訊息給多工的郵箱、訊息佇列、訊號量時,使用者不希望高優先順序的任務在郵箱、佇列和訊號量沒有得到訊息之前就取得了cpu 的控制權,此時,使用者可以使用禁止排程器函式。

給排程器上鎖

void osschedlock (void)

}給排程器開鎖.

void osschedunlock (void)

else

} else }}

uC OS II原始碼分析(六)

c os 總是執行進入就緒態任務中優先順序最高的那乙個。確定哪個任務優先順序最高,下面該哪個任務執行了的工作是由排程器 scheduler 完成的。任務級的排程是由函式 ossched 完成的。中斷級的排程是由另乙個函式osintext 完成的,這個函式將在以後描 述。ossched 的 如下 vo...

uC OS II原始碼分析(六)

c os 總是執行進入就緒態任務中優先順序最高的那乙個。確定哪個任務優先順序最高,下面該哪個任務執行了的工作是由排程器 scheduler 完成的。任務級的排程是由函式 ossched 完成的。中斷級的排程是由另乙個函式osintext 完成的,這個函式將在以後描 述。ossched 的 如下 vo...

uC OS II原始碼分析(六)

c os 總是執行進入就緒態任務中優先順序最高的那乙個。確定哪個任務優先順序最高,下面該哪個任務執行了的工作是由排程器 scheduler 完成的。任務級的排程是由函式 ossched 完成的。中斷級的排程是由另乙個函式osintext 完成的,這個函式將在以後描 述。ossched 的 如下 vo...