Debe introducir al menos 3 caracteres en el buscador.
Inicio / Wikis / Tutoriales / Dentro del núcleo Linux 2.4 - Spinlocks, Spinlocks Read-Write y Spinlocks Big-Reader

Dentro del núcleo Linux 2.4 - Spinlocks, Spinlocks Read-Write y Spinlocks Big-Reader

 ***-- (2 opiniones)
GNU Free Documentation License Tutorial de Tigran Aivazian - 14 de Febrero de 2006
Temas Relacionados: Linux
19. Spinlocks, Spinlocks Read-Write y Spinlocks Big-Reader
Desde los primeros días del soporte Linux (al principio de los 90, en el siglo XX), los desarrolladores se encararon con el clásico problema de acceder a datos compartidos entre los diferentes tipos de contexto (procesos de usuario vs interrupciones) y diferentes instancias del mismo contexto para múltiples cpus.

El soporte SMP fue añadido a Linux 1.3.42 el 15 de Noviembre de 1995 (el parche original fue hecho para el 1.3.37 en Octubre del mismo año).

Si la región crítica del código puede ser ejecutada por el contexto de los procesos y el contexto de las interrupciones, entonces la forma de protegerlo usando las instrucciones cli/sti en UP es:



unsigned long flags;

save_flags(flags);
cli();
/* código crítico */
restore_flags(flags);




Mientras que esto está bien en UP, obviamente no lo está usándolo en SMP porque la misma secuencia de código quizás sea ejecutada simultáneamente en otra cpu, y mientras cli() suministra protección contra las carreras con el contexto de interrupciones en cada CPU individualmente, no suministra protección contra todas las carreras entre los contextos funcionando en diferentes CPUs. Es aquí donde los spinlocks son útiles.

Hay tres tipos de spinlocks: vanilla (básico), read-write y spinlocks big-reader. Los spinlocks read-write deberían de ser usados cuando existe una tendencia natural de 'muchos lectores y pocos escritores'. Un ejemplo de esto es el acceso a las lista de sistemas de archivos registrados (ver fs/super.c). La lista es guardada por el spinlock read-write file_systems_lock porque uno necesita acceso exclusivo sólo cuando se está registrando/desregistrando un sistema de archivos, pero cualquier proceso puede leer el archivo /proc/filesystems o usar la llamada al sistema sysfs(2) para forzar un escaneo de sólo lectura de la lista file_systems. Esto lo hace sensible a usar spinlocks read-write. Con los spinlocks read-write, uno puede tener múltiples lectores a la vez pero sólo un escritor y no puede haber lectores mientras hay un escritor. Por el camino, sería bonito si nuevos lectores no isaran un cierre mientras hay un escritor intentando usar un cierre, esto es, si Linux pudiera distribuir correctamente la solución del hambre potencial del escritor por los múltiples lectores. Esto quiere significar que los lectores deben de ser bloqueados mientras exista un escritor intentando usar el cierre. Este no es actualmente el caso y no es obvio cuando debería de ser arreglado - el argumento para lo contrario es - los lectores usualmente ocupan el cierre por un instante de tiempo muy pequeño, por lo tanto, ¿ellos realmente deberían de tener hambre mientras el escritor usa el cierre para periodos potencialmente más largos?

Los spinlocks Big-reader son una forma de spinlocks read-write altamente optimizados para accesos de lectura muy ligeros, con una penalización para los escritores. Hay un número limitado de spinlocks big-reader - actualmente sólo existen dos, de los cuales uno es usado sólo en sparc64 (irq global) y el otro es usado para redes. En todos los demás casos donde el patrón de acceso no concuerda con ninguno de estos dos escenarios, se debería utilizar los spinlocks básicos. No puedes bloquear mientras mantienes algún tipo de spinlock.

Los Spinlocks vienen en tres tipos: plano, _irq() y _bh().

  1. spin_lock()/spin_unlock() plano: si conoces que las interrupciones están siempre deshabilitadas o si no compites con el contexto de interrupciones (ej. desde un manejador de interrupciones), entonces puedes utilizar este. No toca el estado de interrupción en la actual CPU.
  2. spin_lock_irq()/spin_unlock_irq(): si sabes que las interrupciones están siempre habilitadas entonces puedes usar esta versión, la cual simplemente deshabilita (en el cierre) y re-habilita (en el desbloqueo) las interrupciones en la actual CPU. Por ejemplo, rtc_read() usa spin_lock_irq(&rtc_lock) (las interrupciones están siempre habilitadas dentro de read()) mientras que rtc_interrupt() usa spin_lock(&rtc_lock) (las interrupciones están siempre deshabilitadas dentro del manejador de interrupciones). Nótese que rtc_read() usa spin_lock_irq() y no el más genérico spin_lock_irqsave() porque en la entrada a cualquier llamada al sistema las interrupciones están siempre habilitadas.
  3. spin_lock_irqsave()/spin_unlock_irqrestore(): la forma más fuerte, es usada cuando el estado de las interrupciones no es conocido, pero sólo si las interrupciones no importan nada, esto es, no hay punteros usándolo si nuestro manejador de interrupciones no ejecuta ningún código crítico.

El motivo por el que no puedes usar el spin_lock() plano si compites contra el manejador de interrupciones es porque si lo usas y después un interrupción viene en la misma CPU, el esperará ocupado por el bloqueo para siempre: el que tenga el bloqueo, habiendo sido interrumpido, no continuará hasta el que manejador de interrupciones vuelva.

El uso más común de un spinlock es para acceder a estructuras de datos compartidas entre el contexto de proceso de usuario y el manejador de interrupciones:



spinlock_t my_lock = SPIN_LOCK_UNLOCKED;

my_ioctl()
{
spin_lock_irq(&my_lock);
/* sección crítica */
spin_unlock_irq(&my_lock);
}

my_irq_handler()
{
spin_lock(&lock);
/* sección crítica */
spin_unlock(&lock);
}




Hay un par de cosas que destacar sobre este ejemplo:

  1. El contexto del proceso, representado aquí como un método típico de un controlador - ioctl() (argumentos y valores de retorno omitidos para una mayor claridad), deben de usar spin_lock_irq() porque conocen que las interrupciones están siempre habilitadas mientras se ejecuta un método de dispositivo ioctl().
  2. El contexto de interrupciones, representado aquí por my_irq_handler() (otra vez los argumentos son omitidos para una mayor claridad) pueden usar la forma spin_lock() plana porque las interrupciones están deshabilitadas dentro del manejador de interrupciones.
Autor y licencia de 'Dentro del núcleo Linux 2.4 - Spinlocks, Spinlocks Read-Write y Spinlocks Big-Reader'
Tigran Aivazian Extraído de: http://es.tldp.org/Manuales-LuCAS/DENTRO-NUCLEO-LINUX/dentro-nucleo-linux-html/ GNU Free Documentation License
Licencia GNU Free Documentation License: http://www.es.gnu.org/licencias/fdles.html
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.

Wikis relacionados con 'Dentro del núcleo Linux 2.4 - Spinlocks, Spinlocks Read-Write y Spinlocks Big-Reader'

La fijación de precios está convirtiéndose en un modo de vida para muchos minoristas y... Más »
Este documento describe cómo hacer el enmascarado (masqueradinq), proxy transparente, reenvío de puertos (port forwarding),... Más »
En este documento se presenta la información acerca de la instalación, configuración, ejecución y mantenimiento... Más »
Esta es la primerísima edición del Linux en Castellano COMO. La audiencia a la que... Más »
Este documento pretende ser el punto de entrada de los hispanohablantes al mundo Linux, intentando... Más »
¿Estás seguro de que deseas eliminar este capítulo?