Articulo de referencia

Leer-copiar-actualizar

En informática , el mecanismo de lectura-copia-actualización ( RCU ) es un mecanismo de sincronización que evita el uso de primitivas de bloqueo mientras múltiples hilos leen y ...

En informática , el mecanismo de lectura-copia-actualización ( RCU ) es un mecanismo de sincronización que evita el uso de primitivas de bloqueo mientras múltiples hilos leen y actualizan concurrentemente elementos que están vinculados a través de punteros y que pertenecen a estructuras de datos compartidas (por ejemplo, listas enlazadas , árboles , tablas hash ). [ 1 ]

Siempre que un hilo inserta o elimina elementos de estructuras de datos en memoria compartida , se garantiza que todos los lectores vean y recorran la estructura antigua o la nueva, evitando así inconsistencias (por ejemplo, la desreferenciación de punteros nulos ). [ 1 ]

Se utiliza cuando el rendimiento de las lecturas es crucial y es un ejemplo de compensación espacio-tiempo , que permite operaciones rápidas a costa de un mayor consumo de espacio. Esto hace que todos los lectores procesen como si no hubiera sincronización , por lo que serán rápidos, pero también dificulta las actualizaciones.

Nombre y descripción general

El nombre proviene de la forma en que se utiliza RCU para actualizar una estructura vinculada in situ. Un hilo que desee realizar esta operación sigue los siguientes pasos:

  • crear una nueva estructura,
  • copiar los datos de la estructura antigua a la nueva y guardar un puntero a la estructura antigua,
  • modificar la nueva estructura copiada,
  • actualizar el puntero global para que haga referencia a la nueva estructura,
  • dormir hasta que el núcleo del sistema operativo determine que no quedan lectores que utilicen la estructura antigua, por ejemplo, en el núcleo de Linux, mediante el uso de synchronize_rcu() ,
  • Una vez activado por el núcleo, se libera la estructura antigua.

Así, la estructura se lee simultáneamente con una copia de hilo para realizar una actualización , de ahí el nombre "actualización de lectura y copia". La abreviatura "RCU" fue una de las muchas contribuciones de la comunidad Linux. Otros nombres para técnicas similares incluyen serialización pasiva y MP defer por programadores de VM/XA , y generaciones por programadores de K42 y Tornado .

Descripción detallada

Procedimiento de inserción de lectura, copia y actualización. Un hilo asigna una estructura con tres campos y luego establece el puntero global gptr para que apunte a esta estructura.

Una propiedad clave de RCU es que los lectores pueden acceder a una estructura de datos incluso cuando se está actualizando: los actualizadores de RCU no pueden bloquear a los lectores ni obligarlos a reintentar el acceso. Esta descripción general comienza mostrando cómo se pueden insertar y eliminar datos de forma segura en estructuras vinculadas a pesar de la presencia de lectores concurrentes. El primer diagrama de la derecha muestra un procedimiento de inserción de cuatro estados, con el tiempo avanzando de izquierda a derecha.

El primer estado muestra un puntero global llamado gptr que inicialmente es NULL , coloreado en rojo para indicar que un lector podría acceder a él en cualquier momento, por lo que los actualizadores deben tener cuidado. La asignación de memoria para una nueva estructura da paso al segundo estado. Esta estructura tiene un estado indeterminado (indicado por los signos de interrogación) pero es inaccesible para los lectores (indicado por el color verde). Debido a que la estructura es inaccesible para los lectores, el actualizador puede realizar cualquier operación deseada sin temor a interrumpir a los lectores concurrentes. La inicialización de esta nueva estructura da paso al tercer estado, que muestra los valores inicializados de los campos de la estructura. La asignación de una referencia a esta nueva estructura a gptr da paso al cuarto y último estado. En este estado, la estructura es accesible para los lectores y, por lo tanto, está coloreada en rojo. La primitiva rcu_assign_pointer se utiliza para realizar esta asignación y garantiza que la asignación sea atómica en el sentido de que los lectores concurrentes verán un puntero NULL o un puntero válido a la nueva estructura, pero no una combinación de ambos valores. En este artículo se describen propiedades adicionales de rcu_assign_pointer .

procedimiento de eliminación de lectura, copia y actualización

Este procedimiento demuestra cómo se pueden insertar nuevos datos en una estructura de datos enlazada, incluso cuando los lectores la recorren simultáneamente antes, durante y después de la inserción. El segundo diagrama de la derecha muestra un procedimiento de eliminación de cuatro estados, donde el tiempo avanza de izquierda a derecha.

El primer estado muestra una lista enlazada que contiene los elementos A , B y C. Los tres elementos están coloreados de rojo para indicar que un lector RCU puede hacer referencia a cualquiera de ellos en cualquier momento. Usar list_del_rcu para eliminar el elemento B de esta lista da paso al segundo estado. Nótese que el enlace del elemento B al elemento C permanece intacto para permitir que los lectores que actualmente hacen referencia al elemento B recorran el resto de la lista. Los lectores que accedan al enlace desde el elemento A obtendrán una referencia al elemento B o al elemento C , pero en cualquier caso, cada lector verá una lista enlazada válida y con el formato correcto. El elemento B ahora está coloreado de amarillo para indicar que, si bien los lectores preexistentes aún pueden tener una referencia al elemento B , los nuevos lectores no tienen forma de obtener una referencia. Una operación wait-for-readers da paso al tercer estado. Nótese que esta operación wait-for-readers solo necesita esperar a los lectores preexistentes, no a los nuevos. El elemento B ahora está coloreado de verde para indicar que los lectores ya no pueden hacer referencia a él. Por lo tanto, ahora es seguro que el actualizador libere el elemento B , pasando así al cuarto y último estado.

Es importante reiterar que, en el segundo estado, distintos lectores pueden ver dos versiones diferentes de la lista: con o sin el elemento B. En otras palabras, RCU proporciona coordinación tanto espacial (diferentes versiones de la lista) como temporal (diferentes estados en los procedimientos de eliminación). Esto contrasta notablemente con las primitivas de sincronización más tradicionales, como el bloqueo o las transacciones , que coordinan en el tiempo, pero no en el espacio.

Este procedimiento demuestra cómo se pueden eliminar datos antiguos de una estructura de datos enlazada, incluso cuando los lectores la recorren simultáneamente antes, durante y después de la eliminación. Mediante RCU, se puede implementar una amplia variedad de estructuras de datos, incluyendo inserciones y eliminaciones.

Los lectores de RCU se ejecutan dentro de secciones críticas de lectura , que normalmente están delimitadas por `rcu_read_lock` y `rcu_read_unlock` . Cualquier instrucción que no esté dentro de una sección crítica de lectura de RCU se considera en estado de reposo , y dichas instrucciones no pueden contener referencias a estructuras de datos protegidas por RCU, ni la operación `wait-for-readers` está obligada a esperar a los hilos en estado de reposo. Cualquier período de tiempo durante el cual cada hilo reside al menos una vez en estado de reposo se denomina período de gracia . Por definición, cualquier sección crítica de lectura de RCU existente al comienzo de un período de gracia determinado debe completarse antes del final de dicho período, lo que constituye la garantía fundamental que proporciona RCU. Además, la operación `wait-for-readers` debe esperar a que transcurra al menos un período de gracia. Resulta que esta garantía puede proporcionarse con sobrecargas de lectura extremadamente pequeñas; de hecho, en el caso límite que se implementa en las compilaciones del kernel de Linux de clase servidor, la sobrecarga de lectura es exactamente cero. [ 2 ]

La garantía fundamental de RCU se puede utilizar dividiendo las actualizaciones en fases de eliminación y recuperación . La fase de eliminación elimina las referencias a los elementos de datos dentro de una estructura de datos (posiblemente reemplazándolas con referencias a nuevas versiones de estos elementos de datos) y puede ejecutarse simultáneamente con las secciones críticas de lectura de RCU. La razón por la que es seguro ejecutar la fase de eliminación simultáneamente con los lectores de RCU es que la semántica de las CPU modernas garantiza que los lectores verán la versión antigua o la nueva de la estructura de datos, en lugar de una referencia parcialmente actualizada. Una vez transcurrido un período de gracia, ya no puede haber lectores que hagan referencia a la versión antigua, por lo que es seguro que la fase de recuperación libere ( recupere ) los elementos de datos que componían esa versión antigua. [ 3 ]

Dividir una actualización en fases de eliminación y recuperación permite al actualizador realizar la fase de eliminación de inmediato y aplazar la fase de recuperación hasta que todos los lectores activos durante la fase de eliminación hayan finalizado, es decir, hasta que haya transcurrido un período de gracia. [ nota 1 ]

Entonces, la secuencia típica de actualización de RCU es algo así como lo siguiente: [ 4 ]

  1. Asegúrese de que todos los lectores que accedan a estructuras de datos protegidas por RCU realicen sus referencias desde dentro de una sección crítica de lectura de RCU.
  2. Elimine los punteros a una estructura de datos, de modo que los lectores posteriores no puedan obtener una referencia a ella.
  3. Espere a que transcurra un período de gracia para que todos los lectores anteriores (que podrían tener punteros a la estructura de datos eliminados en el paso anterior) hayan completado sus secciones críticas de lectura de RCU.
  4. En este punto, no puede haber lectores que aún conserven referencias a la estructura de datos, por lo que ahora se puede recuperar de forma segura (por ejemplo, liberarla). [ nota 2 ]

En el procedimiento anterior (que coincide con el diagrama previo), el actualizador realiza tanto la eliminación como la recuperación, pero suele ser útil que un hilo completamente diferente realice la recuperación. Se puede utilizar el conteo de referencias para que el lector realice la eliminación, por lo que, incluso si el mismo hilo realiza tanto la actualización (paso (2) anterior) como la recuperación (paso (4) anterior), suele ser útil considerarlas por separado.

RCU es quizás el algoritmo no bloqueante más común para una estructura de datos compartida. RCU no requiere esperas para ningún número de lectores. Las implementaciones de RCU con un solo escritor tampoco requieren bloqueo para el escritor. [ 5 ] Algunas implementaciones de RCU con múltiples escritores no requieren bloqueo. [ 6 ] Otras implementaciones de RCU con múltiples escritores serializan a los escritores con un bloqueo. [ 7 ]

Usos

A principios de 2008, había casi 2000 usos de la API RCU dentro del kernel de Linux [ 8 ], incluyendo las pilas de protocolos de red [ 9 ] y el sistema de gestión de memoria. [ 10 ] A marzo de 2014 , hubo más de 9000 usos. [ 11 ] Desde 2006, los investigadores han aplicado RCU y técnicas similares a una serie de problemas, incluyendo la gestión de metadatos utilizados en análisis dinámico, [ 12 ] la gestión del ciclo de vida de objetos agrupados, [ 13 ] la gestión del ciclo de vida de objetos en el sistema operativo de investigación K42 , [ 14 ] [ 15 ] y la optimización de implementaciones de memoria transaccional de software . [ 16 ] [ 17 ] Dragonfly BSD utiliza una técnica similar a RCU que se asemeja más a la implementación Sleepable RCU (SRCU) de Linux.

Ventajas y desventajas

La capacidad de esperar hasta que todos los lectores hayan terminado permite a los lectores RCU usar una sincronización mucho más ligera ; en algunos casos, ninguna sincronización en absoluto. En los esquemas más convencionales basados ​​en bloqueos, los lectores deben usar una sincronización pesada para evitar que un actualizador elimine la estructura de datos sin que se den cuenta. La razón es que los actualizadores basados ​​en bloqueos suelen actualizar los datos en el mismo lugar y, por lo tanto, deben excluir a los lectores. En cambio, los actualizadores basados ​​en RCU suelen aprovechar el hecho de que las escrituras en punteros alineados simples son atómicas en las CPU modernas, lo que permite la inserción, eliminación y reemplazo atómicos de datos en una estructura enlazada sin interrumpir a los lectores. Los lectores RCU concurrentes pueden entonces seguir accediendo a las versiones antiguas y pueden prescindir de las instrucciones atómicas de lectura-modificación-escritura, las barreras de memoria y los fallos de caché que son tan costosos en los sistemas informáticos SMP modernos, incluso en ausencia de contención de bloqueos. [ 18 ] [ 19 ] La naturaleza ligera de las primitivas del lado de lectura de RCU proporciona ventajas adicionales más allá del excelente rendimiento, la escalabilidad y la respuesta en tiempo real. Por ejemplo, proporcionan inmunidad a la mayoría de las condiciones de interbloqueo y bloqueo mutuo . [ nota 3 ]

RCU es una técnica especializada que funciona mejor en situaciones con predominio de lecturas y pocas actualizaciones, pero suele ser menos aplicable a cargas de trabajo que solo implican actualizaciones. Si bien la capacidad de los lectores y actualizadores de RCU para ejecutarse simultáneamente es lo que permite la ligereza de las primitivas de lectura de RCU, algunos algoritmos pueden no ser compatibles con la concurrencia de lectura/actualización.

La aplicabilidad de RCU es objeto de investigación continua.

Patentes

La técnica está cubierta por la patente de software estadounidense 5,442,758 , emitida el 15 de agosto de 1995 y asignada a Sequent Computer Systems , así como por las patentes estadounidenses 5,608,893 (expirada el 30 de marzo de 2009), 5,727,209 (expirada el 5 de abril de 2010), 6,219,690 (expirada el 18 de mayo de 2009) y 6,886,162 (expirada el 25 de mayo de 2009). La patente estadounidense 4,809,168, ahora expirada, cubre una técnica estrechamente relacionada. RCU también es objeto de una reivindicación en la demanda SCO contra IBM .

Interfaz RCU de ejemplo

RCU está disponible en varios sistemas operativos y se añadió al núcleo de Linux en octubre de 2002. También existen implementaciones a nivel de usuario, como liburcu . [ 20 ]

La implementación de RCU en la versión 2.6 del kernel de Linux se encuentra entre las implementaciones de RCU más conocidas y se utilizará como inspiración para la API de RCU en el resto de este artículo. La API principal ( Interfaz de Programación de Aplicaciones ) es bastante pequeña: [ 21 ]

  • rcu_read_lock(): Marca una estructura de datos protegida por RCU para que no se pueda recuperar durante toda la duración de esa sección crítica.
  • rcu_read_unlock(): Utilizada por un lector para informar al recuperador de que el lector está saliendo de una sección crítica de lectura de RCU. Tenga en cuenta que las secciones críticas de lectura de RCU pueden estar anidadas o superpuestas.
  • synchronize_rcu(): Se bloquea hasta que se hayan completado todas las secciones críticas de lectura de RCU preexistentes en todas las CPU. Tenga en cuenta que nosynchronize_rcu necesariamente esperará a que se completen las secciones críticas de lectura de RCU subsiguientes. Por ejemplo, considere la siguiente secuencia de eventos:
 CPU 0 CPU 1 CPU 2 ----------------- ------------------------- --------------- 1. rcu_read_lock() 2. entra en synchronize_rcu() 3. rcu_read_lock() 4. rcu_read_unlock() 5. sale synchronize_rcu() 6. rcu_read_unlock() 
Dado que synchronize_rcues la API la que debe determinar cuándo los lectores han terminado, su implementación es clave para RCU. Para que RCU sea útil en todas las situaciones, excepto en las que se requiere mayor cantidad de lecturas, synchronize_rcula sobrecarga de también debe ser bastante pequeña.
Como alternativa, en lugar de bloquearse, synchronize_rcu puede registrar una función de devolución de llamada que se invocará una vez que se hayan completado todas las secciones críticas de lectura de RCU en curso. Esta variante de la función de devolución de llamada se invoca call_rcuen el kernel de Linux.
  • rcu_assign_pointer(): El actualizador utiliza esta función para asignar un nuevo valor a un puntero protegido por RCU, con el fin de comunicar de forma segura el cambio de valor desde el actualizador al lector. Esta función devuelve el nuevo valor y también ejecuta las instrucciones de barrera de memoria necesarias para la arquitectura de CPU correspondiente. Quizás aún más importante, sirve para documentar qué punteros están protegidos por RCU.
  • rcu_dereference(): El lector se utiliza rcu_dereferencepara obtener un puntero protegido por RCU, que devuelve un valor que luego puede desreferenciarse de forma segura. También ejecuta cualquier directiva requerida por el compilador o la CPU, por ejemplo, una conversión volátil para gcc, una carga memory_order_consume para C/C++11 o la instrucción memory-barrier requerida por la antigua CPU DEC Alpha. El valor devuelto por rcu_dereferencees válido solo dentro de la sección crítica de lectura RCU que lo contiene. Al igual que con rcu_assign_pointer, una función importante de rcu_dereferencees documentar qué punteros están protegidos por RCU.
Comunicaciones API de RCU entre el lector, el actualizador y el recuperador.

El diagrama de la derecha muestra cómo se comunica cada API entre el lector, el actualizador y el recuperador.

La infraestructura RCU observa la secuencia temporal de rcu_read_locklas rcu_read_unlockinvocaciones para determinar cuándo (1) las invocaciones pueden regresar a sus llamadores y (2) se pueden invocar las devoluciones synchronize_rcude llamada. Las implementaciones eficientes de la infraestructura RCU hacen un uso intensivo del procesamiento por lotes para amortizar su sobrecarga en muchos usos de las API correspondientes.call_rcusynchronize_rcucall_rcu

Implementación sencilla

RCU cuenta con implementaciones de ejemplo extremadamente sencillas que pueden facilitar su comprensión. Esta sección presenta una de estas implementaciones de ejemplo que funciona en un entorno no preferente . [ 22 ]

void rcu_read_lock ( void ) { }void rcu_read_unlock ( void ) { }void call_rcu ( void ( * callback ) ( void * ), void * arg ) { // agregar par callback/arg a una lista }void synchronize_rcu ( void ) { int cpu , ncpus = 0 ;para cada_cpu ( cpu ) programar_tarea_actual_en ( cpu );para cada entrada en la lista call_rcu entrada -> devolución de llamada ( entrada -> arg ); }

En el código de ejemplo, rcu_assign_pointerse rcu_dereferencepueden ignorar sin que se pierda mucho. Sin embargo, son necesarios para suprimir la optimización perjudicial del compilador y evitar que las CPU reordenen los accesos.

#define rcu_assign_pointer(p, v) ({ \  smp_wmb(); /* Ordenar las escrituras anteriores. */ \  ACCESS_ONCE(p) = (v); \ })#define rcu_dereference(p) ({ \  typeof(p) _value = ACCESS_ONCE(p); \  smp_read_barrier_depends(); /* nop en la mayoría de las arquitecturas */ \  (_value); \ })

Tenga en cuenta que rcu_read_locky rcu_read_unlockno haga nada. Esta es la fuerza de RCU clásico en un kernel no preemptivo: la sobrecarga del lado de lectura es precisamente cero, al igual que smp_read_barrier_depends()una macro vacía en todas las CPU excepto DEC Alpha ; [ 23 ] tales barreras de memoria no son necesarias en las CPU modernas. La macro es una conversión volátil que no genera código adicional en la mayoría de los casos. Y no hay forma de que pueda participar en un ciclo de interbloqueo , hacer que un proceso en tiempo real pierda su fecha límite de planificación, precipitar la inversión de prioridad o resultar en una alta contención de bloqueo . Sin embargo, en esta implementación de juguete de RCU, bloquear dentro de una sección crítica del lado de lectura de RCU es ilegal, al igual que bloquear mientras se mantiene un spinlock puro.ACCESS_ONCE()rcu_read_lock

La implementación synchronize_rcutraslada la llamada a synchronize_cpu a cada CPU, bloqueando así la ejecución hasta que todas las CPU hayan podido realizar el cambio de contexto. Cabe recordar que se trata de un entorno no preemptivo y que el bloqueo dentro de una sección crítica de lectura de RCU es ilegal, lo que implica que no puede haber puntos de preempción dentro de una sección crítica de lectura de RCU. Por lo tanto, si una CPU determinada ejecuta un cambio de contexto (para programar otro proceso), sabemos que esta CPU debe haber completado todas las secciones críticas de lectura de RCU anteriores. Una vez que todas las CPU hayan ejecutado un cambio de contexto, todas las secciones críticas de lectura de RCU anteriores habrán finalizado.

Analogía con el bloqueo lector-escritor

Aunque RCU puede utilizarse de muchas maneras diferentes, un uso muy común de RCU es análogo al bloqueo de lectura/escritura. La siguiente comparación de código muestra la estrecha relación entre el bloqueo de lectura/escritura y RCU. [ 24 ]

/* Bloqueo de lector-escritura */ /* RCU */1 struct el { 1 struct el { 2 struct list_head lp ; 2 struct list_head lp ; 3 long key ; 3 long key ; 4 spinlock_t mutex ; 4 spinlock_t mutex ; 5 int data ; 5 int data ; 6 /* Otros campos de datos */ 6 /* Otros campos de datos */ 7 }; 7 }; 8 DEFINE_RWLOCK ( listmutex ); 8 DEFINE_SPINLOCK ( listmutex ); 9 LIST_HEAD ( head ); 9 LIST_HEAD ( head );1 int search ( long key , int * result ) 1 int search ( long key , int * result ) 2 { 2 { 3 struct el * p ; 3 struct el * p ; 4 4 5 read_lock ( & listmutex ); 5 rcu_read_lock (); 6 list_for_each_entry ( p , & head , lp ) { 6 list_for_each_entry_rcu ( p , & head , lp ) { 7 if ( p -> key == key ) { 7 if ( p -> key == key ) { 8 * result = p -> data ; 8 * result = p -> data ; 9 read_unlock ( & listmutex ); 9 rcu_read_unlock (); 10 return 1 ; 10 return 1 ; 11 } 11 } 12 } 12 } 13 read_unlock ( & listmutex ); 13 rcu_read_unlock (); 14 return 0 ; 14 return 0 ; 15 } 15 }1 int delete ( long key ) 1 int delete ( long key ) 2 { 2 { 3 struct el * p ; 3 struct el * p ; 4 4 5 write_lock ( & listmutex ); 5 spin_lock ( & listmutex ); 6 list_for_each_entry ( p , & head , lp ) { 6 list_for_each_entry ( p , & head , lp ) { 7 if ( p -> key == key ) { 7 if ( p -> key == key ) { 8 list_del ( & p -> lp ); 8 list_del_rcu ( & p -> lp ); 9 write_unlock ( & listmutex ); 9 spin_unlock ( & listmutex ); 10 synchronize_rcu (); 10 kfree ( p ); 11 kfree ( p ); 11 return 1 ; 12 return 1 ; 12 } 13 } 13 } 14 } 14 write_unlock ( & listmutex ); 15 spin_unlock ( & listmutex ); 15 return 0 ; 16 return 0 ; 16 } 17 }

Las diferencias entre los dos enfoques son bastante pequeñas. El bloqueo del lado de lectura se mueve a rcu_read_locky rcu_read_unlock, el bloqueo del lado de actualización se mueve de un bloqueo de lector-escritor a un simple spinlock, y un synchronize_rcuprecede al kfree.

Sin embargo, existe un posible inconveniente: las secciones críticas de lectura y actualización ahora pueden ejecutarse simultáneamente. En muchos casos, esto no supondrá un problema, pero es necesario revisarlo con detenimiento. Por ejemplo, si varias actualizaciones de lista independientes deben considerarse como una única actualización atómica, la conversión a RCU requerirá especial atención.

Además, la presencia de synchronize_rcusignifica que la versión RCU de deleteahora puede bloquear. Si esto es un problema, call_rcupodría usarse como call_rcu (kfree, p)en lugar de synchronize_rcu. Esto es especialmente útil en combinación con el conteo de referencias.

Historia

Se han inventado de forma independiente varias veces técnicas y mecanismos similares a RCU: [ 25 ]

  1. HT Kung y Q. Lehman describieron el uso de recolectores de basura para implementar un acceso similar a RCU a un árbol de búsqueda binaria. [ 26 ]
  2. Udi Manber y Richard Ladner extendieron el trabajo de Kung y Lehman a entornos sin recolección de basura al aplazar la recuperación hasta que todos los hilos que se ejecutan en el momento de la eliminación hayan terminado, lo que funciona en entornos que no tienen hilos de larga duración. [ 27 ]
  3. Richard Rashid et al. describieron una implementación de búfer de traducción anticipada (TLB) diferida que posponía la recuperación del espacio de direcciones virtuales hasta que todas las CPU vaciaran su TLB, lo cual es similar en espíritu a algunas implementaciones de RCU. [ 28 ]
  4. James P. Hennessy, Damian L. Osisek y Joseph W. Seigh, II obtuvieron la patente estadounidense 4,809,168 en 1989 (actualmente caducada). Esta patente describe un mecanismo similar a RCU que aparentemente se utilizaba en VM/XA en mainframes de IBM . [ 29 ]
  5. William Pugh describió un mecanismo similar a RCU que dependía del establecimiento explícito de indicadores por parte de los lectores. [ 30 ]
  6. Aju John propuso una implementación tipo RCU donde los actualizadores simplemente esperan un período de tiempo fijo, bajo el supuesto de que todos los lectores completarían dentro de ese tiempo fijo, como podría ser apropiado en un sistema de tiempo real estricto. [ 31 ] Van Jacobson propuso un esquema similar en 1993 (comunicación verbal).
  7. J. Slingwine y P.E. McKenney recibieron la patente estadounidense 5,442,758 en agosto de 1995, que describe RCU tal como se implementó en DYNIX/ptx y posteriormente en el núcleo de Linux. [ 32 ]
  8. B. Gamsa, O. Krieger, J. Appavoo y M. Stumm describieron un mecanismo similar a RCU utilizado en el sistema operativo de investigación Tornado de la Universidad de Toronto y en los sistemas operativos de investigación K42 de IBM Research, estrechamente relacionados. [ 33 ]
  9. Rusty Russell y Phil Rumpf describieron técnicas similares a RCU para manejar la descarga de módulos del kernel de Linux. [ 34 ] [ 35 ]
  10. D. Sarma añadió RCU a la versión 2.5.43 del kernel de Linux en octubre de 2002.
  11. Robert Colvin et al. verificaron formalmente un algoritmo de conjunto basado en listas concurrente perezoso que se asemeja a RCU. [ 36 ]
  12. M. Desnoyers et al. publicaron una descripción de RCU en el espacio del usuario. [ 37 ] [ 38 ]
  13. A. Gotsman et al. derivaron una semántica formal para RCU basada en la lógica de separación. [ 39 ]
  14. Ilan Frenkel, Roman Geller, Yoram Ramberg y Yoram Snir obtuvieron la patente estadounidense 7,099,932 en 2006. Esta patente describe un mecanismo similar a RCU para recuperar y almacenar información de gestión de políticas de calidad de servicio utilizando un servicio de directorio de manera que se garantice la coherencia de lectura/escritura y se permita la concurrencia de lectura/escritura. [ 40 ]

Véase también

Notas

  1. Solo se deben considerar los lectores que estén activos durante la fase de eliminación, ya que cualquier lector que comience después de la fase de eliminación no podrá obtener una referencia a los elementos de datos eliminados y, por lo tanto, no puede verse afectado por la fase de recuperación.
  2. Los recolectores de basura , cuando estén disponibles, pueden utilizarse para realizar este paso.
  3. Los interbloqueos basados ​​en RCU aún son posibles, por ejemplo, al ejecutar una instrucción que se bloquea hasta que finaliza un período de gracia dentro de una sección crítica de lectura de RCU.

Referencias

  1. ^ Tanenbaum , Andrés (2015). Sistemas operativos modernos (4ª  ed.). Estados Unidos: Pearson. pag.  148.ISBN 9781292061429.
  2. Guniguntala, Dinakar; McKenney, Paul E.; Triplett, Joshua; Walpole, Jonathan (abril-junio de 2008). "El mecanismo de lectura-copia-actualización para admitir aplicaciones en tiempo real en sistemas multiprocesador de memoria compartida con Linux". IBM Systems Journal . 47 (2): 221– 236. doi : 10.1147/sj.472.0221 .
  3. McKenney, Paul E.; Walpole, Jonathan (17 de diciembre de 2007). "¿Qué es RCU, fundamentalmente?" . Linux Weekly News . Consultado el 24 de septiembre de 2010 .
  4. McKenney, Paul E.; Slingwine, John D. (octubre de 1998). Actualización de lectura y copia: uso del historial de ejecución para resolver problemas de concurrencia (PDF) . Computación y sistemas paralelos y distribuidos . págs. 509–518 . 
  5. Naama Ben-David; Guy E. Blelloch; Yihan Sun; Yuanhao Wei. "Concurrencia eficiente de un solo escritor" .
  6. "Multiprocesamiento sin bloqueo con operaciones atómicas" .
  7. Eddie Kohler. "Notas sobre la actualización de lectura-copia" . Cita: "Para gestionar los conflictos de escritura-escritura, la mayoría de las estructuras de datos RCU utilizan bloqueos regulares".
  8. McKenney, Paul E.; Walpole, Jonathan (julio de 2008). "Introducción de tecnología en el núcleo de Linux: un estudio de caso". SIGOPS Oper. Syst. Rev. 42 ( 5): 4– 17. doi : 10.1145/1400097.1400099 . S2CID 12748421 . 
  9. Olsson, Robert; Nilsson, Stefan (mayo de 2007). "TRASH: una estructura de datos dinámica LC-trie y hash". Taller de 2007 sobre conmutación y enrutamiento de alto rendimiento . págs. 1-6 . doi : 10.1109/HPSR.2007.4281239 . ISBN  978-1-4244-1205-1. S2CID 17493674 . 
  10. Piggin, Nick (julio de 2006). Una caché de páginas sin bloqueo en Linux: introducción, progreso y rendimiento . Simposio Linux de Ottawa .
  11. "Paul E. McKenney: Uso de Linux en RCU" .
  12. Kannan, Hari (2009). "Ordenación de accesos a metadatos desacoplados en multiprocesadores". Actas del 42.º Simposio Internacional Anual IEEE/ACM sobre Microarquitectura - Micro-42 . págs. 381–390 . doi : 10.1145/1669112.1669161 . ISBN  978-1-60558-798-1. S2CID 2465311 . 
  13. Matthews, Chris; Coady, Yvonne; Appavoo, Jonathan (2009). «Eventos de portabilidad: Un modelo de programación para infraestructuras de sistemas escalables». Actas del 3er taller sobre lenguajes de programación y sistemas operativos: Soporte lingüístico para sistemas operativos modernos . San José, CA, EE. UU.: Association for Computing Machinery. pág. 11. doi : 10.1145/1215995.1216006 . ISBN  978-1-59593-577-9.
  14. Da Silva, Dilma ; Krieger, Orran; Wisniewski, Robert W.; Waterland, Amos; Tam, David; Baumann, Andrew (abril de 2006). "K42: Una infraestructura para la investigación de sistemas operativos". ACM SIGOPS Operating Systems Review . 40 (2): 34– 42. doi : 10.1145/1131322.1131333 . S2CID 669053 . 
  15. Appavoo, Jonathan; Da Silva, Dilma; Krieger, Orran; Auslander, Mark; Ostrowski, Michal; Rosenburg, Bryan; Waterland, Amos; Wisniewski, Robert W.; Xenidis, Jimi (agosto de 2007). "Experiencia en la distribución de objetos en un sistema operativo SMMP". ACM Transactions on Computer Systems . 25 (3): 6/1–6/52. doi : 10.1145/1275517.1275518 . S2CID 931202 . 
  16. Fraser, Keir; Harris, Tim (2007). "Programación concurrente sin bloqueos". ACM Transactions on Computer Systems . 25 (2): 34– 42. CiteSeerX 10.1.1.532.5050 . doi : 10.1145/1233307.1233309 . S2CID 3030814 .  
  17. Porter, Donald E.; Hofmann, Owen S.; Rossbach, Christopher J.; Benn, Alexander; Witchel, Emmett (2009). "Transacciones de sistemas operativos". Actas del 22.º simposio ACM SIGOPS sobre principios de sistemas operativos - SOSP '09 . pág. 161. doi : 10.1145/1629575.1629591 . hdl : 2152/ETD-UT-2010-12-2488 . ISBN  978-1-60558-752-3. S2CID 28504 . 
  18. Hart, Thomas E.; McKenney, Paul E.; Demke Brown, Angela; Walpole, Jonathan (diciembre de 2007). "Rendimiento de la recuperación de memoria para la sincronización sin bloqueo". J. Parallel Distrib. Comput . 67 (12): 1270– 1285. doi : 10.1016/j.jpdc.2007.04.010 .
  19. McKenney, Paul E. (4 de enero de 2008). "RCU parte 2: Uso" . Linux Weekly News . Recuperado el 24 de septiembre de 2010 .
  20. ^ Desnoyers, Mathieu (diciembre de 2009). Seguimiento del sistema operativo de bajo impacto (PDF) . École Polytechnique de Montreal (Tesis).
  21. McKenney, Paul E. (17 de enero de 2008). "RCU parte 3: la API de RCU" . Linux Weekly News . Recuperado el 24 de septiembre de 2010 .
  22. ^ McKenney, Paul E.; Appavoo, Jonathan; Kleen, Andi; Krieger, Orran; Russell, oxidado; Sarma, Dipankar; Soni, Maneesh (julio de 2001). Actualización de lectura y copia (PDF) . Simposio de Linux en Ottawa .
  23. Wizard, The (agosto de 2001). "Memoria compartida, subprocesos, comunicación entre procesos" . Hewlett-Packard . Archivado del original el 20 de julio de 2011. Consultado el 26 de diciembre de 2010 .
  24. McKenney, Paul E. (octubre de 2003). "Uso de {RCU} en el kernel {Linux} 2.5" . Linux Journal . Consultado el 24 de septiembre de 2010 .
  25. McKenney, Paul E. (julio de 2004). Explotación de la destrucción diferida: un análisis de las técnicas de lectura, copia y actualización (PDF) . Escuela de Ciencias e Ingeniería OGI de la Universidad de Salud y Ciencias de Oregón (tesis).
  26. Kung, HT; Lehman, Q. (septiembre de 1980). "Mantenimiento concurrente de árboles de búsqueda binaria". ACM Transactions on Database Systems . 5 (3): 354. CiteSeerX 10.1.1.639.8357 . doi : 10.1145/320613.320619 . S2CID 13007648 .  
  27. Manber, Udi; Ladner, Richard E. (septiembre de 1984). "Control de concurrencia en una estructura de búsqueda dinámica". ACM Transactions on Database Systems . 9 (3).
  28. Rashid, Richard; Tevanian, Avadis; Young, Michael; Golub, David; Baron, Robert; Bolosky, William; Chew, Jonathan (octubre de 1987). Gestión de memoria virtual independiente de la máquina para arquitecturas de uniprocesadores y multiprocesadores paginados (PDF) . Segundo simposio sobre soporte arquitectónico para lenguajes de programación y sistemas operativos . Association for Computing Machinery.
  29. US 4809168 , Hennessy, James P.; Osisek, Damian L. y Seigh II, Joseph W., "Serialización pasiva en un entorno multitarea", publicado en febrero de 1989. 
  30. Pugh, William (junio de 1990). Mantenimiento concurrente de listas de salto (Informe técnico). Instituto de Estudios Avanzados de Ciencias de la Computación, Departamento de Ciencias de la Computación, Universidad de Maryland. CS-TR-2222.1.
  31. John, Aju (enero de 1995). vnodes dinámicos : diseño e implementación . USENIX Invierno de 1995 .
  32. US 5442758 , Slingwine, John D. y McKenney, Paul E., "Aparato y método para lograr la exclusión mutua con sobrecarga reducida y mantener la coherencia en un sistema multiprocesador", publicado en agosto de 1995. 
  33. Gamsa, Ben; Krieger, Orran; Appavoo, Jonathan; Stumm, Michael (febrero de 1999). Tornado: Maximización de la localidad y la concurrencia en un sistema operativo multiprocesador de memoria compartida (PDF) . Actas del tercer simposio sobre diseño e implementación de sistemas operativos .
  34. Russell, Rusty (junio de 2000). "Re: controladores de red modulares" . Archivado del original el 31 de marzo de 2012. Recuperado el 1 de octubre de 2010 .
  35. Russell, Rusty (junio de 2000). "Re: controladores de red modulares" . Archivado del original el 31 de marzo de 2012. Recuperado el 1 de octubre de 2010 .
  36. Colvin, Robert; Groves, Lindsay; Luchangco, Victor; Moir, Mark (agosto de 2006). Verificación formal de un algoritmo de conjuntos basado en listas concurrente perezoso (PDF) . Verificación asistida por computadora . Archivado del original (PDF) el 17 de julio de 2009.
  37. Desnoyers, Mathieu; McKenney, Paul E.; Stern, Alan; Dagenais, Michel R.; Walpole, Jonathan (febrero de 2012). "Implementaciones a nivel de usuario de actualización de lectura y copia" (PDF) . IEEE Transactions on Parallel and Distributed Systems . 23 (2): 375– 382. Bibcode : 2012ITPDS..23..375D . doi : 10.1109/TPDS.2011.159 . S2CID 832767 . 
  38. McKenney, Paul E.; Desnoyers, Mathieu; Jiangshan, Lai (13 de noviembre de 2013). "RCU en el espacio de usuario" . Linux Weekly News . Consultado el 17 de noviembre de 2013 .
  39. Gotsman, Alexey; Rinetzky, Noam; Yang, Hongseok (16–24 de marzo de 2013). Verificación de algoritmos de recuperación de memoria concurrentes con gracia (PDF) . ESOP'13: Simposio Europeo sobre Programación .
  40. US 7099932 , Frenkel, Ilan; Geller, Roman y Ramberg, Yoram et al., "Método y aparato para recuperar información de políticas de calidad de servicio de red desde un directorio en un sistema de gestión de políticas de calidad de servicio", publicado el 29 de agosto de 2006, asignado a Cisco Tech Inc. 

Bauer, RT, (junio de 2009), "Verificación operativa de un programa relativista" Informe técnico TR-09-04 de la PSU ( http://www.pdx.edu/sites/www.pdx.edu.computer-science/files/tr0904.pdf Archivado el 18 de junio de 2015 en Wayback Machine )

  • Paul E. McKenney, Mathieu Desnoyers y Lai Jiangshan: RCU en el espacio de usuario . Noticias semanales de Linux .
  • Paul E. McKenney y Jonathan Walpole: ¿Qué es RCU, fundamentalmente?, ¿ Qué es RCU? Parte 2: Uso , y RCU parte 3: la API de RCU . Noticias semanales de Linux .
  • Página web de RCU de Paul E. McKenney
  • Hart, McKenney y Demke Brown (2006). Lograr una sincronización sin bloqueo rápida: implicaciones de rendimiento de la recuperación de memoria. Un artículo destacado de IPDPS 2006 que compara el rendimiento de RCU con el de otros mecanismos de sincronización sin bloqueo. Versión de la revista (con Walpole como autor).
  • Patente estadounidense 5,442,758 (1995) "Aparato y método para lograr una exclusión mutua con sobrecarga reducida y mantener la coherencia en un sistema multiprocesador utilizando el historial de ejecución y la monitorización de hilos".
  • Paul McKenney: RCU para dormir . Noticias semanales de Linux .
Obtenido de " https://en.wikipedia.org/w/index.php?title=Read-copy-update&oldid=1356640379 "