En primer lugar, asumo que la línea # 7 se refiere a la línea x = -1; ya que si cuento siete líneas hacia abajo desde la parte superior, llego a una línea en blanco encima de // Algún código.
Si el nivel base (prioridad baja) está ejecutando esa línea de código y es interrumpido por el ISR que luego se ejecuta, ¿qué sucede con x? Nada inesperado, ya que ambos hilos de ejecución están configurando la variable en -1. En la mayoría de las CPU, hacer esto necesitará dos instrucciones: configurar un registro en -1 y luego almacenarlo en la memoria. Si la interrupción se produce antes de la primera o la segunda instrucción, el ISR establece x en -1 y luego se establece en -1 justo después de que regrese el ISR. Si la interrupción ocurre después de la segunda instrucción, entonces el nivel base ya ha establecido x en -1, y el ISR lo hará nuevamente.
El caso más interesante es la línea y ++;
Suponiendo que una CPU no tiene instrucciones de incremento de memoria, esto normalmente tomará tres instrucciones: cargar un registro desde la memoria, incrementar el registro y volver a almacenar en la memoria.
Tenemos cuatro casos: interrupción antes de la primera instrucción, interrupción después de la primera instrucción (carga), interrupción después de la segunda instrucción (incremento) e interrupción después de la tercera instrucción (almacenamiento).
En el caso donde la interrupción ocurre antes de la primera instrucción, o después de la tercera, es bastante claro que y se incrementará dos veces, pasando de 10 a 12. Sin embargo, en los otros dos casos, y solo se incrementa una vez .
Este es el caso cuando la interrupción ocurre primero (lo mismo si ocurre la última vez):
(int)
ldr y 10
inc 11
str y 11
(rti)
ldr y 11
inc 12
str y 12
En mi notación simple, ldr, inc, y str significa registro de carga, registro de incremento y registro de tienda; y es alguna dirección de memoria, e (int) y (rti) indican dónde se produce la interrupción y el retorno de la interrupción.
Sin embargo, esto es lo que sucede cuando se produce la interrupción después de la primera instrucción:
ldr y 10
(int)
ldr y 10
inc 11
str y 11
(rti)
inc 11
str y 11
Así que y solo se incrementa una vez. Lo mismo cuando se produce la interrupción después del incremento.
Entonces, aunque y ++ es una operación única en C, no es una operación "atómica", se necesitan varias instrucciones de la máquina para ejecutarla. Para protegerse de manera segura contra este tipo de cosas, donde se puede acceder a una variable volátil desde un ISR o desde el nivel base al mismo tiempo, el código debe incluirse en una región crítica. Esto se puede hacer desactivando las interrupciones antes de la (s) línea (s) de código, y habilitándolas nuevamente después.
Tenga en cuenta que este es un argumento para no usar la misma función tanto desde el nivel básico como desde el nivel de interrupción, ya que generalmente no querrá deshabilitar y volver a habilitar las interrupciones dentro de una función llamada por un ISR.