stringtranslate.com

Leer-copiar-actualizar

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

Siempre que un hilo inserta o elimina elementos de estructuras de datos en la memoria compartida , se garantiza que todos los lectores verán y atravesarán la estructura anterior o la nueva, evitando así inconsistencias (por ejemplo, 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 más espacio. Esto hace que todos los lectores procedan como si no hubiera sincronización involucrada, por lo que serán rápidos, pero también dificultarán las actualizaciones.

Nombre y descripción general

El nombre proviene de la forma en que se utiliza RCU para actualizar una estructura vinculada en su lugar. Un hilo que desee hacer esto utiliza los siguientes pasos:

Por lo tanto, la estructura se lee simultáneamente con la copia de un 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 aplazamiento de MP por parte de programadores VM/XA y generaciones de programadores K42 y Tornado.

Descripción detallada

Procedimiento de inserción lectura-copia-actualización. Un hilo asigna una estructura con tres campos y luego configura 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 está en proceso de actualización: los actualizadores de RCU no pueden bloquear a los lectores ni obligarlos a reintentar sus accesos. Esta descripción general comienza mostrando cómo se pueden insertar y eliminar datos de estructuras vinculadas de forma segura a pesar de los lectores simultáneos. 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 , de color rojo para indicar que un lector puede acceder a él en cualquier momento, lo que requiere que los actualizadores tengan cuidado. La asignación de memoria para una nueva estructura pasa 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 pasa al tercer estado, que muestra los valores inicializados de los campos de la estructura. Asignar una referencia a esta nueva estructura a las transiciones de gptr al cuarto y último estado. En este estado, la estructura es accesible para los lectores y, por tanto, está coloreada en rojo. La primitiva rcu_assign_pointer se utiliza para llevar a cabo esta asignación y garantiza que la asignación sea atómica en el sentido de que los lectores simultáneos verán un puntero NULL o un puntero válido a la nueva estructura, pero no una combinación de los dos valores. Las propiedades adicionales de rcu_assign_pointer se describen más adelante en este artículo.

Procedimiento de eliminación de lectura-copia-actualización

Este procedimiento demuestra cómo se pueden insertar nuevos datos en una estructura de datos vinculada incluso aunque los lectores estén recorriendo simultáneamente la estructura de datos antes, durante y después de la inserción. El segundo diagrama de la derecha muestra un procedimiento de eliminación de cuatro estados, nuevamente con el tiempo avanzando de izquierda a derecha.

El primer estado muestra una lista vinculada que contiene los elementos A , B y C. Los tres elementos están coloreados en rojo para indicar que un lector de RCU puede hacer referencia a cualquiera de ellos en cualquier momento. El uso de list_del_rcu para eliminar el elemento B de esta lista pasa al segundo estado. Tenga en cuenta que el vínculo del elemento B al C se deja intacto para permitir a los lectores que actualmente hacen referencia al elemento B recorrer 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 de cualquier manera, cada lector verá una lista enlazada válida y con el formato correcto. El elemento B ahora está coloreado en 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 de espera de lectores pasa al tercer estado. Tenga en cuenta que esta operación de espera de lectores solo necesita esperar a los lectores preexistentes, pero no a los lectores nuevos. El elemento B ahora está coloreado en verde para indicar que los lectores ya no pueden hacer referencia a él. Por lo tanto, ahora es seguro para el actualizador liberar el elemento B , pasando así al cuarto y último estado.

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

Este procedimiento demuestra cómo se pueden eliminar datos antiguos de una estructura de datos vinculada incluso aunque los lectores estén recorriendo simultáneamente la estructura de datos antes, durante y después de la eliminación. Dada la inserción y eliminación, se puede implementar una amplia variedad de estructuras de datos utilizando RCU.

Los lectores de RCU se ejecutan dentro de las secciones críticas del lado de lectura , que normalmente están delimitadas por rcu_read_lock y rcu_read_unlock . Cualquier declaración que no esté dentro de una sección crítica del lado de lectura de RCU se dice que está en un estado inactivo y no se permite que dichas declaraciones contengan referencias a estructuras de datos protegidas por RCU, ni se requiere que la operación de espera de lectores espere. para hilos en estados de reposo. Cualquier período de tiempo durante el cual cada subproceso reside al menos una vez en estado inactivo se denomina período de gracia . Por definición, cualquier sección crítica de lectura de RCU que exista al comienzo de un período de gracia determinado debe completarse antes del final de ese período de gracia, lo que constituye la garantía fundamental proporcionada por RCU. Además, la operación de espera de lectores debe esperar a que transcurra al menos un período de gracia. Resulta que esta garantía se puede proporcionar con gastos generales del lado de lectura extremadamente pequeños; de hecho, en el caso límite que realmente se logra mediante compilaciones del kernel de Linux de clase servidor, el costo adicional del lado 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 referencias a 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 del lado de lectura de RCU. La razón por la que es seguro ejecutar la fase de eliminación al mismo tiempo que los lectores RCU es que la semántica de las CPU modernas garantiza que los lectores verán la versión antigua o nueva de la estructura de datos en lugar de una referencia parcialmente actualizada. Una vez transcurrido el período de gracia, ya no puede haber lectores que hagan referencia a la versión anterior, por lo que es seguro que la fase de recuperación libere ( recupere ) los elementos de datos que componían esa versión anterior. [3]

Dividir una actualización en fases de eliminación y recuperación permite al actualizador realizar la fase de eliminación inmediatamente y posponer la fase de recuperación hasta que todos los lectores activos durante la fase de eliminación hayan completado, en otras palabras, hasta que haya transcurrido un período de gracia. [nota 1]

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

  1. Asegúrese de que todos los lectores que acceden a estructuras de datos protegidas por RCU realicen sus referencias desde una sección crítica del lado 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, de modo que todos los lectores anteriores (que aún puedan tener punteros a la estructura de datos eliminada en el paso anterior) hayan completado las secciones críticas del lado de lectura de la RCU.
  4. En este punto, no puede haber lectores que todavía tengan referencias a la estructura de datos, por lo que ahora se puede recuperar de forma segura (por ejemplo, liberar). [nota 2]

En el procedimiento anterior (que coincide con el diagrama anterior), el actualizador realiza tanto el paso de eliminación como el de recuperación, pero a menudo es útil que un subproceso completamente diferente realice la recuperación. El recuento de referencias se puede utilizar para permitir que el lector realice la eliminación, de modo que, incluso si el mismo hilo realiza tanto el paso de actualización (paso (2) anterior) como el paso de recuperación (paso (4) anterior), a menudo es útil pensar en ellos. por separado.

RCU es quizás el algoritmo sin bloqueo más común para una estructura de datos compartida. RCU no requiere ninguna espera para cualquier número de lectores. Las implementaciones de RCU de un solo escritor también están libres de bloqueos para el escritor. [5] Algunas implementaciones de RCU con múltiples escritores no tienen bloqueos. [6] Otras implementaciones de múltiples escritores de RCU serializan escritores con un bloqueo. [7]

Usos

A principios de 2008, había casi 2.000 usos de la API RCU dentro del kernel de Linux [8], incluidas las pilas de protocolos de red [9] y el sistema de gestión de memoria. [10] En marzo de 2014 , había más de 9.000 usos. [11] Desde 2006, los investigadores han aplicado RCU y técnicas similares a una serie de problemas, incluida la gestión de metadatos utilizados en el análisis dinámico, [12] la gestión de la vida útil de los objetos agrupados, [13] la gestión de la vida útil de los objetos en el sistema operativo de investigación K42 , [14] [15] y optimización de implementaciones de memoria transaccional de software . [16] [17] Dragonfly BSD utiliza una técnica similar a RCU que se parece 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 que los lectores de RCU utilicen una sincronización mucho más liviana; en algunos casos, ninguna sincronización en absoluto. Por el contrario, en esquemas basados ​​en bloqueos más convencionales, los lectores deben utilizar una sincronización intensa para evitar que un actualizador borre la estructura de datos que se encuentra debajo de ellos. La razón es que los actualizadores basados ​​en bloqueos generalmente actualizan los datos en el lugar y, por lo tanto, deben excluir a los lectores. Por el contrario, los actualizadores basados ​​en RCU generalmente aprovechan el hecho de que las escrituras en punteros alineados únicos son atómicas en las CPU modernas, lo que permite la inserción, eliminación y reemplazo atómicos de datos en una estructura vinculada sin interrumpir a los lectores. Los lectores RCU simultáneos pueden continuar accediendo a las versiones antiguas y prescindir de las instrucciones atómicas de lectura, modificación y escritura, barreras de memoria y errores de caché que son tan costosos en los sistemas informáticos SMP modernos, incluso en ausencia de contención de bloqueo. [18] [19] La naturaleza liviana de las primitivas del lado de lectura de RCU proporciona ventajas adicionales más allá del excelente rendimiento, escalabilidad y respuesta en tiempo real. Por ejemplo, brindan inmunidad a la mayoría de las condiciones de bloqueo y bloqueo activo. [nota 3]

Por supuesto, RCU también tiene desventajas. Por ejemplo, RCU es una técnica especializada que funciona mejor en situaciones con mayoritariamente lecturas y pocas actualizaciones, pero suele ser menos aplicable a cargas de trabajo de solo actualización. Para otro ejemplo, aunque el hecho de que los lectores y actualizadores de RCU puedan ejecutarse simultáneamente es lo que permite la naturaleza liviana de las primitivas del lado de lectura de RCU, algunos algoritmos pueden no ser compatibles con la concurrencia de lectura/actualización.

A pesar de más de una década de experiencia con RCU, el alcance exacto de su aplicabilidad sigue siendo un tema de investigación.

Patentes

La técnica está cubierta por la patente de software estadounidense 5.442.758 , expedida el 15 de agosto de 1995 y asignada a Sequent Computer Systems , así como por la patente estadounidense 5.608.893 (expirada el 30 de marzo de 2009), la patente estadounidense 5.727.209 (expirada el 30 de marzo de 2010) 05), la patente de EE. UU. 6.219.690 (expirada el 18 de mayo de 2009) y la patente de EE. UU. 6.886.162 (expirada el 25 de mayo de 2009). La patente estadounidense 4.809.168, ahora vencida, cubre una técnica estrechamente relacionada. RCU es también el tema de un reclamo en la demanda SCO v. IBM .

Interfaz RCU de muestra

RCU está disponible en varios sistemas operativos y se agregó al kernel de Linux en octubre de 2002. También están disponibles 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]

 CPU 0 CPU 1 CPU 2 ----------------- ------------------------- -------- ------- 1.rcu_read_lock() 2. ingresa sincronizar_rcu() 3.rcu_read_lock() 4.rcu_read_unlock() 5. sale de sincronizar_rcu() 6.rcu_read_unlock()
Dado que synchronize_rcues la API la que debe determinar cuándo terminan los lectores, su implementación es clave para RCU. Para que RCU sea útil en todas las situaciones, excepto en las de lectura más intensiva, la synchronize_rcusobrecarga de 's también debe ser bastante pequeña.
Alternativamente, en lugar de bloquear, sincronizar_rcu puede registrar una devolución de llamada que se invocará después de que se hayan completado todas las secciones críticas del lado de lectura de RCU en curso. Esta variante de devolución de llamada se llama call_rcuen el kernel de Linux.
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 de RCU observa la secuencia de tiempo de rcu_read_lock, rcu_read_unlock, synchronize_rcuy call_rculas invocaciones para determinar cuándo (1) synchronize_rculas invocaciones pueden regresar a sus llamantes y (2) call_rcuse pueden invocar las devoluciones de llamada. Las implementaciones eficientes de la infraestructura RCU hacen un uso intensivo del procesamiento por lotes para amortizar sus gastos generales en muchos usos de las API correspondientes.

Implementación sencilla

RCU tiene implementaciones de "juguete" extremadamente simples que pueden ayudar a comprender RCU. Esta sección presenta una de esas implementaciones de "juguete" que funciona en un entorno no preventivo . [22]

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

En el ejemplo de código, rcu_assign_pointerse rcu_dereferencepuede ignorar sin perder mucho. Sin embargo, son necesarios para suprimir la optimización dañina del compilador y evitar que las CPU reordenen los accesos.

#define rcu_assign_pointer(p, v) ({ \  smp_wmb(); /* Ordenar 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 eso rcu_read_locky rcu_read_unlockno haga nada. Esta es la gran fortaleza de la RCU clásica en un kernel no preventivo: la sobrecarga del lado de lectura es precisamente cero, al igual smp_read_barrier_depends()que una macro vacía en todas las CPU excepto en DEC Alpha ; [23] [ verificación fallida ] tales barreras de memoria no son necesarias en las CPU modernas. La ACCESS_ONCE()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 rcu_read_lockpueda participar en un ciclo de interbloqueo , hacer que un proceso en tiempo real no cumpla con su fecha límite de programación, precipitar la inversión de prioridad o resultar en una alta contención de bloqueo . Sin embargo, en esta implementación de RCU de juguete, el bloqueo dentro de una sección crítica del lado de lectura de la RCU es ilegal, al igual que el bloqueo mientras se mantiene un bloqueo de giro puro.

La implementación de synchronize_rcumueve la persona que llama de sincronizar_cpu a cada CPU, bloqueando así hasta que todas las CPU hayan podido realizar el cambio de contexto. Recuerde que este es un entorno no preventivo y que el bloqueo dentro de una sección crítica del lado de lectura de la RCU es ilegal, lo que implica que no puede haber puntos de preferencia dentro de una sección crítica del lado de lectura de la 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 del lado de lectura de la RCU anteriores. Una vez que todas las CPU hayan ejecutado un cambio de contexto, se habrán completado todas las secciones críticas del lado de lectura de la RCU anteriores.

Analogía con el bloqueo lector-escritor

Aunque RCU se puede utilizar de muchas maneras diferentes, un uso muy común de RCU es análogo al bloqueo de lector-escritor. La siguiente visualización de códigos en paralelo muestra cuán estrechamente relacionados pueden estar el bloqueo del lector-escritor y la RCU. [24]

 /* bloqueo lector-escritor */ /* RCU */  1 estructura el { 1 estructura el { 2 estructura list_head lp ; 2 estructura list_head lp ; 3 teclas largas ; 3 teclas largas ; 4 exclusión mutua spinlock_t ; 4 exclusión mutua spinlock_t ; 5 datos enteros ; 5 datos enteros ; 6 /* Otros campos de datos */ 6 /* Otros campos de datos */ 7 }; 7 }; 8 DEFINE_RWLOCK ( listamutex ); 8 DEFINE_SPINLOCK ( listamutex ); 9 LIST_HEAD ( cabeza ); 9 LIST_HEAD ( cabeza );                                                  1 búsqueda int ( clave larga , int * resultado ) 1 búsqueda int ( clave larga , int * resultado ) 2 { 2 { 3 struct el * p ; 3 estructura el * p ; 4 4 5 lectura_bloqueo ( & 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 -> clave == clave ) { 7 if ( p -> clave == clave ) { 8 * resultado = p -> datos ; 8 * resultado = p -> datos ; 9 read_unlock ( & ​​listmutex ); 9 rcu_read_unlock (); 10 devuelve 1 ; 10 devuelve 1 ; 11 } 11 } 12 } 12 } 13 read_unlock ( & ​​listmutex ); 13 rcu_read_unlock (); 14 devuelve 0 ; 14 devuelve 0 ; 15 } 15 }                                                                                      1 int eliminar ( tecla larga ) 1 int eliminar ( tecla larga ) 2 { 2 { 3 struct el * p ; 3 estructura 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 -> clave == clave ) { 7 if ( p -> clave == clave ) { 8 list_del ( & p- > lp ); 8 list_del_rcu ( & p- > lp ); 9 write_unlock ( & ​​listmutex ); 9 spin_unlock ( & ​​listmutex ); 10 sincronizar_rcu (); 10 k gratis ( p ); 11 k gratis ( p ); 11 devolver 1 ; 12 retorno 1 ; 12 } 13 } 13 } 14 } 14 write_unlock ( & ​​listmutex ); 15 spin_unlock ( & ​​listmutex ); 15 devuelve 0 ; 16 devuelve 0 ; 16 } 17 }                                                                                  

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

Sin embargo, existe un problema potencial: las secciones críticas del lado de lectura y del lado de actualización ahora pueden ejecutarse simultáneamente. En muchos casos, esto no será un problema, pero de todos modos es necesario comprobarlo cuidadosamente. Por ejemplo, si varias actualizaciones de listas independientes deben verse como una única actualización atómica, la conversión a RCU requerirá especial cuidado.

Además, la presencia de synchronize_rcusignifica que la versión RCU 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 recuento de referencias.

Historia

Las técnicas y mecanismos que se asemejan a la RCU se han inventado de forma independiente varias veces: [25]

  1. HT Kung y Q. Lehman describieron el uso de recolectores de basura para implementar un acceso tipo RCU a un árbol de búsqueda binario. [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 subprocesos que se ejecutan en el momento de la eliminación hayan terminado, lo que funciona en entornos que no tienen subprocesos de larga duración. [27]
  3. Richard Rashid y otros. describió una implementación diferida de búfer de traducción (TLB) que difería la recuperación de espacio de direcciones virtuales hasta que todas las CPU vaciaron su TLB, que es similar en espíritu a algunas implementaciones de RCU. [28]
  4. A James P. Hennessy, Damian L. Osisek y Joseph W. Seigh, II se les concedió la patente estadounidense 4.809.168 en 1989 (ya caducada). Esta patente describe un mecanismo similar a una RCU que aparentemente se usó en VM/XA en mainframes IBM . [29]
  5. William Pugh describió un mecanismo similar a RCU que dependía de que los lectores establecieran banderas explícitas. [30]
  6. Aju John propuso una implementación similar a la de RCU en la que 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 PE McKenney recibieron la patente estadounidense 5.442.758 en agosto de 1995, que describe la RCU implementada en DYNIX/ptx y posteriormente en el kernel de Linux. [32]
  8. B. Gamsa, O. Krieger, J. Appavoo y M. Stumm describieron un mecanismo similar a una RCU utilizado en el sistema operativo de investigación Tornado de la Universidad de Toronto y los sistemas operativos de investigación IBM Research K42 , 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 agregó RCU a la versión 2.5.43 del kernel de Linux en octubre de 2002.
  11. Robert Colvin et al. Verificó formalmente un algoritmo de conjunto basado en listas concurrentes diferidos que se parece a RCU. [36]
  12. M. Desnoyers y col. publicó una descripción de la RCU en el espacio de usuario. [37] [38]
  13. A. Gotsman et al. Semántica formal derivada para RCU basada en la lógica de separación. [39]
  14. A Ilan Frenkel, Roman Geller, Yoram Ramberg y Yoram Snir se les concedió 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 una manera que exige lectura/escritura. coherencia y permite la simultaneidad de lectura/escritura. [40]

Ver también

Notas

  1. ^ Solo se deben considerar los lectores que estén activos durante la fase de eliminación, porque 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, la fase de recuperación no podrá interrumpirlos.
  2. ^ Se pueden utilizar recolectores de basura , cuando estén disponibles, para realizar este paso.
  3. ^ Los interbloqueos basados ​​en RCU aún son posibles, por ejemplo, ejecutando una declaración que se bloquea hasta que se completa un período de gracia dentro de una sección crítica del lado de lectura de RCU.

Referencias

  1. ^ a b Tanenbaum, Andrew (2015). Sistemas operativos modernos (4ª ed.). Estados Unidos: Pearson. pag. 148.ISBN _ 9781292061429.
  2. ^ Guniguntala, Dinakar; McKenney, Paul E.; Triplett, Josué; 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". Revista de sistemas IBM . 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?". Noticias semanales de Linux . 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 simultaneidad (PDF) . Computación y Sistemas Paralelos y Distribuidos . págs. 509–518. {{cite conference}}: Enlace externo en |journal=( ayuda )
  5. ^ Naama Ben-David; Guy E. Blelloch; Yihan Sun; Yuanhao Wei. "Simultaneidad eficiente de un solo escritor".
  6. ^ "Multiproceso sin bloqueo con operaciones atómicas".
  7. ^ Eddie Kohler. "Notas sobre la actualización de lectura y copia". cita: "Para gestionar los conflictos de escritura-escritura, la mayoría de las estructuras de datos de RCU utilizan bloqueo regular".
  8. ^ McKenney, Paul E.; Walpole, Jonathan (julio de 2008). "Introducción de tecnología en el kernel de Linux: un estudio de caso". Opera SIGOPS. Sistema. Rdo . 42 (5): 4-17. doi :10.1145/1400097.1400099. S2CID  12748421.
  9. ^ Olsson, Robert; Nilsson, Stefan (mayo de 2007). "TRASH una estructura dinámica de datos LC-trie y hash". 2007 Taller 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). Un caché de página sin bloqueo en Linux: introducción, progreso, rendimiento. Simposio de Linux en Ottawa .
  11. ^ "Paul E. McKenney: uso de RCU Linux".
  12. ^ Kannan, Hari (2009). "Ordenar 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. ^ Mateos, Chris; Coady, Yvonne; Appavoo, Jonathan (2009). Eventos de portabilidad: un modelo de programación para infraestructuras de sistemas escalables . PLOS '06: Actas del 3er Taller sobre Lenguajes de Programación y Sistemas Operativos . San José, California, Estados Unidos. doi :10.1145/1215995.1216006. ISBN 978-1-59593-577-9.
  14. ^ Da Silva, Dilma ; Krieger, Orran; Wisniewski, Robert W.; Waterland, Amós; Tam, David; Baumann, Andrew (abril de 2006). "K42: una infraestructura para la investigación de sistemas operativos". Opera SIGOPS. Sistema. Rdo . 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, Amós; Wisniewski, Robert W.; Xenidis, Jimi (agosto de 2007). "Experiencia en la distribución de objetos en un sistema operativo SMMP". Transacciones ACM en sistemas informáticos . 25 (3): 1/6–6/52. doi :10.1145/1275517.1275518. S2CID  931202.
  16. ^ Fraser, Keir; Harris, Tim (2007). "Programación concurrente sin bloqueos". Transacciones ACM en sistemas informáticos . 25 (2): 34–42. CiteSeerX 10.1.1.532.5050 . doi :10.1145/1233307.1233309. S2CID  3030814. 
  17. ^ Portero, Donald E.; Hofmann, Owen S.; Rossbach, Christopher J.; Benn, Alejandro; Witchel, Emmett (2009). "Transacciones de sistemas operativos". Actas del 22º simposio de ACM SIGOPS sobre principios de sistemas operativos - SOSP '09 . pag. 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, Ángela; Walpole, Jonathan (diciembre de 2007). "Rendimiento de la recuperación de memoria para sincronización sin bloqueo". J. Distribución paralela. Computación . 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". Noticias semanales de Linux . Consultado 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". Noticias semanales de Linux . Consultado 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. ^ Mago, The (agosto de 2001). "Memoria compartida, subprocesos, comunicación entre procesos". Hewlett Packard . Consultado el 26 de diciembre de 2010 .
  24. ^ McKenney, Paul E. (octubre de 2003). "Usando {RCU} en el kernel {Linux} 2.5". Diario de Linux . 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 técnicas de lectura, copia y actualización (PDF) . Escuela de Ciencias e Ingeniería OGI de la Universidad de Ciencias y Salud de Oregon (Tesis).
  26. ^ Kung, HT; Lehman, Q. (septiembre de 1980). "Mantenimiento simultáneo de árboles de búsqueda binaria". Transacciones ACM en sistemas de bases de datos . 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". Transacciones ACM en sistemas de bases de datos . 9 (3).
  28. ^ Rashid, Richard; Tevaniano, Avadis; Joven, Miguel; Golub, David; Barón, Robert; Bolosky, William; Chew, Jonathan (octubre de 1987). Gestión de memoria virtual independiente de la máquina para arquitecturas monoprocesador y multiprocesador paginadas (PDF) . Segundo Simposio sobre Soporte Arquitectónico para Lenguajes de Programación y Sistemas Operativos . Asociación para Maquinaria de Computación.
  29. ^ Estados Unidos 4809168, Hennessy, James P.; Osisek, Damian L. & 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 Omisión (Informe técnico). Instituto de Estudios Avanzados en 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). Vnodos dinámicos: diseño e implementación. USENIX Invierno de 1995 .
  32. ^ US 5442758, Slingwine, John D. & McKenney, Paul E., "Aparato y método para lograr una reducción de la exclusión mutua y el mantenimiento de 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 simultaneidad 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 desde el original el 31 de marzo de 2012 . Consultado el 1 de octubre de 2010 .
  35. ^ Russell, Rusty (junio de 2000). "Re: controladores de red modulares". Archivado desde el original el 31 de marzo de 2012 . Consultado el 1 de octubre de 2010 .
  36. ^ Colvin, Robert; Arboledas, Lindsay; Luchangco, Víctor; Moir, Mark (agosto de 2006). Verificación formal de un algoritmo de conjunto basado en listas concurrentes diferidos (PDF) . Verificación asistida por computadora . Archivado desde el original (PDF) el 17 de julio de 2009.
  37. ^ Desnoyers, Mathieu; McKenney, Paul E.; popa, Alan; Dagenais, Michel R.; Walpole, Jonathan (febrero de 2012). "Implementaciones a nivel de usuario de actualización de lectura y copia" (PDF) . Transacciones IEEE en sistemas paralelos y distribuidos . 23 (2): 375–382. doi :10.1109/TPDS.2011.159. S2CID  832767.
  38. ^ McKenney, Paul E.; Desnoyers, Mathieu; Jiangshan, Lai (13 de noviembre de 2013). "RCU de espacio de usuario". Noticias semanales de Linux . Consultado el 17 de noviembre de 2013 .
  39. ^ Gotsman, Alexey; Rinetzky, Noam; Yang, Hongseok (16 al 24 de marzo de 2013). Verificación de algoritmos de recuperación de memoria concurrente con gracia (PDF) . ESOP'13: Simposio Europeo de Programación .
  40. ^ Estados Unidos 7099932, Frenkel, Ilan; Geller, Roman & Ramberg, Yoram et al., "Método y aparato para recuperar información de políticas de calidad de servicio de red de 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" PSU Tech Report TR-09-04 (http://www.pdx.edu/sites/www.pdx.edu.computer-science/files/ tr0904.pdf)

enlaces externos