preempt_count详解
生活随笔
收集整理的這篇文章主要介紹了
preempt_count详解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
當從內核態返回到用戶態的時候,要檢查是否進行調度,而調度要看兩個條件:
1.preempt_count是否為02.rescheduled是否置位ret_from_exception:
?preempt_stop(CLBR_ANY)
ret_from_intr:
?GET_THREAD_INFO(%ebp)
check_userspace:
?movl PT_EFLAGS(%esp), %eax?# mix EFLAGS and CS
?movb PT_CS(%esp), %al
?andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
?cmpl $USER_RPL, %eax
?jb resume_kernel??# not returning to v8086 or userspaceENTRY(resume_userspace)
?LOCKDEP_SYS_EXIT
??DISABLE_INTERRUPTS(CLBR_ANY)?# make sure we don't miss an interrupt
?????# setting need_resched or sigpending
?????# between sampling and the iret
?movl TI_flags(%ebp), %ecx
?andl $_TIF_WORK_MASK, %ecx?# is there any work to be done on
?????# int/exception return?
?jne work_pending
?jmp restore_all
END(ret_from_exception)#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
?DISABLE_INTERRUPTS(CLBR_ANY)
?cmpl $0,TI_preempt_count(%ebp)?# non-zero preempt_count ?
?jnz restore_nocheck
need_resched:
?movl TI_flags(%ebp), %ecx?# need_resched set ?
?testb $_TIF_NEED_RESCHED, %cl
?jz restore_all
?testl $IF_MASK,PT_EFLAGS(%esp)?# interrupts off (exception path) ?
?jz restore_all
?call preempt_schedule_irq
?jmp need_resched
END(resume_kernel)
#endif
?CFI_ENDPROC檢查preempt_count的時候,是統一檢查是否為0,也就是說,有4個條件限制,可能不能夠進行調度。1.preempt_disable()?#define preempt_disable() \
do { \
?inc_preempt_count(); \
?barrier(); \
} while (0)#define inc_preempt_count() add_preempt_count(1)會在preempt_enable中釋放2.add_preempt_count(HARDIRQ_OFFSET)是在irq_enter()中調用的,記錄進入硬件中斷處理的次數(計數),會在irq_exit()中釋放3.__local_bh_disable((unsigned long)__builtin_return_address(0));在do_softirq中調用的,static inline void __local_bh_disable(unsigned long ip)
{
?add_preempt_count(SOFTIRQ_OFFSET);
?barrier();
}4.總開關,第一位。
?preempt_stop(CLBR_ANY)
ret_from_intr:
?GET_THREAD_INFO(%ebp)
check_userspace:
?movl PT_EFLAGS(%esp), %eax?# mix EFLAGS and CS
?movb PT_CS(%esp), %al
?andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
?cmpl $USER_RPL, %eax
?jb resume_kernel??# not returning to v8086 or userspaceENTRY(resume_userspace)
?LOCKDEP_SYS_EXIT
??DISABLE_INTERRUPTS(CLBR_ANY)?# make sure we don't miss an interrupt
?????# setting need_resched or sigpending
?????# between sampling and the iret
?movl TI_flags(%ebp), %ecx
?andl $_TIF_WORK_MASK, %ecx?# is there any work to be done on
?????# int/exception return?
?jne work_pending
?jmp restore_all
END(ret_from_exception)#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
?DISABLE_INTERRUPTS(CLBR_ANY)
?cmpl $0,TI_preempt_count(%ebp)?# non-zero preempt_count ?
?jnz restore_nocheck
need_resched:
?movl TI_flags(%ebp), %ecx?# need_resched set ?
?testb $_TIF_NEED_RESCHED, %cl
?jz restore_all
?testl $IF_MASK,PT_EFLAGS(%esp)?# interrupts off (exception path) ?
?jz restore_all
?call preempt_schedule_irq
?jmp need_resched
END(resume_kernel)
#endif
?CFI_ENDPROC檢查preempt_count的時候,是統一檢查是否為0,也就是說,有4個條件限制,可能不能夠進行調度。1.preempt_disable()?#define preempt_disable() \
do { \
?inc_preempt_count(); \
?barrier(); \
} while (0)#define inc_preempt_count() add_preempt_count(1)會在preempt_enable中釋放2.add_preempt_count(HARDIRQ_OFFSET)是在irq_enter()中調用的,記錄進入硬件中斷處理的次數(計數),會在irq_exit()中釋放3.__local_bh_disable((unsigned long)__builtin_return_address(0));在do_softirq中調用的,static inline void __local_bh_disable(unsigned long ip)
{
?add_preempt_count(SOFTIRQ_OFFSET);
?barrier();
}4.總開關,第一位。
總結
以上是生活随笔為你收集整理的preempt_count详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 禁止抢占
- 下一篇: 单列模式(懒汉)测试代码