{}

2010-09-22 16 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