La Compréhension Du Noyau Linux Tampon Circulaire

Il y a un article à: http://lwn.net/Articles/378262/ qui décrit les noyaux Linux tampon circulaire de mise en œuvre. J'ai quelques questions:

Ici est le "producteur":

spin_lock(&producer_lock);

unsigned long head = buffer->head;
unsigned long tail = ACCESS_ONCE(buffer->tail);

if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
    /* insert one item into the buffer */
    struct item *item = buffer[head];

    produce_item(item);

    smp_wmb(); /* commit the item before incrementing the head */

    buffer->head = (head + 1) & (buffer->size - 1);

    /* wake_up() will make sure that the head is committed before
     * waking anyone up */
    wake_up(consumer);
}

spin_unlock(&producer_lock);

Questions:

  1. Étant donné que ce code traite explicitement de la mémoire de la commande et de l'atomicité quel est le point de la spin_lock()?
  2. Pour l'instant, ma compréhension est que ACCESS_ONCE s'arrête compilateur réorganisation, vrai?
  3. Ne produce_item(item), il suffit de problème de toutes les écritures associées à l'élément?
  4. Je crois smp_wmb() garantit que toutes les écritures dans produce_item(item) complète AVANT de la "publication" d'écriture qui la suit. vrai?
  5. Le commentaire sur la page où j'ai eu ce code semble impliquer qu'un smp_wmb()
    normalement nécessaire après la mise à jour la tête de l'indice, mais wake_up(de consommation) est-ce que, donc, il n'est pas nécessaire. Est-ce vrai? Si oui, pourquoi?

Ici est le "consommateur":

spin_lock(&consumer_lock);

unsigned long head = ACCESS_ONCE(buffer->head);
unsigned long tail = buffer->tail;

if (CIRC_CNT(head, tail, buffer->size) >= 1) {
    /* read index before reading contents at that index */
    smp_read_barrier_depends();

    /* extract one item from the buffer */
    struct item *item = buffer[tail];

    consume_item(item);

    smp_mb(); /* finish reading descriptor before incrementing tail */

    buffer->tail = (tail + 1) & (buffer->size - 1);
}

spin_unlock(&consumer_lock);

Questions spécifiques à la "consommateurs":

  1. Ce n'smp_read_barrier_depends ()? À partir de quelques commentaires dans un forum, il semble que vous pourriez avoir émis un smp_rmb() ici, mais sur certaines architectures, c'est inutile (x86) et trop cher, donc smp_read_barrier_depends() a été créé pour ce faire éventuellement... cela dit, je ne comprends vraiment pas pourquoi smp_rmb() est toujours nécessaire!
  2. Est le smp_mb() afin de garantir que toutes les lectures avant de terminer avant de l'écrire après?

OriginalL'auteur dicroce | 2013-01-17