#define switch_to(n) __tmp; \
__asm__("cmpl %%ecx,current\n\t" \
"je 1f\n\t" \
"movw %%dx,%1\n\t" \
"xchgl %%ecx,current\n\t" \
"ljmp *%0\n\t" \
"cmpl %%ecx,last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:" \
::"m" (*&__tmp.a),"m" (*&__tmp.b), \
"d" (_tss(n)),"c" ((long) task[n])); \
}
上面的嵌入巨集彙編**就是完成任務的切換操作。首先判斷傳遞進來的任務號n是否是當前任務,如果是就跳出,否則將current指向task[n],然後長跳轉任務n的tss選擇符,這樣就完成了任務切換操作。
注意:1. 跳轉到tss段選擇符會造成任務切換到該tss對應的程序。
2. 對於造成任務切換的長跳轉,tss段基址無用。
在保護模式下cpu進行長跳轉,如果發現段選擇符指向tss段,那麼cpu將會自動將tss段的內容載入到當前cpu暫存器中,比如eax,ldr,cs,ss,esp等等,其實就是104位元組的tss結構的所有成員變數賦值給cpu暫存器(注意這裡是ss0和esp0)。再次強調這個過程是自動完成的。程序tss結構的初始值在copy_process函式中完成,最後呼叫set_tss_desc函式將tss段插入到gdt描述符表中,在該函式中設定tss的段基址和段長度(104位元組)。
**中 ljmp *%0 指令需要說明下,對於長跳轉首先要指定段暫存器,其次就是偏移。在32位保護模式下,長跳轉段暫存器其實也就變成了段選擇符,即ljmp sel:offset。**中該條指令的運算元是乙個結構體,其實這個結構體的第乙個成員就是偏移,第二個成員也就是選擇子了。由於選擇子是16位的,所以第二個成員的高2位元組無用,程式中定義成32位的long型是為了位元組對齊。所以要跳轉到任務n的tss段,首先就要對__tmp結構的b成員賦值,如果目標段為tss段,則段基址無用,至於原因,這是intel規定的,所以沒有為什麼。因此最後ljmp *%0就是ljmp __tmp.b : __tmp.a
Linux 0 11幾個重要的切換
機器上電自動進入16位實模式,在setup.s中設定機器狀態字cr0的保護模式位元位,然後通過一條段間跳轉,開始執行head.s。所以,從head.s開始,作業系統才執行在保護模式中。軟體在head.s中設定了頁目錄表和前4個頁表,在設定了cr0的分頁操作位元位後,跳轉入main函式。所以從main...
Cortex M3 任務切換函式例項
建立人 ruo xiao 1 該函式的功能是初步理解任務切換的本質,即 儲存當前任務所使用的暫存器 r4 r11 的值到記憶體,中斷或者異常服務例程執行完之後,再恢復中斷或者異常之前任務的暫存器的值,從而繼續執行該任務。2 第8行 第13行 是當前任務所使用的暫存器儲存到記憶體。3 第16行 第18...
32位保護模式學習小結 3 任務切換
協同式 從乙個任務切換到另乙個任務,需要當前任務主動地請求暫時放棄執行權,或者在通過呼叫門請求作業系統服務時,由作業系統 趁機 將控制轉移到另乙個任務.這種方式依賴於每個任務的 自律 性,當乙個任務失控時,其他任務可能得不到執行的機會.搶占式 這種方式下,可以安裝乙個定時器中斷,並在中斷服務程式中實...