Linux Kernel Development — 設定當前進程的狀態

來源:互聯網
上載者:User
首先查看核心源碼中是如何定義的
#define __set_task_state(tsk, state_value) \ do { (tsk)->state = (state_value); } while (0) #define set_task_state(tsk, state_value) \ set_mb((tsk)->state, (state_value)) /* * set_current_state() includes a barrier so that the write of current->state * is correctly serialised wrt the caller's subsequent test of whether to * actually sleep: * * set_current_state(TASK_UNINTERRUPTIBLE); * if (do_i_need_to_sleep()) * schedule(); * * If the caller does not need such serialisation then use __set_current_state()*/ #define __set_current_state(state_value) \ do { current->state = (state_value); } while (0) #define set_current_state(state_value) \ set_mb(current->state, (state_value)) 

 

如果是單一處理器,則 set_mb 的定義為(asm-x86/system_32.h):

#define set_mb(var, value) do { var = value; barrier(); } while (0)

在對 current->state 複製後,簡單的用 barrier() 重新整理一下記憶體和寄存器之間的關係。

如果是多處理器 SMP,則 set_mb 的定義為:

#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)xchg(&var, value) 定義為(asm-x86/cmpxchg_32.h):#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))

上面,(__typeof__(*(ptr))) 獲得 *ptr 的類型,因為 *ptr 就是 var,而 var 的類型為 long 型,所以這裡也是對 __xchg() 返回的類型強制轉換為 long 型。

__xchg() 被定義為:

/** Note: no "lock" prefix even on SMP: xchg always implies lock anyway* Note 2: xchg has side effect, so that attribute volatile is necessary,* but generally the primitive is invalid, *ptr is output argument. --ANK*/static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size){switch (size) {case 1:__asm__ __volatile__("xchgb %b0,%1":"=q" (x):"m" (*__xg(ptr)), "0" (x):"memory");break;case 2:__asm__ __volatile__("xchgw %w0,%1":"=r" (x):"m" (*__xg(ptr)), "0" (x):"memory");break;case 4:__asm__ __volatile__("xchgl %0,%1":"=r" (x):"m" (*__xg(ptr)), "0" (x):"memory");break;}return x;}

上面,根據 __xchg 第 3 個表示長度的參數來使用 xchg 指令將要設定的新 state 的值交換到 current->state 中。

set_current_state()與set_task_state()

set_current_state(state)等價於set_task_state(current, state)

__set_current_state()與set_current_state()

set_task_state()帶有一個memory barrier,__set_task_state()則沒有,當狀態state是RUNNING時,因為scheduler可能訪問這個state,因 此此時要變成其他狀態(如INTERRUPTIBLE),就要用set_task_state();
而當state不是RUNNING時,因為沒有其他人會 訪問這個state,因此可以用__set_task_state().
所以用set_task_state()肯定是安全的,但 __set_task_state()可能會快些。

set_current_state() 的使用

在驅動程式中,進程睡眠往往通過 3 個步驟進行:
1. 將進程加入等待隊列中。
2. 然後使用 set_current_state() 來設定進程的狀態,設定的狀態為 TASK_INTERRUPTIBLE 或 TASK_UNINTERRUTIBLE 。
3. 上面的設定完後,我們就要放棄處理器了。但在放棄處理器之前,還有一件重要的事情需要做:檢查睡眠等待的條件。如果不檢查,如果此時條件正好變為真,那麼就漏掉了繼續啟動並執行機會,從而會睡眠更長的時間。

所以,一般在睡前需要類似的動作:

set_current_state(TASK_UNINTERRUPTIBLE);
if (do_i_need_to_sleep())
schedule();

參考:
http://blog.21ic.com/user1/6406/archives/2010/73685.html
http://www.groad.net/bbs/simple/?t3279.html
Linux Kernel Development

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.