生活随笔
收集整理的這篇文章主要介紹了
禁止抢占
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
由于內核是搶占性的,內核中的進程在任何時刻都可能停下來以便另一個具有更高優先級的進程運行。這意味著一個任務與被搶占的任務可能會在同一個臨界區內運行。為了避免這樣的情況,內核搶占代碼使用自旋鎖作為非搶占區域的標記。如果一個自旋鎖被持有,內核便不能進行搶占。因為內核搶占和SMP面對相同的并發問題,并且內核已經是SMP安全的,因此,這種簡單的變化使得內核也是搶占安全的。
? 實際中,某些情況并不需要自旋鎖,但是仍然需要關閉內核搶占。出現得最頻繁的情況就是每個處理器上的數據。如果數據對每個處理器是唯一的,那么這樣的數據可能就不需要使用鎖來保護,因為數據只能被一個處理器訪問。如果自旋鎖沒有被持有,內核有是搶占式的,那么一個新調度的任務就可能訪問同一個變量。為了解決這個問題,可以通過preempt_disable()禁止內核搶占。這是一個可以嵌套調用的函數,可以調用任意次。每次調用都必須有一個相應的preempt_enable()調用。當最后一次preempt_enable()被調用后,內核搶占才重新啟用。
?
#ifdef?CONFIG_PREEMPTasmlinkage?void?preempt_schedule(void);#define?preempt_disable()?/do?{?/????inc_preempt_count();?/????barrier();?/}?while?(0)#define?preempt_enable_no_resched()?/do?{?/????barrier();?/????dec_preempt_count();?/}?while?(0)#define?preempt_check_resched()?/do?{?/????if?(unlikely(test_thread_flag(TIF_NEED_RESCHED)))?/????????preempt_schedule();?/}?while?(0)#define?preempt_enable()?/do?{?/????preempt_enable_no_resched();?/????barrier();?/????preempt_check_resched();?/}?while?(0)#else#define?preempt_disable()???????do?{?}?while?(0)#define?preempt_enable_no_resched()?do?{?}?while?(0)#define?preempt_enable()????????do?{?}?while?(0)#define?preempt_check_resched()?????do?{?}?while?(0)#endif
??搶占計數存放著被持有鎖的數量和preempt_disable()的調度次數,如果計數是0,那么內核可以進行搶占,如果為1或更大的值,那么內核就不會進行搶占。這個計數非常有用,它是一種對原子操作和睡眠很有效的調試方法。函數preempt_count()返回這個值。
#ifdef?CONFIG_DEBUG_PREEMPT??extern?void?fastcall?add_preempt_count(int?val);??extern?void?fastcall?sub_preempt_count(int?val);#else#?define?add_preempt_count(val)?do?{?preempt_count()?+=?(val);?}?while?(0)#?define?sub_preempt_count(val)?do?{?preempt_count()?-=?(val);?}?while?(0)#endif#define?inc_preempt_count()?add_preempt_count(1)#define?dec_preempt_count()?sub_preempt_count(1)#define?preempt_count()?(current_thread_info()->preempt_count)
在<Thread_info.h(include/asm-i386)>中struct?thread_info?{????struct?task_struct??*task;??????????struct?exec_domain??*exec_domain;???????unsigned?long???????flags;??????????unsigned?long???????status;?????????__u32???????????cpu;????????????int?????????preempt_count;??????mm_segment_t????????addr_limit;?????void????????????*sysenter_return;????struct?restart_block????restart_block;????unsigned?long???????????previous_esp;???????__u8????????????supervisor_stack[0];
總結
以上是生活随笔為你收集整理的禁止抢占的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。