Accediendo al recurso por diferentes tareas

-1

Tengo una pregunta simple sobre Acceso a los recursos en el concepto de SO (freeRtos). Si se está ejecutando una tarea de baja prioridad y está utilizando el recurso (programación anticipada).

Recurso para LPT (tarea de baja prioridad) y HPT (tarea de alta prioridad)

extern uint8 x;
void func(void)
{ 
  uint8 y = 10 
  if((x - y))
  {

      //Some Code
      x = -1;
      y++; //line 7
  }
 }

Recurso para HPT (tarea de alta prioridad) que se divertirá cada 5 ms

  if(cond)
  {
       func();
  }

si la tarea de baja prioridad ejecuta la línea número 7, en ese momento se ejecuta la tarea de mayor prioridad. Entonces, ¿cuál podría ser el valor de x ?. Esto es un ejemplo. Mi pregunta es si después de ejecutar la línea número 7 con LPT, luego HPT en estado de ejecución el valor de x e y será el mismo que cambió LPT?

    
pregunta user2732944

3 respuestas

1

Técnicamente, mucho depende del sistema que está utilizando, pero se reduce a la intemperie, las instrucciones son de naturaleza "atómica". Si la instrucción es atómica, significa que no se puede interrumpir hasta que se complete. Si la instrucción no es atómica, entonces el comportamiento en el valor de x se vuelve no determinista, por lo que el valor de X se vuelve "quién sabe" para este tipo de situación, puede implementar taskEnterCritical y taskExitCritical que se utilizan para hacer una sección del código atómico en naturaleza. Además, puede considerar el uso de semáforo y / o mutex para implementar acceso mutuamente exclusivo a un recurso.

    
respondido por el Kvegaoro
0

No tengo experiencia con su sistema en particular, pero he visto cómo funcionan estos tipos de sistemas en general. Básicamente, tiene una interrupción que se dispara de vez en cuando, generalmente desde un temporizador, y el ISR decide si simplemente volver de la interrupción a la tarea que interrumpió o si cambiar pilas y luego regresar de la interrupción, por lo tanto tareas.

Entonces, en términos de su situación, lo manejaría como si se llamara a func () tanto desde el bucle principal como desde un ISR, que generalmente es un no-no debido al problema que describió. Se puede hacer, pero es muy fácil desordenar las cosas si no lo haces bien.

Si func () se debe hacer de inmediato, buscaría una manera de bloquear la interrupción del interruptor de tareas para que no se dispare hasta que se haga. Es una especie de pirateo en el sistema operativo para hacer eso, pero resolvería el problema. O si se puede retrasar, establecería una marca para que se haga más tarde y luego la llamaría exclusivamente desde una tarea que no se adelantará.

    
respondido por el AaronD
0

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.

    
respondido por el tcrosley

Lea otras preguntas en las etiquetas