?? sched.h
字號:
#define INIT_TASK \/* state etc */ { 0,15,15, \ // state, counter, priority/* signals */ 0,{ { },}, 0, \ // signal, sigaction[32], blocked /* ec,brk... */ 0, 0, 0, 0, 0, 0, \ // exit_code,start_code,end_code,end_data,brk,start_stack /* pid etc.. */ 0, -1, 0, 0, 0, \ // pid, father, pgrp, session, leader /* uid etc */ 0, 0, 0, 0, 0, 0, \ // uid, euid, suid, gid, egid, sgid /* alarm */ 0, 0, 0, 0, 0, 0, \ // alarm, utime, stime, cutime, cstime, start_time /* math */ 0, \ // used_math /* fs info */ -1, 0022, NULL, NULL, NULL, 0, \ // tty,umask,pwd,root,executable,close_on_exec/* filp */{NULL,}, \ // filp[20]{ \ // ldt[3] { 0, 0} ,/* ldt */ { 0x9f, 0xc0fa00} , \ // 代碼長640K,基址0x0,G=1,D=1,DPL=3,P=1 TYPE=0x0a { 0x9f, 0xc0f200} , \ // 數(shù)據(jù)長640K,基址0x0,G=1,D=1,DPL=3,P=1 TYPE=0x02},/*tss*/{ 0, PAGE_SIZE + (long) &init_task, 0x10, 0, 0, 0, 0, (long) &pg_dir, \ // tss 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, _LDT (0), 0x80000000, { }},}extern struct task_struct *task[NR_TASKS]; // 任務數(shù)組。extern struct task_struct *last_task_used_math; // 上一個使用過協(xié)處理器的進程。extern struct task_struct *current; // 當前進程結(jié)構指針變量。extern long volatile jiffies; // 從開機開始算起的滴答數(shù)(10ms/滴答)。extern long startup_time; // 開機時間。從1970:0:0:0 開始計時的秒數(shù)。#define CURRENT_TIME (startup_time+jiffies/HZ) // 當前時間(秒數(shù))。// 添加定時器函數(shù)(定時時間jiffies 滴答數(shù),定時到時調(diào)用函數(shù)*fn())。( kernel/sched.c,272)extern void add_timer (long jiffies, void (*fn) (void));// 不可中斷的等待睡眠。( kernel/sched.c, 151 )extern void sleep_on (struct task_struct **p);// 可中斷的等待睡眠。( kernel/sched.c, 167 )extern void interruptible_sleep_on (struct task_struct **p);// 明確喚醒睡眠的進程。( kernel/sched.c, 188 )extern void wake_up (struct task_struct **p);/** Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall* 4-TSS0, 5-LDT0, 6-TSS1 etc ...*//** 尋找第1 個TSS 在全局表中的入口。0-沒有用nul,1-代碼段cs,2-數(shù)據(jù)段ds,3-系統(tǒng)段syscall* 4-任務狀態(tài)段TSS0,5-局部表LTD0,6-任務狀態(tài)段TSS1,等。*/// 全局表中第1 個任務狀態(tài)段(TSS)描述符的選擇符索引號。#define FIRST_TSS_ENTRY 4// 全局表中第1 個局部描述符表(LDT)描述符的選擇符索引號。#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)// 宏定義,計算在全局表中第n 個任務的TSS 描述符的索引號(選擇符)。#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))// 宏定義,計算在全局表中第n 個任務的LDT 描述符的索引號。#define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))// 宏定義,加載第n 個任務的任務寄存器tr。#define ltr(n) __asm__( "ltr %%ax":: "a" (_TSS(n)))// 宏定義,加載第n 個任務的局部描述符表寄存器ldtr。#define lldt(n) __asm__( "lldt %%ax":: "a" (_LDT(n)))// 取當前運行任務的任務號(是任務數(shù)組中的索引值,與進程號pid 不同)。// 返回:n - 當前任務號。用于( kernel/traps.c, 79)。#define str(n) \__asm__( "str %%ax\n\t" \ // 將任務寄存器中TSS 段的有效地址??ax"subl %2,%%eax\n\t" \ // (eax - FIRST_TSS_ENTRY*8)??eax "shrl $4,%%eax" \ // (eax/16)??eax = 當前任務號。: "=a" (n):"a" (0), "i" (FIRST_TSS_ENTRY << 3))/** switch_to(n) should switch tasks to task nr n, first* checking that n isn't the current task, in which case it does nothing.* This also clears the TS-flag if the task we switched to has used* tha math co-processor latest.*//** switch_to(n)將切換當前任務到任務nr,即n。首先檢測任務n 不是當前任務,* 如果是則什么也不做退出。如果我們切換到的任務最近(上次運行)使用過數(shù)學* 協(xié)處理器的話,則還需復位控制寄存器cr0 中的TS 標志。*/// 輸入:%0 - 新TSS 的偏移地址(*&__tmp.a); %1 - 存放新TSS 的選擇符值(*&__tmp.b);// dx - 新任務n 的選擇符;ecx - 新任務指針task[n]。// 其中臨時數(shù)據(jù)結(jié)構__tmp 中,a 的值是32 位偏移值,b 為新TSS 的選擇符。在任務切換時,a 值// 沒有用(忽略)。在判斷新任務上次執(zhí)行是否使用過協(xié)處理器時,是通過將新任務狀態(tài)段的地址與// 保存在last_task_used_math 變量中的使用過協(xié)處理器的任務狀態(tài)段的地址進行比較而作出的。#define switch_to(n) {\struct {long a,b;} __tmp; \__asm__( "cmpl %%ecx,_current\n\t" \ // 任務n 是當前任務嗎?(current ==task[n]?) "je 1f\n\t" \ // 是,則什么都不做,退出。 "movw %%dx,%1\n\t" \ // 將新任務的選擇符??*&__tmp.b。 "xchgl %%ecx,_current\n\t" \ // current = task[n];ecx = 被切換出的任務。 "ljmp %0\n\t" \ // 執(zhí)行長跳轉(zhuǎn)至*&__tmp,造成任務切換。// 在任務切換回來后才會繼續(xù)執(zhí)行下面的語句。 "cmpl %%ecx,_last_task_used_math\n\t" \ // 新任務上次使用過協(xié)處理器嗎? "jne 1f\n\t" \ // 沒有則跳轉(zhuǎn),退出。 "clts\n" \ // 新任務上次使用過協(xié)處理器,則清cr0 的TS 標志。 "1:"::"m" (*&__tmp.a), "m" (*&__tmp.b), "d" (_TSS (n)), "c" ((long) task[n]));}// 頁面地址對準。(在內(nèi)核代碼中沒有任何地方引用!!)#define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)// 設置位于地址addr 處描述符中的各基地址字段(基地址是base),參見列表后說明。// %0 - 地址addr 偏移2;%1 - 地址addr 偏移4;%2 - 地址addr 偏移7;edx - 基地址base。#define _set_base(addr,base) \__asm__( "movw %%dx,%0\n\t" \ // 基址base 低16 位(位15-0)??[addr+2]。"rorl $16,%%edx\n\t" \ // edx 中基址高16 位(位31-16)??dx。 "movb %%dl,%1\n\t" \ // 基址高16 位中的低8 位(位23-16)??[addr+4]。 "movb %%dh,%2" \ // 基址高16 位中的高8 位(位31-24)??[addr+7]。::"m" (*((addr) + 2)), "m" (*((addr) + 4)), "m" (*((addr) + 7)), "d" (base):"dx")// 設置位于地址addr 處描述符中的段限長字段(段長是limit)。// %0 - 地址addr;%1 - 地址addr 偏移6 處;edx - 段長值limit。#define _set_limit(addr,limit) \__asm__( "movw %%dx,%0\n\t" \ // 段長limit 低16 位(位15-0)??[addr]。 "rorl $16,%%edx\n\t" \ // edx 中的段長高4 位(位19-16)??dl。 "movb %1,%%dh\n\t" \ // 取原[addr+6]字節(jié)??dh,其中高4 位是些標志。 "andb $0xf0,%%dh\n\t" \ // 清dh 的低4 位(將存放段長的位19-16)。 "orb %%dh,%%dl\n\t" \ // 將原高4 位標志和段長的高4 位(位19-16)合成1 字節(jié), "movb %%dl,%1" \ // 并放會[addr+6]處。::"m" (*(addr)), "m" (*((addr) + 6)), "d" (limit):"dx")// 設置局部描述符表中l(wèi)dt 描述符的基地址字段。#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )// 設置局部描述符表中l(wèi)dt 描述符的段長字段。#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )// 從地址addr 處描述符中取段基地址。功能與_set_base()正好相反。// edx - 存放基地址(__base);%1 - 地址addr 偏移2;%2 - 地址addr 偏移4;%3 - addr 偏移7。#define _get_base(addr) ({\unsigned long __base; \__asm__( "movb %3,%%dh\n\t" \ // 取[addr+7]處基址高16 位的高8 位(位31-24)??dh。 "movb %2,%%dl\n\t" \ // 取[addr+4]處基址高16 位的低8 位(位23-16)??dl。 "shll $16,%%edx\n\t" \ // 基地址高16 位移到edx 中高16 位處。 "movw %1,%%dx" \ // 取[addr+2]處基址低16 位(位15-0)??dx。:"=d" (__base) \ // 從而edx 中含有32 位的段基地址。:"m" (*((addr) + 2)), "m" (*((addr) + 4)), "m" (*((addr) + 7)));__base;})// 取局部描述符表中l(wèi)dt 所指段描述符中的基地址。#define get_base(ldt) _get_base( ((char *)&(ldt)) )// 取段選擇符segment 的段長值。// %0 - 存放段長值(字節(jié)數(shù));%1 - 段選擇符segment。#define get_limit(segment) ({ \unsigned long __limit; \__asm__( "lsll %1,%0\n\tincl %0": "=r" (__limit): "r" (segment)); \__limit;})#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -