国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区

掃一掃
關注微信公眾號

Linux操作系統內核搶占補丁的基本原理
2006-11-29   

CPU在內核中運行時并不是處處不可搶占的,內核中存在一些空隙,在這時進行搶占是安全的,內核搶占補丁的基本原理就是將SMP可并行的代碼段看成是可以進行內核搶占的區域。

2.4內核正好細化了多CPU下的內核線程同步機構,對不可并行的指令塊用spinlock和rwlock作了細致的表示,該補丁的實現可謂水到渠成。具體的方法就是在進程的任務結構上增加一個preempt_count變量作為內核搶占鎖,它隨著spinlock和rwlock一起加鎖和解鎖。當preempt_count為0時表示可以進行內核調度。內核調度器的入口為preempt_schedule(),它將當前進程標記為TASK_PREEMPTED狀態再調用schedule(),在TASK_PREEMPTED狀態,schedule()不會將進程從運行隊列中刪除。

下面是內核搶占補丁的主要代碼示意:

arch/i386/kernel/entry.S:
preempt_count = 4 # 將task_struct中的flags用作preempt_count,flags被移到了別
的位置
ret_from_exception: # 從異常返回
#ifdef CONFIG_SMP
GET_CURRENT(%ebx)
movl processor(%ebx),%eax
shll $CONFIG_X86_L1_CACHE_SHIFT,%eax
movl SYMBOL_NAME(irq_stat)(,%eax),%ecx # softirq_active
testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx # softirq_mask
#else
movl SYMBOL_NAME(irq_stat),%ecx # softirq_active
testl SYMBOL_NAME(irq_stat)+4,%ecx # softirq_mask
#endif
jne handle_softirq
#ifdef CONFIG_PREEMPT
cli
incl preempt_count(%ebx) # 異常的入口沒有禁止內核調度的指令,與ret_from_intr
匹配一下
#endif
ENTRY(ret_from_intr) # 硬件中斷的返回
GET_CURRENT(%ebx)
#ifdef CONFIG_PREEMPT
cli
decl preempt_count(%ebx) # 恢復內核搶占標志
#endif
movl EFLAGS(%esp),%eax # mix EFLAGS and CS
movb CS(%esp),%al
testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor?
jne ret_with_reschedule
#ifdef CONFIG_PREEMPT
cmpl $0,preempt_count(%ebx)
jnz restore_all # 如果preempt_count非零則表示禁止內核搶占
cmpl $0,need_resched(%ebx)
jz restore_all #
movl SYMBOL_NAME(irq_stat)+irq_stat_local_bh_count CPU_INDX,%ecx
addl SYMBOL_NAME(irq_stat)+irq_stat_local_irq_count CPU_INDX,%ecx
jnz restore_all
incl preempt_count(%ebx)
sti
call SYMBOL_NAME(preempt_schedule)
jmp ret_from_intr # 新進程返回,返回ret_from_intr恢復搶占標志后再返回
#else
jmp restore_all
#endif
ALIGN
handle_softirq:
#ifdef CONFIG_PREEMPT
cli
GET_CURRENT(%ebx)
incl preempt_count(%ebx)
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(%ebx)\n\t"
#else
#define BUMP_CONTEX_SWITCH_LOCK
#endif
#define SAVE_ALL \ 硬件中斷保護入口現場
"cld\n\t" \
"pushl %es\n\t" \
"pushl %ds\n\t" \
"pushl %eax\n\t" \
"pushl %ebp\n\t" \
"pushl %edi\n\t" \
"pushl %esi\n\t" \
"pushl %edx\n\t" \
"pushl %ecx\n\t" \
"pushl %ebx\n\t" \
"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
"movl %edx,%ds\n\t" \
"movl %edx,%es\n\t" \
BUMP_CONTEX_SWITCH_LOCK # 硬件中斷的入口禁止內核搶占
include/linux/spinlock.h:
#ifdef CONFIG_PREEMPT
#define switch_lock_count() current->preempt_count
#define in_ctx_sw_off() (switch_lock_count().counter) 判斷當前進程的搶占計數
是否非零
#define atomic_ptr_in_ctx_sw_off() (&switch_lock_count())
#define ctx_sw_off() \ 禁止內核搶占
do { \
atomic_inc(atomic_ptr_in_ctx_sw_off()); \ 當前進程的內核搶占計數增1
} while (0)
#define ctx_sw_on_no_preempt() \ 允許內核搶占
do { \
atomic_dec(atomic_ptr_in_ctx_sw_off()); \ 當前進程的內核搶占計數減1
} while (0)
#define ctx_sw_on() \ 允許并完成內核搶占
do { \
if (atomic_dec_and_test(atomic_ptr_in_ctx_sw_off()) && \
current->need_resched) \
preempt_schedule(); \
} while (0)
#define spin_lock(lock) \
do { \
ctx_sw_off(); \ 進入自旋鎖時禁止搶占
_raw_spin_lock(lock); \
} while(0)
#define spin_trylock(lock) ({ctx_sw_off(); _raw_spin_trylock(lock) ? \鎖定并
測試原來是否上鎖
1 : ({ctx_sw_on(); 0;});})
#define spin_unlock(lock) \
do { \
_raw_spin_unlock(lock); \
ctx_sw_on(); \ 離開自旋鎖時允許并完成內核搶占
} while (0)
#define read_lock(lock) ({ctx_sw_off(); _raw_read_lock(lock);})
#define read_unlock(lock) ({_raw_read_unlock(lock); ctx_sw_on();})
#define write_lock(lock) ({ctx_sw_off(); _raw_write_lock(lock);})
#define write_unlock(lock) ({_raw_write_unlock(lock); ctx_sw_on();})
#define write_trylock(lock) ({ctx_sw_off(); _raw_write_trylock(lock) ? \
1 : ({ctx_sw_on(); 0;});})
...
include/asm/softirq.h:
#define cpu_bh_disable(cpu) do { ctx_sw_off(); local_bh_count(cpu)++; barrie
r(); } while (0)
#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--;ctx_sw_on()
; } while (0)
kernel/schedule.c:
#ifdef CONFIG_PREEMPT
asmlinkage void preempt_schedule(void)
{
while (current->need_resched) {
ctx_sw_off();
current->state |= TASK_PREEMPTED;
schedule();
current->state &= ~TASK_PREEMPTED;
ctx_sw_on_no_preempt();
}
}
#endif
asmlinkage void schedule(void)
{
struct schedule_data * sched_data;
struct task_struct *prev, *next, *p;
struct list_head *tmp;
int this_cpu, c;
#ifdef CONFIG_PREEMPT
ctx_sw_off();
#endif
if (!current->active_mm) BUG();
need_resched_back:
prev = current;
this_cpu = prev->processor;
if (in_interrupt())
goto scheduling_in_interrupt;
release_kernel_lock(prev, this_cpu);
/* Do "administrative" work here while we don't hold any locks */
if (softirq_active(this_cpu) & softirq_mask(this_cpu))
goto handle_softirq;
handle_softirq_back:
/*
* 'sched_data' is protected by the fact that we can run
* only one process per CPU.
*/
sched_data = & aligned_data[this_cpu].schedule_data;
spin_lock_irq(&runqueue_lock);
/* move an exhausted RR process to be last.. */
if (prev->policy == SCHED_RR)
goto move_rr_last;
move_rr_back:
switch (prev->state) {
case TASK_INTERRUPTIBLE:
if (signal_pending(prev)) {
prev->state = TASK_RUNNING;
break;
}
default:
#ifdef CONFIG_PREEMPT
if (prev->state & TASK_PREEMPTED)
break; 如果是內核搶占調度,則保留運行隊列
#endif
del_from_runqueue(prev);
#ifdef CONFIG_PREEMPT
case TASK_PREEMPTED:
#endif
case TASK_RUNNING:
}
prev->need_resched = 0;
/*
* this is the scheduler proper:
*/
repeat_schedule:
/*
* Default process to select..
*/
next = idle_task(this_cpu);
c = -1000;
if (task_on_runqueue(prev))
goto still_running;
still_running_back:
list_for_each(tmp, &runqueue_head) {
p = list_entry(tmp, struct task_struct, run_list);
if (can_schedule(p, this_cpu)) {
int weight = goodness(p, this_cpu, prev->active_mm);
if (weight > c)
c = weight, next = p;
}
}
/* Do we need to re-calculate counters? */
if (!c)
goto recalculate;
/*
* from this point on nothing can prevent us from
* switching to the next task, save this fact in
* sched_data.
*/
sched_data->curr = next;
#ifdef CONFIG_SMP
next->has_cpu = 1;
next->processor = this_cpu;
#endif
spin_unlock_irq(&runqueue_lock);
if (prev == next)
goto same_process;
#ifdef CONFIG_SMP
/*
* maintain the per-process 'last schedule' value.
* (this has to be recalculated even if we reschedule to
* the same process) Currently this is only used on SMP,
* and it's approximate, so we do not have to maintain
* it while holding the runqueue spinlock.
*/
sched_data->last_schedule = get_cycles();
/*
* We drop the scheduler lock early (it's a global spinlock),
* thus we have to lock the previous process from getting
* rescheduled during switch_to().
*/
#endif /* CONFIG_SMP */
kstat.context_swtch++;
/*
* there are 3 processes which are affected by a context switch:
*
* prev == .... ==> (last => next)
*
* It's the 'much more previous' 'prev' that is on next's stack,
* but prev is set to (the just run) 'last' process by switch_to().
* This might sound slightly confusing but makes tons of sense.
*/
prepare_to_switch();
{
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if (!mm) {
if (next->active_mm) BUG();
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next, this_cpu);
} else {
if (next->active_mm != mm) BUG();
switch_mm(oldmm, mm, next, this_cpu);
}
if (!prev->mm) {
prev->active_mm = NULL;
mmdrop(oldmm);
}
}
/*
* This just switches the register state and the
* stack.
*/
switch_to(prev, next, prev);
__schedule_tail(prev);
same_process:
reacquire_kernel_lock(current);
if (current->need_resched)
goto need_resched_back;
#ifdef CONFIG_PREEMPT
ctx_sw_on_no_preempt();
#endif
return;
recalculate:
{
struct task_struct *p;
spin_unlock_irq(&runqueue_lock);
read_lock(&tasklist_lock);
for_each_task(p)
p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
read_unlock(&tasklist_lock);
spin_lock_irq(&runqueue_lock);
}
goto repeat_schedule;
still_running:
c = goodness(prev, this_cpu, prev->active_mm);
next = prev;
goto still_running_back;
handle_softirq:
do_softirq();
goto handle_softirq_back;
move_rr_last:
if (!prev->counter) {
prev->counter = NICE_TO_TICKS(prev->nice);
move_last_runqueue(prev);
}
goto move_rr_back;
scheduling_in_interrupt:
printk("Scheduling in interrupt\n");
BUG();
return;
}
void schedule_tail(struct task_struct *prev)
{
__schedule_tail(prev);
#ifdef CONFIG_PREEMPT
ctx_sw_on();
#endif
}


熱詞搜索:

上一篇:深度分析Windows2003自動升級補丁功能
下一篇:如何給類unix操作系統打補丁

分享到: 收藏
国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区
在线亚洲一区二区| 成人av免费在线播放| 日韩午夜av一区| 成人免费观看av| 日韩av午夜在线观看| 国产女主播一区| 欧美一区二区视频在线观看 | 国产一区二区三区蝌蚪| 亚洲欧美偷拍三级| 久久精品欧美一区二区三区麻豆| 欧美私人免费视频| 色综合欧美在线| 粉嫩一区二区三区性色av| 日本中文字幕不卡| 亚洲一区在线观看免费 | 精品粉嫩aⅴ一区二区三区四区 | 欧美主播一区二区三区美女| 国产成人自拍网| 日韩成人精品视频| 亚洲国产日产av| 亚洲摸摸操操av| 中文字幕一区二区三区四区 | 日韩精品一区二区三区四区| 在线免费观看日韩欧美| 成人免费视频网站在线观看| 精彩视频一区二区三区| 免费成人在线网站| 日本aⅴ精品一区二区三区| 亚洲mv大片欧洲mv大片精品| 亚洲欧美自拍偷拍| 中文字幕一区二区不卡 | 亚洲女子a中天字幕| 国产精品初高中害羞小美女文| 久久婷婷久久一区二区三区| 欧美精品一区二区三区视频| 精品国产亚洲在线| 精品久久久久一区| 2欧美一区二区三区在线观看视频| 日韩欧美资源站| 欧美一级理论片| 精品毛片乱码1区2区3区| 日韩欧美色电影| 久久影视一区二区| 久久久久久夜精品精品免费| 久久婷婷成人综合色| 国产精品网站一区| 国产精品国产三级国产| 国产欧美日韩另类一区| 国产精品免费视频网站| 国产精品理论片| 亚洲视频一二区| 亚洲一区二区精品3399| 天天射综合影视| 美国十次了思思久久精品导航| 久久精品噜噜噜成人88aⅴ| 老汉av免费一区二区三区| 国产一区二区三区四区五区美女| 国产一区二区三区高清播放| 成人午夜碰碰视频| 91色综合久久久久婷婷| 欧美性大战xxxxx久久久| 91精品国产手机| 2020国产精品| 中文字幕制服丝袜成人av | 亚洲国产激情av| 中文久久乱码一区二区| 一区二区三区91| 蜜臀av性久久久久av蜜臀妖精| 国产精品一级在线| jlzzjlzz欧美大全| 欧美高清视频不卡网| 久久综合久久综合久久综合| 国产精品久久久久久久久久免费看 | 亚洲欧洲日韩在线| 亚洲sss视频在线视频| 国产在线视视频有精品| 91影院在线免费观看| 欧美一区二区三区在| 中文字幕免费观看一区| 午夜成人免费电影| 成人激情免费网站| 9191成人精品久久| 中文字幕av一区二区三区高| 午夜欧美视频在线观看| 国产一区二区在线视频| 色噜噜狠狠色综合欧洲selulu| 91麻豆精品国产综合久久久久久| 国产色综合久久| 五月激情丁香一区二区三区| 国产成人综合视频| 91精品国产一区二区三区蜜臀| 国产精品久久久久久久久久久免费看 | 欧美精品一区二区三区四区| 亚洲人123区| 国产麻豆精品在线| 欧美日韩一卡二卡三卡 | 精品国产成人系列| 亚洲一区二区在线免费看| 国产sm精品调教视频网站| 欧美一二三区在线观看| 亚洲精品亚洲人成人网在线播放| 韩国v欧美v日本v亚洲v| 欧美在线观看视频一区二区三区| 国产欧美视频在线观看| 狠狠色综合色综合网络| 欧美乱妇15p| 一区二区三区日韩欧美精品| 丁香另类激情小说| 精品欧美久久久| 青青青伊人色综合久久| 欧洲精品在线观看| 国产精品成人免费| 国产91精品免费| 久久久精品日韩欧美| 蓝色福利精品导航| 日韩西西人体444www| 午夜欧美视频在线观看| 色综合色综合色综合| 国产精品三级在线观看| 国产自产高清不卡| 日韩午夜在线影院| 午夜成人免费电影| 欧美精品一卡两卡| 午夜精品在线看| 欧美视频三区在线播放| 亚洲乱码一区二区三区在线观看| 成人中文字幕在线| 国产精品色在线| 成人污视频在线观看| 国产亚洲va综合人人澡精品| 国产综合色在线视频区| 久久综合九色综合欧美98| 麻豆专区一区二区三区四区五区| 欧美另类高清zo欧美| 亚洲成人动漫在线免费观看| 欧美日韩国产欧美日美国产精品| 一区二区久久久| 欧美色视频在线观看| 午夜欧美视频在线观看| 欧美一区二区三区精品| 麻豆精品在线看| 久久亚洲一区二区三区明星换脸 | 六月丁香综合在线视频| 欧美一级日韩免费不卡| 蜜桃久久久久久| 日韩欧美一区中文| 黄色资源网久久资源365| 精品久久五月天| 东方欧美亚洲色图在线| 亚洲欧洲一区二区在线播放| 日本高清成人免费播放| 亚洲国产欧美另类丝袜| 欧美一区午夜视频在线观看| 麻豆精品国产传媒mv男同| 久久综合视频网| 国产福利精品一区二区| 亚洲色图.com| 欧美日韩大陆一区二区| 久久精品国产亚洲一区二区三区| 久久久久久久久97黄色工厂| 国产激情精品久久久第一区二区| 国产精品嫩草99a| 欧美日韩中文字幕一区| 精品一区二区三区在线播放| 中文一区一区三区高中清不卡| 一本在线高清不卡dvd| 日韩av电影免费观看高清完整版| 久久这里只有精品视频网| 99免费精品在线观看| 亚洲综合成人在线视频| 日韩欧美国产综合| 99久免费精品视频在线观看| 亚洲一区二区中文在线| 久久一日本道色综合| 91免费观看视频在线| 丝袜亚洲另类丝袜在线| 国产婷婷色一区二区三区| 在线视频一区二区三区| 激情综合色播激情啊| 日韩一区有码在线| 日韩午夜小视频| 99精品在线免费| 精品一区二区国语对白| 亚洲人成在线观看一区二区| 日韩色在线观看| 色综合久久天天| 麻豆91精品视频| 亚洲同性gay激情无套| 欧美tickling挠脚心丨vk| 色综合久久99| 国产高清久久久久| 日韩国产成人精品| 亚洲男帅同性gay1069| 久久理论电影网| 欧美人成免费网站| 99久久综合狠狠综合久久| 激情综合色综合久久| 亚洲第一福利一区| 中文字幕一区二区三区乱码在线 | 偷拍与自拍一区|