En este sistema hay una serie de puntos clave que condicionan la estructura de procesos adoptada:
El primer asunto entraña un riesgo claro de interbloqueo si un proceso de la unidad de registro intenta enviar una petición a un proceso de una UAD que a su vez trata de enviar un valor crítico al proceso anterior. Como las operaciones de muestrear y de recogida de valores por parte de la unidad de registro son independientes, una posibilidad simple de resolver este problema es asignar procesos diferentes a cada una de dichas operaciones. En nuestra solución hemos denominado a estas tareas Muestreo y Almacen.
Un proceso de la UAD que esté esperando por las órdenes periódicas de muestreo procedentes de la unidad de registro se ejecutará, en principio, al ritmo de la tarea Muestreo. Para garantizar que la frecuencia de lectura del sensor esté desacoplada podemos encargársela a otra tarea de la UAD, que llamaremos Sensor.
Finalmente, puesto que el disco es lento y queremos que la unidad de registro esté siempre lista para recibir lecturas desde las UADs, encargamos la escritura en disco a una tarea Disco que recibirá de Almacen la lista con las mediciones más recientes tras notificar que está libre. Con esto nuestra solución queda así:
Naturalmente, no es la única solución posible, pero cualquier solución válida habrá de tratar los tres problemas mencionados.
A modo de simplificación se ha supuesto que no se distingue entre lecturas procedentes de alarmas y muestras periódicas y que Almacen simplemente conserva el valor más reciente para cada sensor, realizando un volcado a disco cada vez que éste lo permite, independientemente de que se graben varias veces los mismos valores o se machaquen valores aún no volcados (el enunciado garantiza que eso no va a suceder).
A continuación se especifica el código CC-MODULA de las tareas.
TASK Datos(k: CARDINAL); VAR x: TIPOSENNAL; t: BOOLEAN; BEGIN GetChannel(senal[k]); GetChannel(petmuestra[k]); LOOP SELECT WHEN Receive(senal[k],X) DO IF Extrema(X) THEN Send(lectura,HazMuestra(x,k)); WHEN Receive(petmuestra[k],t) DO Send(lectura,hazmuestra(x,k)); END END END Datos;
TASK Muestreo; VAR k: CARDINAL; click: BOOLEAN; BEGIN GetChannel(reloj); LOOP Receive(reloj,click); FOR k:=1 TO TAM DO Send(petmuestra[k],TRUE); END; END END Muestreo;
TASK Sensor(k: CARDINAL); VAR x: TIPOSENNAL; BEGIN LOOP ObtenerSenal(x); Send(senal,x); END END Sensor;
TASK Reloj; BEGIN LOOP Retardo(RETARDO); Send(reloj,TRUE) END END Reloj;
TASK Disco; VAR Inf: TIPOINFORME; BEGIN GetChannel(informe); LOOP Send(petdisco,TRUE); Receive(informe,Inf); EscribeLentisimo(Inf); END END Disco;
TASK Almacen; VAR Muestra: TIPOMUESTRA; INFO: ARRAY [1..TAM] OF TIPOSENNAL; t: BOOLEAN; BEGIN GetChannel(lectura); GetChannel(petdisco); LOOP SELECT WHEN Receive(petdisco,t) DO Send(informe,INFO) WHEN Receive(lectura,Muestra) DO INFO[Muestra.origen]:=Muestra.valor; END END END Almacen;