Un bloqueo primitivo que se usa ampliamente en el kernel de Linux es el bloqueo de actualización de lectura y copia (RCU). Es un mecanismo de sincronización que se agregó al Kernel de Linux en octubre de 2002. Ha logrado mejoras al permitir que las lecturas ocurran simultáneamente con las actualizaciones. Admite la concurrencia entre varios lectores y un único actualizador. No hay gastos generales en la primitiva del lado de lectura de la RCU. Es una de las estructuras de datos más seguras diseñada para operar de manera segura durante el acceso simultáneo porque utiliza la línea de caché y la memoria de manera eficiente.
Los bloqueos de actualización de lectura y copia (CPU) tienen una sección de lectura crítica sin bloqueo. Los bloqueos de RCU funcionan para cargas de trabajo en las que un escritor es compatible con los lectores sin bloqueo. La preferencia no está permitida en la sección crítica de lectura.
Considere el siguiente código:
struct Node { int key, val; /* pointer to the "next" and "prev"(previous) node */ struct Node *next, *prev; } /* Searches for a given key node in a list li and, returns the value corresponding to that key*/ int search(struct Node *li, int key) { int ret= -1; preempt_disable(); /* Disabling the preempt */ while(li!=NULL) { /* The required key is found */ if(li->key == key) { /* Assigning "ret" the value of that particular key */ ret = li->val; break; } /* moving on to the next list value */ li=li->next; } /* Enabling the interrupt which was disabled earlier */ preempt_enable(); /* Return the value of the key that is found */ return ret; } /* Deletes a given node */ void delete (struct Node *node) { /* Take a spin lock on the given node */ spin_lock(&lock); node->next->prev = node->prev; node->prev->next = node->next; /* Unlock the lock on the node, because the deletion has been done */ spin_unlock(&lock); free(node); }
En el código anterior, la actualización de eliminación de siguiente (es decir, Node->anterior->siguiente = Node->siguiente) es atómica, porque las operaciones de almacenamiento son atómicas. Si se ejecuta una eliminación al mismo tiempo, la rutina de búsqueda verá la lista nueva o la lista anterior, dependiendo de si la siguiente se actualiza o no. Además, la operación de eliminación puede ejecutarse simultáneamente con la operación de búsqueda porque las actualizaciones que importan para la búsqueda son la actualización del siguiente campo de un Node de lista enlazada.
En el esquema de actualización de lectura y copia, una operación libre se retrasa hasta que el actualizador está 100 % seguro de que los otros subprocesos no tienen una referencia al objeto que se va a eliminar. Dado que la prioridad no está permitida en la sección de lectura crítica, la invocación del cronograma de RCU sugiere que el núcleo en particular no está ejecutando una sección de lectura crítica.
En el esquema RCU, un escritor llama a rcu_free en lugar de free .rcu_free asegura que todos los lectores hayan salido al menos una vez de su sección crítica después de llamar a rcu_free. Esta verificación asegura que los otros subprocesos no tengan una referencia activa al objeto que se va a eliminar.
Esto se hace cuando rcu_free llama a wait_for_rcu , lo que fuerza un estado de reposo en cada núcleo.
Ventajas y desventajas:
los bloqueos de RCU no se pueden usar para una estructura de datos como Tree porque una búsqueda de Tree puede depender de múltiples actualizaciones que no se pueden realizar de forma atómica.
Una desventaja de los bloqueos de actualización de lectura y copia es que requiere la desactivación de la prioridad debido a que no se pueden usar en modo de usuario .