requisitos de alineación para las instrucciones x86 atómicas

Microsoft ofrece la función InterlockedCompareExchange para realizar operaciones atómicas de comparación e intercambio. También hay un _InterlockedCompareExchange intrínseco .

En x86 estos se implementan utilizando la instrucción cmpxchg .

Sin embargo, al leer la documentación sobre estos tres enfoques, no parecen estar de acuerdo con los requisitos de alineación.

El manual de referencia de Intel no dice nada sobre la alineación (aparte de que si la verificación de alineación está habilitada y se hace una referencia de memoria no alineada, se genera una excepción)

También busqué el prefijo de lock , que especifica específicamente que

La integridad del prefijo LOCK no se ve afectada por la alineación del campo de memoria.

(énfasis mío)

Entonces Intel parece decir que la alineación es irrelevante. La operación será atómica sin importar qué.

La documentación intrínseca de _InterlockedCompareExchange tampoco dice nada sobre la alineación, sin embargo, la función InterlockedCompareExchange establece que

Los parámetros para esta función deben estar alineados en un límite de 32 bits; de lo contrario, la función se comportará de forma impredecible en sistemas multiprocesador x86 y cualquier sistema que no sea x86.

Entonces, ¿qué da? ¿Los requisitos de alineación para InterlockedCompareExchange solo son para asegurarse de que la función funcionará incluso en las CPU pre-486 donde la instrucción cmpxchg no está disponible? Eso parece estar basado en la información anterior, pero me gustaría estar seguro antes de confiar en él. 🙂

¿O es la alineación requerida por el ISA para garantizar la atomicidad, y solo estoy buscando los lugares incorrectos en los manuales de referencia de Intel?

El PDF del que está haciendo una cita es de 1999 y CLARAMENTE desactualizado.

La documentación actualizada de Intel , específicamente el Volumen-3A, cuenta una historia diferente.

Por ejemplo, en un procesador Core-i7, TODAVÍA tiene que asegurarse de que sus datos no abarquen las líneas de caché, o de lo contrario la operación NO tiene la garantía de ser atómica.

En el Volumen 3A, Progtwigción del sistema, para x86 / x64 Intel establece claramente:

8.1.1 Operaciones atómicas garantizadas

El procesador Intel486 (y los procesadores más nuevos desde entonces) garantiza que las siguientes operaciones básicas de memoria siempre se llevarán a cabo atómicamente:

  • Leer o escribir un byte
  • Leer o escribir una palabra alineada en un límite de 16 bits
  • Leer o escribir una doble palabra alineada en un límite de 32 bits

El procesador Pentium (y los procesadores más nuevos desde entonces) garantiza que las siguientes operaciones adicionales de memoria siempre se llevarán a cabo atómicamente:

  • Leer o escribir una quadword alineada en un límite de 64 bits
  • Accesos de 16 bits a ubicaciones de memoria no guardadas en caché que se ajustan a un bus de datos de 32 bits

Los procesadores de familia P6 (y los procesadores más nuevos desde entonces) garantizan que la siguiente operación de memoria adicional siempre se llevará a cabo atómicamente:

  • Los accesos no alineados de 16, 32 y 64 bits a la memoria en caché que se ajustan a una línea de caché

Los accesos a la memoria cacheable que se dividen entre líneas de caché y límites de página no están garantizados por ser atómicos para Intel Core 2 Duo, Intel® Atom ™, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, familia P6, Pentium y Procesadores Intel486. Los procesadores Intel Core 2 Duo, Intel Atom, Intel Core Duo Duo, Pentium M, Pentium 4, Intel Xeon y P6 proporcionan señales de control de bus que permiten a los subsistemas de memoria externos hacer que los accesos sean atómicos; sin embargo, los accesos de datos no alineados afectarán seriamente el rendimiento del procesador y se deben evitar

x86 no requiere alineación para la instrucción cmpxchg . Sin embargo, se recomienda la alineación para el rendimiento. Esto no debería ser una sorpresa, la compatibilidad con versiones anteriores significa que el software escrito con un manual de hace 14 años todavía se ejecutará en los procesadores de hoy.

Por qué Microsoft requiere exactamente la alineación no está claro en su documentación. Puede ser para rendimiento o para soportar architectures RISC o ambas.

Intel® 64 y IA-32 Architectures Software Developer’s Manual
Volumen 3 (3A): Guía de progtwigción del sistema
enero 2013

8.1.2.2 Bloqueo de bus controlado por software

Para forzar explícitamente la semántica de LOCK, el software puede usar el prefijo LOCK con las siguientes instrucciones cuando se usan para modificar una ubicación de memoria. […]

• Las instrucciones de intercambio (XADD, CMPXCHG y CMPXCHG8B).
• El prefijo LOCK se asume automáticamente para la instrucción XCHG.
• […]

[…] La integridad de un locking de bus no se ve afectada por la alineación del campo de memoria. Se sigue la semántica LOCK para tantos ciclos de bus como sea necesario para actualizar todo el operando. Sin embargo, se recomienda que los accesos bloqueados estén alineados en sus límites naturales para un mejor rendimiento del sistema:

• Cualquier límite para un acceso de 8 bits (bloqueado o no).
• Límite de 16 bits para accesos de palabras bloqueadas.
• Límite de 32 bits para accesos de doble palabra bloqueada.
• Límite de 64 bits para accesos de cuádruple bloqueados.

Vea esta pregunta ASÍ : la alineación natural es importante para el rendimiento, y se requiere en la architecture x64 (por lo tanto, no solo son sistemas PRE-x86, sino POST-x86 también; x64 puede seguir siendo un nicho pero está creciendo en popularidad después de todo ;-); esa puede ser la razón por la cual Microsoft lo documenta según sea necesario (documentos difíciles de encontrar sobre si MS decidió FORZAR el problema de alineación habilitando la verificación de alineación, que puede variar según la versión de Windows; al reclamar en los documentos que se requiere alineación, MS mantiene el libertad para forzarlo en alguna versión de Windows, incluso si no lo forzaron en otros).

Las API de enclavamiento de Microsoft también se aplicaron a ia64 (mientras todavía existía). No había ningún prefijo de locking en ia64, solo las instrucciones cmpxchg.acq y cmpxchg.rel (o fetchadd y otras bestias similares), y todas estas requieren alineación si recuerdo correctamente.