c - how does do{} while(0) work in macro? -
though topic has been discussed many times in forum , other forums, still have doubts. please help.
how do{} while(0)
in macro work in linux kernel? example,
#define preempt_disable() { } while (0)
how disable preempt?
#define might_resched() { } while (0)
how reschedule?
similarly have seen macros mutex locks , other also. how help? understand following problem not examples above.
#define foo(x) { } while(0)
edit:
what following code rt_mutex_lock
?
/** * rt_mutex_lock - lock rt_mutex * * @lock: rt_mutex 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 * * atomic acquire/release ops compiled away, when either * architecture not support cmpxchg or when debugging 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); } }
i confused because rt_mutex_deadlock_account_lock
define @ 2 places in kernel:
in kernel/rtmutex-debug.c
:
void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task) { //.... }
in kernel/rtmutex.h
:
#define rt_mutex_deadlock_account_lock(m, t) { } while (0)
in new kernel 2.6.35.4 in i2c driver rt_mutex_lock(&adap->bus_lock);
has replaced mutex_lock()
. how lock then?
@kragen has answered do...while construct - makes macro safer use.
however, don't think answers question of "how work?":
#define preempt_disable() { } while (0)
the macro defined do nothing. why want nothing?
in cases want use macro placeholder doing something. example, might write code on 1 system "preempt" isn't issue, know code might ported system "preempt" needs special handling. use macro everywhere second system needs (so handling easy enable later), first system define macro blank macro.
in cases may want things task made of different parts, (e.g. start_table(); table_entry(1); table_entry(2); end_table();). makes nice clean clear implementation of table. find don't need end_table() macro. keep client code tidy, leave macro defined, , define nothing. way, tables have end_table , code easier read.
a similar case can occur 2 states (enable/disable) 1 state needs macro something, other state happens default, implementation of 1 "empty" - still use macro because makes client code easier understand, because explicitly states places things enabled or disabled.
Comments
Post a Comment