En el documento con el mismo título que el de esta pregunta, los autores describen cómo construir una operación CAS de varias palabras linealizable sin bloqueo utilizando solo un CAS de una sola palabra. Primero presentan la operación de doble comparación, intercambio único, RDCSS, de la siguiente manera:
word_t RDCSS(RDCSSDescriptor_t *d) {
do {
r = CAS1(d->a2, d->o2, d);
if (IsDescriptor(r)) Complete(r);
} while (IsDescriptor(r));
if (r == d->o2) Complete(d); // !!
return r;
}
void Complete(RDCSSDescriptor_t *d) {
v = *(d->a1);
if (v == d->o1) CAS1(d->a2, d, d->n2);
else CAS1(d->a2, d, d->o2);
}
donde el RDCSSDescriptor_t
es una estructura con los siguientes campos:
a1
- dirección de la primera condicióno1
- valor esperado en la primera direccióna2
- dirección de la segunda condicióno2
- valor esperado en la segunda direcciónn2
- el nuevo valor que se escribirá en la segunda dirección
Este descriptor se crea e inicializa una vez en un subproceso que inicia la operación RDCSS: ningún otro subproceso tiene una referencia hasta que el primer CAS1 en la función RDCSS
tiene éxito, haciendo que el descriptor sea accesible (o activo en la terminología del documento).
La idea detrás del algoritmo es la siguiente: reemplace la segunda ubicación de memoria con un descriptor que diga lo que desea hacer. Luego, dado que el descriptor está presente, verifique la primera ubicación de la memoria para ver si su valor cambió. Si no es así, reemplace el descriptor en la segunda ubicación de memoria con el nuevo valor. De lo contrario, vuelva a establecer la segunda ubicación de memoria en el valor anterior.
Los autores no explican por qué la línea con el !!
comentario es necesaria dentro del artículo. Me parece que las CAS1
instrucciones en la Complete
función siempre fallarán después de esta verificación, siempre que no haya una modificación concurrente. Y si hubo una modificación concurrente entre la verificación y el CAS Complete
, entonces el hilo que realiza la verificación aún debería fallar con su CAS Complete
, ya que la modificación concurrente no debería usar el mismo descriptor d
.
Mi pregunta es: ¿se puede omitir la verificación en la función RDCSSS
, if (r == d->o2)...
con RDCSS aún manteniendo la semántica de una instrucción de doble comparación, intercambio único que es linealizable y sin bloqueo ? (línea con !!
comentario)
Si no, ¿puede describir el escenario en el que esta línea es realmente necesaria para garantizar la corrección?
Gracias.