4.5. Eliminando los bloqueos: Ordenamiento de Lecturas y Escrituras

Algunas veces es posible eliminar el bloqueo. Considera el siguiente caso del c�digo del cortafuegos 2.2, que inserta un elemento en una lista simplemente enlazada en el contexto de usuario:


        new->next = i->next;
        i->next = new;
    

Aqu� el autor (Alan Cox, que sab�a lo que estaba haciendo) asume que el asignamiento de punteros es at�mico. Esto es importante, porque los paquetes de red atravesar�an esta lista en bottom halves sin un bloqueo. Dependiendo del tiempo exacto, ellos ver�an el nuevo elemento en las lista con un puntero next v�lido, o no ver�an la lista todav�a. A�n se requiere un bloqueo contra otras CPUs insertando o borrando de la lista, por supuesto.

Por supuesto, las escrituras deben estar en este orden, en otro caso el nuevo elemento aparece en la lista con un puntero next inv�lido, y alguna otra CPU iterando en el tiempo equivocado saltar� a trav�s de �l a la basura. Porque las modernas CPUs reordenan, el c�digo de Alan actualmente se lee como sigue:


        new->next = i->next;
        wmb();
        i->next = new;

La funci�n wmb() es una barrera de escritura de memoria (include/asm/system.h): ni el compilador ni la CPU permitir�n alguna escritura a memoria despu�s de que wmb() sea visible a otro hardware antes de que alguna otra escritura se encuentre antes de wmb().

Como i386 no realiza reordenamiento de escritura, este bug nunca fue mostrada en esta plataforma. Es otras plataformas SMP, de cualquier forma, si que fue mostrado.

Tambi�n hay rmb() para ordenamiento de lectura: para asegurar que cualquier lectura previa de una variable ocurre antes de la siguiente lectura. La macro simple mb() combina rmb() y wmb().

Algunas operaciones at�micas est�n definidas para actuar como una barrera de memoria (esto es, como la macro mb(), pero si dudas, se expl�cito. Tambi�n, las operaciones de spinlock actuan como barreras parciales: las operaciones despu�s de obtener un spinlock nunca ser�n movidas para preceder a la llamada spin_lock(), y las operaciones antes de liberar un spinlock nunca ser�n movidas despu�s de la llamada spin_unlock().