Domanda

Anche se questo argomento è stato discusso molte volte in questo forum e tutti gli altri forum, ancora ho dei dubbi. Si prega di aiuto.

Come funziona il do{} while(0) nel lavoro macro in kernel di Linux? Ad esempio,

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

Come disabilitare la preemption?

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

Come riscadenziamento?

macro Allo stesso modo ho visto per blocchi mutex ed altri anche. Come funziona questo aiuto? Capisco il seguente problema, ma non per gli esempi sopra riportati.

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

Modifica

E il seguente codice per 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);
        }
}

Sono confuso perché rt_mutex_deadlock_account_lock è definire in due punti nel 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) do { } while (0)

Nel nuovo kernel 2.6.35.4 nel rt_mutex_lock(&adap->bus_lock); conducente i2c ha sostituito il mutex_lock(). Come funziona questo blocco, allora?

È stato utile?

Soluzione

@Kragen ha risposto ciò che il fare ... mentre costrutto è per -. Si fa fondamentalmente una macro molto più sicuro di utilizzo

Tuttavia, non credo che risponde alla domanda di "come funziona?":

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

La macro viene definita per fare nulla . Perché si vuole fare nulla?

  • In alcuni casi si desidera utilizzare una macro come segnaposto per fare qualcosa. Ad esempio, è possibile scrivere il codice su un sistema in cui "preemption" non è un problema, ma si conosce il codice potrebbe essere portato su un sistema in cui "preemption" ha bisogno di un trattamento speciale. Quindi si utilizza una macro ovunque il secondo sistema ne ha bisogno (in modo che il trattamento è facile da attivare in seguito), ma per il primo sistema che si definisce poi che macro come macro vuota.

  • In alcuni casi si può decidere di fare le cose come un compito che si compone di diverse parti, (per esempio START_TABLE (); TABLE_ENTRY (1); TABLE_ENTRY (2); END_TABLE ();). Questo fa una bella chiara implementazione pulita della tabella. Ma poi si scopre che in realtà non è necessario la macro END_TABLE (). Per mantenere il codice del client ordinato, si lascia la macro definita, e semplicemente definire per fare nulla. In questo modo, tutte le tabelle hanno un END_TABLE e il codice è più facile da leggere.

  • Un caso simile si può verificare con due stati (abilitazione / disabilitazione) in cui uno stato ha bisogno la macro di fare qualcosa, ma l'altro stato appena capita di default, quindi l'attuazione di uno è "vuota" - ancora utilizzare la macro perché rende il codice del client più facile da capire, perché afferma esplicitamente i luoghi dove le cose sono attivate o disattivate.

Altri suggerimenti

questo link per una spiegazione migliore di quanto potessi dare.

IIRC l'uso del do-while nelle macro è per farli sembrare più simile a una normale funzione invocazione; ci sono alcuni problemi di sintassi sottili intorno unbraced se le dichiarazioni e cose del genere. Senza il do-while l'aspetto potrebbe macro come una normale funzione invocazione, ma potrebbe funzionare in modo diverso.

Direi che in questo caso le macro vengono utilizzate in modo determinate chiamate di funzione compilare via per nulla; sembra che potrebbe essere quello che si ottiene se CONFIG_PREEMPT non è stato impostato, in modo da alcune parti del kernel che sono necessari solo per la preemption semplicemente scompaiono senza di essa. Così quei cicli fanno la preemption non disabilitare o riprogrammare qualsiasi cosa; ci sarà un'altra definizione (probabilmente una funzione reale) in altre parti del codice sorgente del kernel.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top