Barrera de memoria en un solo núcleo ARM
memory-barriers (2)
La CPU solo reordena instrucciones que ya han sido "emitidas", por lo que un cambio de contexto no detendrá ninguna de esas instrucciones que ya están en la tubería, continuarán ejecutándose hasta que se completen.
Es poco probable que para cuando el cambio de contexto haya finalizado, alguna de esas instrucciones quede por completar. Un cambio de contexto generalmente guarda el estado de todos los registros, creando así una dependencia de cada instrucción que está modificando un registro para completar primero.
Sin embargo, incluso para la improbable situación de que las instrucciones reordenadas aún se ejecuten después del cambio de contexto, posiblemente un almacenamiento de memoria, la CPU asegura que da la apariencia del software que las instrucciones ejecutan en el orden correcto. Entonces, como el segundo hilo intenta acceder a los datos compartidos, la CPU se asegurará de que se hayan completado las instrucciones necesarias antes de permitir la ejecución de las instrucciones dependientes.
La situación de núcleos múltiples es realmente un caso de mantener el orden de las escrituras en el caché / memoria para que los otros núcleos vean que los cambios ocurren en el orden correcto. Una barrera de memoria solo es necesaria para esto.
Hay mucha información relacionada con las barreras de la memoria. La mayoría de la información se refiere a arquitecturas multinúcleo o multiprocesador. En algún lugar aquí en Stackoverflow también se afirma que las barreras de memoria no son necesarias en los procesadores de núcleo único.
Hasta el momento no puedo encontrar una explicación clara de por qué no debería ser requerida en CPU de un solo núcleo. Supongamos que una carga y una tienda se reordenan en el subproceso A y se produce un cambio de contexto entre ambas instrucciones. En este caso, el hilo B podría reaccionar no como se esperaba. ¿Por qué un contexto cambiar en un solo núcleo se comportaría de manera diferente en comparación con 2 hilos en diferentes núcleos? (excepto cualquier problema de coherencia de caché)
Por ejemplo, alguna información del sitio web de ARM:
"Está definido arquitectónicamente que el software debe realizar una operación de barrera de memoria de datos (DMB): • entre adquirir un recurso, por ejemplo, mediante el bloqueo de un mutex (MUTual EXclusion) o la reducción de un semáforo, y hacer cualquier acceso a ese recurso • antes de realizar un recurso disponible, por ejemplo, desbloqueando un mutex o incrementando un semáforo "
Esto suena muy claro, sin embargo, en el ejemplo proporcionado se refieren explícitamente a una configuración multinúcleo.
¿Por qué un contexto cambiar en un solo núcleo se comportaría de manera diferente en comparación con 2 hilos en diferentes núcleos? (excepto cualquier problema de coherencia de caché)
Los hilos en núcleos separados pueden actuar exactamente al mismo tiempo. Aún tienes problemas en un solo núcleo.
En algún lugar aquí en también se afirma que las barreras de memoria no son necesarias en los procesadores de núcleo único.
Esta información tal vez se toma fuera de contexto (o no proporciona suficiente contexto).
Las páginas de barrera de memoria y ordenación de memoria de Wikipedia tienen secciones de ejecución fuera de orden frente a optimizaciones de reorganización del compilador y compilación de tiempo / tiempo de ejecución . Hay muchos lugares en una tubería donde el orden de la memoria puede ser importante. En algunos casos, esto puede ser resuelto por el compilador, el SO o nuestro propio código.
Las barreras de memoria del compilador se aplican a una sola CPU. Son especialmente útiles con hardware donde importan el orden y el tiempo de escrituras y lecturas.
Linux define algunos tipos más de barreras de memoria ,
- Escribir / Almacenar
- Dependencia de datos.
- Leer / Cargar.
- Barreras generales de memoria.
Principalmente, estos mapas se ajustan bastante bien a DMB
( DSB
e IMB
son más para la modificación del código).
Cuantos más avances, las CPU ARM tienen múltiples unidades de carga / almacenamiento. En teoría, un conmutador de subprocesamiento no preventivo Note1 (especialmente con memoria alias) podría causar algún problema con una aplicación de CPU única multiproceso . Sin embargo, sería bastante difícil construir este caso.
En su mayor parte, la CPU maneja un buen orden de memoria mediante instrucciones de programación. Un caso común en el que sí importa con una sola CPU es que los programadores a nivel del sistema CP15
registros CP15
. Por ejemplo, se debe emitir una ISB
al encender la MMU. Lo mismo puede ser cierto para ciertos registros de hardware / dispositivo. Finalmente, un cargador de programa necesitará barreras así como operaciones de caché, incluso en sistemas de CPU individuales.
UnixSmurf escribió estos blogs sobre el orden de acceso a la memoria ,
El tema es complejo y debe ser específico sobre los tipos de barreras que está discutiendo.
Nota 1: digo no preventivo, como si ocurriera una interrupción, la CPU única probablemente se asegurará de que se completen todas las solicitudes de memoria pendientes. Con un interruptor no preventivo , haces algo como longjmp
para cambiar los hilos. En teoría, podría cambiar contextos antes de que todas las escrituras se hayan completado. El sistema solo necesitaría un DMB
en el yield()
para evitarlo.