Bloqueos de número en cola
Los bloqueos de número en cola son una variante de bloqueos de giro que funcionan bien para bloqueos altamente contendientes. Los bloqueos de giro tradicionales y sin poner en cola son una mejor opción para bloqueos de duración ligeros o más cortos.
Entre las ventajas de usar un bloqueo de número en cola se incluyen:
Contención reducida del procesador: los bloqueos de giro tradicionales pueden provocar una contención significativa del procesador cuando varios subprocesos intentan adquirir el bloqueo simultáneamente, ya que recorren continuamente (o "gira") comprobando el estado del bloqueo. Esto puede degradar el rendimiento del sistema, especialmente en sistemas multiprocesador. Los bloqueos de número en cola mitigan esto mediante la organización de subprocesos en una cola. Cuando un subproceso adquiere un bloqueo, solo la siguiente línea gira activamente, esperando adquirir el bloqueo. Esto reduce los ciclos de CPU desperdiciados al girar, especialmente cuando el bloqueo se mantiene durante más tiempo.
Equidad y prevención de hambre: uno de los problemas con bloqueos de giro básicos es la falta de equidad; un subproceso se puede morir de hambre y nunca adquirir el bloqueo si otros subprocesos se adquieren y liberan continuamente. Los bloqueos de número en cola abordan esto asegurándose de que los subprocesos adquieren el bloqueo en el orden en que intentaron hacerlo. Este control secuencial evita el colapso y garantiza que todos los subprocesos reciben servicio con el tiempo.
Escalabilidad: a medida que aumenta el número de procesadores o núcleos en un sistema, la eficacia de los mecanismos de sincronización resulta fundamental para el rendimiento. Los bloqueos de número en cola son más escalables que los bloqueos de giro tradicionales porque reducen la sobrecarga en los procesadores al minimizar el giro activo en todos los núcleos. Esto es especialmente importante en sistemas de alto rendimiento y de varios núcleos en los que la eficiencia del controlador puede afectar directamente al rendimiento general del sistema.
Uso eficaz de los recursos del sistema: al reducir los bloqueos de giro innecesarios del procesador, los bloqueos de giro en cola permiten al sistema usar sus recursos de forma más eficaz. Esto no solo mejora el rendimiento del controlador del dispositivo, sino que también tiene un impacto positivo en la capacidad de respuesta general del sistema y el consumo de energía, lo que es especialmente beneficioso en entornos sensibles a la energía.
Simplicidad y confiabilidad: a pesar de sus ventajas para reducir la contención y mejorar la equidad, los bloqueos de giro en cola abstraen la complejidad del desarrollador. Proporcionan un mecanismo sencillo y confiable para proteger los recursos compartidos sin que el desarrollador tenga que implementar una lógica de bloqueo compleja. Esta simplicidad reduce la probabilidad de errores relacionados con el control de bloqueo incorrecto, lo que mejora la confiabilidad del controlador.
A continuación se muestra un fragmento de código simplificado que muestra las operaciones descritas con un bloqueo de giro en cola en un controlador del modo kernel de Windows. En este ejemplo se muestra cómo declarar e inicializar un bloqueo de número mediante KeInitializeSpinLock y, a continuación, adquirir y liberar el bloqueo mediante KeAcquireInStackQueuedSpinLock y KeReleaseInStackQueuedSpinLock, respectivamente.
KSPIN_LOCK SpinLock;
KLOCK_QUEUE_HANDLE LockHandle;
// Initialize the spin lock
KeInitializeSpinLock(&SpinLock);
// Assume this function is called in some kind of context where
// the below operations make sense, e.g., in a device I/O path
// Acquire the queued spin lock
KeAcquireInStackQueuedSpinLock(&SpinLock, &LockHandle);
// At this point, the current thread holds the spin lock.
// Perform thread-safe operations here.
// ...
// Release the queued spin lock
KeReleaseInStackQueuedSpinLock(&LockHandle);
El controlador asigna una estructura KLOCK_QUEUE_HANDLE que pasa por puntero a KeAcquireInStackQueuedSpinLock. El controlador pasa la misma estructura por puntero a KeReleaseInStackQueuedSpinLock cuando libera el bloqueo de giro.
Normalmente, los controladores deben asignar la estructura en la pila cada vez que adquieren el bloqueo. Un controlador no debe asignar la estructura como parte de su contexto de dispositivo y, a continuación, compartir la misma estructura desde varios subprocesos.
Los controladores no deben mezclar llamadas a las rutinas de bloqueo de giro en cola y las rutinas ke Xxx SpinLock normales en el mismo bloqueo degiro.
Si el controlador ya está en IRQL = DISPATCH_LEVEL, puede llamar a KeAcquireInStackQueuedSpinLockAtDpcLevel y KeReleaseInStackQueuedSpinLockFromDpcLevel en su lugar.