Question

Bien que ce sujet a été discuté à plusieurs reprises dans ce forum et tous les autres forums, j'ai encore des doutes. S'il vous plaît aider.

Comment le do{} while(0) dans le travail macro dans le noyau Linux? Par exemple,

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

Comment désactiver il preempt?

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

Comment ça rééchelonner?

De même, je l'ai vu des macros pour des verrous et d'autres aussi. Comment cette aide? Je comprends pour le problème suivant, mais pas pour les exemples ci-dessus.

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

Modifier

Qu'en est-il le code suivant pour 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);
        }
}

Je suis confus parce rt_mutex_deadlock_account_lock est de définir à deux endroits dans le noyau:

En kernel/rtmutex-debug.c:

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

En kernel/rtmutex.h:

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

Dans le nouveau noyau 2.6.35.4 dans le pilote i2c rt_mutex_lock(&adap->bus_lock); a remplacé le mutex_lock(). Comment ce verrou alors fait?

Était-ce utile?

La solution

@Kragen a répondu à ce que le faire ... tout est construit pour -. Il est fondamentalement une macro beaucoup plus sûr à utiliser

Cependant, je ne pense pas qu'il répond à la question de « comment ça marche? »:

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

La macro est définie à ne rien faire . Pourquoi voudriez-vous de ne rien faire?

  • Dans certains cas, vous souhaitez utiliser une macro comme un espace réservé pour faire quelque chose. Par exemple, vous pouvez écrire un code sur un système où « préemptif » n'est pas un problème, mais vous connaissez le code peut être porté à un système où « préemptif » a besoin d'un traitement spécial. Donc, vous utilisez une macro partout le deuxième système a besoin (de sorte que la manipulation est facile à permettre plus tard), mais pour le premier système, vous définissez ensuite cette macro comme une macro vierge.

  • Dans certains cas, vous pouvez faire des choses comme une tâche qui est composée de différentes parties, (par exemple START_TABLE (); TABLE_ENTRY (1); TABLE_ENTRY (2); END_TABLE ();). Cela fait une belle mise en œuvre propre et claire de votre table. Mais vous trouvez que vous ne devez pas vraiment la macro END_TABLE (). Pour garder le bien rangé de code client, vous laissez la macro définie, et de définir simplement de ne rien faire. De cette façon, toutes vos tables ont un END_TABLE et le code est plus facile à lire.

  • Un cas similaire peut se produire avec deux états (activer / désactiver) où un état a besoin de la macro pour faire quelque chose, mais l'autre Etat se produit juste par défaut, la mise en œuvre est « vide » - vous encore utiliser la macro, car il est plus facile de comprendre le code client, parce qu'il énonce explicitement les lieux où les choses sont activées ou désactivées.

Autres conseils

Voir ce lien pour une meilleure explication que je pourrais donner.

IIRC l'utilisation du do-while dans les macros est de les rendre plus comme un appel de fonction normale; il y a quelques problèmes de syntaxe subtiles autour de déclarations et si non contreventées des choses comme ça. Sans le faire-tout l'aspect macro pourrait comme un appel de fonction normale, mais fonctionnerait différemment.

Je suppose que dans ce cas, ces macros sont utilisées de façon certains appels de fonctions compilent loin à rien; il semble que cela pourrait être ce que vous obtenez si CONFIG_PREEMPT n'a pas été défini, si certaines parties de simplement le noyau qui ne sont nécessaires que pour preempt disparaissent sans elle. Donc, ces boucles ne pas désactiver ou quoi que ce soit preempt Reschedule; il y aura une autre définition (probablement une fonction réelle) ailleurs dans la source du noyau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top