{}

2010-09-22 13 views
7

儘管在這個論壇和所有其他論壇上已經多次討論過這個話題,但我仍然有疑問。請幫忙。{}

宏在內核中的do{} while(0)如何工作? 例如,

#define preempt_disable() do { } while (0) 

它如何禁用搶佔?

#define might_resched() do { } while (0) 

它如何重新安排?

同樣我也看到了互斥鎖和其他宏的宏。這有什麼幫助?我理解以下問題,但不是上述示例。

#define foo(x) do { do something } while(0) 

編輯:

什麼爲rt_mutex_lock下面的代碼?

/** 
* rt_mutex_lock - lock a rt_mutex 
* 
* @lock: the rt_mutex to be locked 
*/ 
void __sched rt_mutex_lock(struct rt_mutex *lock) 
{ 
     might_sleep(); 
     rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock); 
} 
EXPORT_SYMBOL_GPL(rt_mutex_lock); 


/* 
* debug aware fast/slowpath lock,trylock,unlock 
* 
* The atomic acquire/release ops are compiled away, when either the 
* architecture does not support cmpxchg or when debugging is enabled. 
*/ 

static inline int rt_mutex_fastlock(struct rt_mutex *lock, 
    int state, int detect_deadlock, int (*slowfn)(struct rt_mutex *lock, 
    int state, struct hrtimer_sleeper *timeout, int detect_deadlock)) 
{ 
     if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { 
       rt_mutex_deadlock_account_lock(lock, current); 
       return 0; 
     } else{ 
       return slowfn(lock, state, NULL, detect_deadlock); 
     } 
} 

我很困惑,因爲rt_mutex_deadlock_account_lock是定義在內核兩個地方:

kernel/rtmutex-debug.c

void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, 
    struct task_struct *task) 
{ 
    //.... 
} 

kernel/rtmutex.h

#define rt_mutex_deadlock_account_lock(m, t) do { } while (0) 

在新內核2.6。 35.4在i2c司機rt_mutex_lock(&adap->bus_lock);公頃s取代了mutex_lock()。那麼這個鎖怎麼樣?

+0

在我看來就像它重新定義該函數什麼都不做。 – mpen 2010-09-22 06:34:51

+0

@ Mark:聽起來很有說服力。 ravspratapsingh:我們說得對,對於上面的兩個語句,大括號之間確實沒有什麼關係。或者你是否用這種方法簡化了代碼?的 – chiccodoro 2010-09-22 06:44:49

+0

可能重複[什麼用做的,而(0)當我們定義一個宏?(http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we- define-a-macro) – paxdiablo 2010-09-22 07:02:32

回答

5

@Kragen已經回答了什麼...雖然構造是 - 它基本上使宏使用更安全。

不過,我不認爲它回答了「如何工作的呢?」這樣的問題:

#define preempt_disable() do { } while (0) 

宏定義爲無能爲力。你爲什麼不想做什麼?

  • 在某些情況下,您希望使用宏作爲佔位符來做某些事情。例如,您可能在一個系統中編寫代碼,其中「搶佔」不是問題,但您知道代碼可能會移植到「搶佔」需要特殊處理的系統。因此,您在第二個系統需要的地方使用宏(以便稍後可以輕鬆啓用處理),但對於第一個系統,則將該宏定義爲空白宏。 (例如START_TABLE(); TABLE_ENTRY(1); TABLE_ENTRY(2); END_TABLE();)在某些情況下,您可能想要執行一些任務,例如由不同部分組成的任務。這使得你的表格非常乾淨清晰的實現。但是,你發現你實際上並不需要END_TABLE()宏。爲了保持客戶端代碼的整潔,您需要定義宏,並將其定義爲什麼都不做。這樣,所有的表都有一個END_TABLE,代碼更易於閱讀。

  • 類似的情況下,可以用兩種狀態(啓用/禁用),其中一個狀態需要宏做一些事情,但其他國家只是在默認情況下發生的,所以一個實行是「空」的出現 - 你還在用因爲它使得客戶端代碼更易於理解,因爲它明確指出了啓用或禁用事物的地方。

+0

。編譯器是否因此產生垃圾指令,或者循環是否會被優化? – Zingam 2016-01-21 11:00:45

+1

目前,編譯器擁有非常好的優化器,所以你很難找到一個浪費時間在這樣一個明顯空洞的案例上。 – 2016-01-21 22:01:00

11

請參閱this link以獲得比我更好的解釋。

+2

+1只是爲了彈出一個間接層,第一引文有回答的問題是:(從大衛米勒)空語句給從編譯器警告所以這就是爲什麼你看到'的#define FOO做{}而(0) '。 – 2010-09-22 07:41:54

3

IIRC在宏中使用do-while是爲了使它們看起來更像是一個正常的函數調用;圍繞無束縛的if語句以及類似的東西存在一些細微的語法問題。如果沒有這樣做 - 宏可能看起來像一個正常的函數調用,但工作方式不同。

我猜想在這種情況下,這些宏正在使用,所以某些函數調用編譯到沒有;如果沒有設置CONFIG_PREEMPT,它看起來可能是你所得到的,所以只有在搶佔時才需要內核的某些部分在沒有它的情況下就會消失。所以這些循環不會禁用搶佔或重新安排任何事情;在內核源碼的其他地方會有另一個定義(可能是一個真正的函數)。

+0

謝謝,我明白這個先發制人的事情是如何工作的,但仍然對互斥鎖感到困惑。請參閱我的關於rt_mutex_lock的回覆 – iSegFault 2010-09-22 06:55:53

+1

我假設互斥鎖是類似的東西 - 有一個「真實」的實現和一個「虛擬」的東西,它什麼都不做。大概在某些情況下,如果內核被配置爲不需要它,可以使用虛擬內核 - 也許如果CONFIG_SMP未啓用?如果'do {} while(0)'什麼都不做,則爲 – Peter 2010-09-23 21:46:31