日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

Linux操作系統(tǒng)內(nèi)核搶占補(bǔ)丁的基本原理

CPU在內(nèi)核中運行時并不是處處不可搶占的 , 內(nèi)核中存在一些空隙 , 在這時進(jìn)行搶占是安全的 , 內(nèi)核搶占補(bǔ)丁的基本原理就是將SMP可并行的代碼段看成是可以進(jìn)行內(nèi)核搶占的區(qū)域 。
2.4內(nèi)核正好細(xì)化了多CPU下的內(nèi)核線程同步機(jī)構(gòu) , 對不可并行的指令塊用spinlock和rwlock作了細(xì)致的表示 , 該補(bǔ)丁的實現(xiàn)可謂水到渠成 。具體的方法就是在進(jìn)程的任務(wù)結(jié)構(gòu)上增加一個preempt_count變量作為內(nèi)核搶占鎖 , 它隨著spinlock和rwlock一起加鎖和解鎖 。當(dāng)preempt_count為0時表示可以進(jìn)行內(nèi)核調(diào)度 。內(nèi)核調(diào)度器的入口為preempt_schedule() , 它將當(dāng)前進(jìn)程標(biāo)記為TASK_PREEMPTED狀態(tài)再調(diào)用schedule() , 在TASK_PREEMPTED狀態(tài) , schedule()不會將進(jìn)程從運行隊列中刪除 。
下面是內(nèi)核搶占補(bǔ)丁的主要代碼示意:
【Linux操作系統(tǒng)內(nèi)核搶占補(bǔ)丁的基本原理】
arch/i386/kernel/entry.S:
preempt_count = 4 # 將task_struct中的flags用作preempt_count,flags被移到了別
的位置
ret_from_exception: # 從異常返回
#ifdef CONFIG_SMP
GET_CURRENT(離)
movl processor(離),陎
shll $CONFIG_X86_L1_CACHE_SHIFT,陎
movl SYMBOL_NAME(irq_stat)(,陎),靫 # softirq_active
testl SYMBOL_NAME(irq_stat) 4(,陎),靫 # softirq_mask
#else
movl SYMBOL_NAME(irq_stat),靫 # softirq_active
testl SYMBOL_NAME(irq_stat) 4,靫 # softirq_mask
#endif
jne handle_softirq
#ifdef CONFIG_PREEMPT
cli
incl preempt_count(離) # 異常的入口沒有禁止內(nèi)核調(diào)度的指令,與ret_from_intr
匹配一下
#endif
ENTRY(ret_from_intr) # 硬件中斷的返回
GET_CURRENT(離)
#ifdef CONFIG_PREEMPT
cli
decl preempt_count(離) # 恢復(fù)內(nèi)核搶占標(biāo)志
#endif
movl EFLAGS(%esp),陎 # mix EFLAGS and CS
movb CS(%esp),%al
testl $(VM_MASK | 3),陎 # return to VM86 mode or non-supervisor?
jne ret_with_reschedule
#ifdef CONFIG_PREEMPT
cmpl $0,preempt_count(離)
jnz restore_all # 如果preempt_count非零則表示禁止內(nèi)核搶占
cmpl $0,need_resched(離)
jz restore_all #
movl SYMBOL_NAME(irq_stat) irq_stat_local_bh_count CPU_INDX,靫
addl SYMBOL_NAME(irq_stat) irq_stat_local_irq_count CPU_INDX,靫
jnz restore_all
incl preempt_count(離)
sti
call SYMBOL_NAME(preempt_schedule)
jmp ret_from_intr # 新進(jìn)程返回,返回ret_from_intr恢復(fù)搶占標(biāo)志后再返回
#else
jmp restore_all
#endif
ALIGN
handle_softirq:
#ifdef CONFIG_PREEMPT
cli
GET_CURRENT(離)
incl preempt_count(離)
sti
#endif
call SYMBOL_NAME(do_softirq)
jmp ret_from_intr
ALIGN
reschedule:
call SYMBOL_NAME(schedule) # test
jmp ret_from_sys_call
include/asm/hw_irq.h:
...
#ifdef CONFIG_PREEMPT
#define BUMP_CONTEX_SWITCH_LOCK
GET_CURRENT
"incl 4(離)nt"
#else
#define BUMP_CONTEX_SWITCH_LOCK
#endif
#define SAVE_ALL硬件中斷保護(hù)入口現(xiàn)場
"cldnt"
"pushl %esnt"
"pushl %dsnt"
"pushl 陎nt"
"pushl 雙nt"
"pushl 韎nt"
"pushl %esint"
"pushl 韝nt"
"pushl 靫nt"
"pushl 離nt"
"movl $" STR(__KERNEL_DS) ",韝nt"
"movl 韝,%dsnt"
"movl 韝,%esnt"
BUMP_CONTEX_SWITCH_LOCK # 硬件中斷的入口禁止內(nèi)核搶占
include/linux/spinlock.h:
#ifdef CONFIG_PREEMPT
#define switch_lock_count() current->preempt_count
#define in_ctx_sw_off() (switch_lock_count().counter) 判斷當(dāng)前進(jìn)程的搶占計數(shù)
是否非零
#define atomic_ptr_in_ctx_sw_off() (&switch_lock_count())
#define ctx_sw_off()禁止內(nèi)核搶占
do {
atomic_inc(atomic_ptr_in_ctx_sw_off());當(dāng)前進(jìn)程的內(nèi)核搶占計數(shù)增1
} while (0)
#define ctx_sw_on_no_preempt()允許內(nèi)核搶占
do {
atomic_dec(atomic_ptr_in_ctx_sw_off());當(dāng)前進(jìn)程的內(nèi)核搶占計數(shù)減1
} while (0)
#define ctx_sw_on()允許并完成內(nèi)核搶占
do {
if (atomic_dec_and_test(atomic_ptr_in_ctx_sw_off()) &&
current->need_resched)
preempt_schedule();

推薦閱讀