Hacer pthread_mutex_lock y pthread_mutex_unlock funciones llamada memoria cerca/barrera instrucciones? O haga las instrucciones de nivel inferior como comparar_e_intercambiar Implícitamente tienen barreras de memoria?
¿pthread_mutex_lock contiene instrucción de valla de memoria? [duplicate]
Maxim Egorushkin
¿Las funciones pthread_mutex_lock y pthread_mutex_unlock llaman a las instrucciones de valla/barrera de memoria?
Lo hacen, así como la creación de subprocesos.
Tenga en cuenta, sin embargo, que hay dos tipos de barreras de memoria: compilador y hardware.
Las barreras del compilador solo evitan que el compilador reordene lecturas y escrituras y especule valores de variables, pero no evitan que la CPU reordene.
Las barreras de hardware evitan que la CPU reordene las lecturas y escrituras. La cerca de memoria completa suele ser la instrucción más lenta, la mayoría de las veces solo necesita operaciones con semántica de adquisición y liberación (para implementar spinlocks y mutexes).
Con subprocesos múltiples, necesita ambas barreras la mayor parte del tiempo.
Cualquier función cuya definición no esté disponible en esta unidad de traducción (y no sea intrínseca) es una compilador barrera de la memoria pthread_mutex_lock
, pthread_mutex_unlock
, pthread_create
también emita una barrera de memoria de hardware para evitar que la CPU reordene lecturas y escrituras.
De Programación con subprocesos POSIX por David R. Butenhof:
Pthreads proporciona algunas reglas básicas sobre la visibilidad de la memoria. Puede contar con todas las implementaciones del estándar para seguir estas reglas:
Cualesquiera que sean los valores de memoria que un subproceso puede ver cuando llama
pthread_create
también puede ser visto por el nuevo hilo cuando comienza. Cualquier dato escrito en la memoria después de la llamada apthread_create
no necesariamente puede ser visto por el nuevo subproceso, incluso si la escritura se produce antes de que comience el subproceso.Cualquier valor de memoria que un subproceso pueda ver cuando desbloquea una exclusión mutua, ya sea directamente o esperando una variable de condición, también puede ser visto por cualquier subproceso que más tarde bloquee la misma exclusión mutua. Una vez más, los datos escritos después de que se desbloquee la exclusión mutua pueden no ser necesariamente vistos por el subproceso que bloquea la exclusión mutua, incluso si la escritura se produce antes del bloqueo.
Cualesquiera que sean los valores de memoria que un hilo puede ver cuando termina, ya sea por cancelación, regresando de su función de inicio o llamando
pthread_exit
también puede ser visto por el subproceso que se une con el subproceso terminado llamandopthread_join
. Y, por supuesto, es posible que el hilo que se une no vea necesariamente los datos escritos después de que finaliza el subproceso, incluso si la escritura se produce antes de la unión.Cualquier valor de memoria que un subproceso pueda ver cuando señala o transmite una variable de condición también puede ser visto por cualquier subproceso que sea despertado por esa señal o transmisión. Y, una vez más, los datos escritos después de la señal o la transmisión pueden no ser necesariamente vistos por el subproceso que se despierta, incluso si la escritura ocurre antes de que se despierte.
Ver también C++ y más allá de 2012: Herb Sutter – Armas atómicas <> para más detalles.
Kaz
Por favor, eche un vistazo a la sección 4.12 de la especificación POSIX.
Las aplicaciones deben garantizar que el acceso a cualquier ubicación de memoria por parte de más de un subproceso de control (subprocesos o procesos) esté restringido de modo que ningún subproceso de control pueda leer o modificar una ubicación de memoria mientras otro subproceso de control puede estar modificándolo. Dicho acceso está restringido mediante funciones que sincronizan la ejecución de subprocesos. y también sincronizar la memoria con respecto a otros hilos. [emphasis mine]
Luego se proporciona una lista de funciones que sincronizan la memoria, además de algunas notas adicionales.
Si eso requiere instrucciones de barrera de memoria en alguna arquitectura, entonces se deben usar.
Sobre compare_and_swap
: eso no está en POSIX; verifique la documentación para lo que sea que esté usando. Por ejemplo, IBM define un compare_and_swap
función para AIX 5.3. que no tiene semántica de barrera de memoria completa La nota de documentación dice:
Si se usa compare_and_swap como una primitiva de bloqueo, inserte un isync al comienzo de cualquier sección crítica.
De esta documentación podemos adivinar que IBM compare_and_swap
tiene semántica de liberación: ya que la documentación no requiere una barrera para el final de la sección crítica. El procesador de adquisición necesita emitir un isync para asegurarse de que no está leyendo datos obsoletos, pero el procesador de publicación no tiene que hacer nada.
A nivel de instrucción, algunos procesadores tienen comparación e intercambio con ciertas garantías de sincronización, y otros no.
-
Buena referencia a POSIX, no sabía que POSIX especificaba la lista exacta de funciones para eso. +1
– Máximo Egorushkin
10 de junio de 2014 a las 15:24